Compare commits

...

56 Commits

Author SHA1 Message Date
752b1df659 shell-app: Add discrete GPU support for NVidia drivers
Add the necessary environment variables that would make offloading to
the NVidia "secondary" drivers work as expected.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1810
2019-10-24 14:49:22 +02:00
366b06716d appDisplay: Respect X-KDE-RunOnDiscreteGpu appInfo property
When X-KDE-RunOnDiscreteGpu is set in the application's .desktop file,
launch the application on the discrete GPU if available, and offer
to launch on the discrete GPU manually otherwise.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1804
2019-10-24 14:44:40 +02:00
4d47b16d33 shell-app: Respect X-KDE-RunOnDiscreteGpu when launching apps
If whether to launch on the discrete GPU or the integrated one isn't
passed down to us, check whether the application prefers to be launched
on the discrete GPU.

See: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1804
2019-10-24 14:44:40 +02:00
6526e9edf6 appDisplay: Remove unimplemented 'activate-discrete-gpu'
It was added in commit 009d021 but not advertised, and likely not used
by an application since then.

See: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1804
2019-10-24 14:22:51 +02:00
055c007ac2 dnd: Skip drag target when its acceptDrop() throws an exception
In the case of bugs in a drag target's acceptDrop() function, it may
throw an exception. In the previous code, this would break out of the
loop entirely and never cancel the drag, so the mouse button release
event would be ignored and you would have to press Esc to get out of the
drag.

In this change, if acceptDrop() throws an exception, we log it and move
on to the next parent target instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/777
2019-10-22 18:08:10 -07:00
43cf466d09 js: Replace Clutter.Actor.get_allocation_geometry()
The function was deprecated and has now been dropped from mutter.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/776
2019-10-21 18:41:35 +02:00
6965781d59 st: Use clutter_actor_pick() in pick
Use the new function to perform picking and avoid
going through any painting-related code paths.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/773
2019-10-21 13:53:56 +00:00
80680803aa Update Persian translation 2019-10-19 15:16:39 +00:00
51601f3ead Update shotwell desktop file name references
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/774
2019-10-18 16:50:57 +02:00
b25a73c243 authPrompt: Wiggle on failure
Add a wiggle effect to the password entry on failure. The
parameters are set as per design review during GNOME Shell
Hackfest 2019.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/768
2019-10-18 11:25:45 +00:00
d0690c3952 util: Add wiggle helper
Add Util.wiggle(), which accepts the wiggle offset, duration,
and number of times, as parameters.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/768
2019-10-18 11:25:45 +00:00
f2466caef3 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.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/768
2019-10-18 11:25:45 +00:00
b1d22d2058 search: Drop SearchResultInterface again
It adds a significant cost to AppIcons which are used
 - quite a log (depending on installed apps)
 - in preformance-sensitive contexts (spring animation)

Just rely on duck typing and revert 91a5133116.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1799
2019-10-17 15:56:07 +00:00
6f7e5976e2 Update Friulian translation 2019-10-17 13:54:18 +00:00
29543f369f Update Croatian translation 2019-10-17 12:08:58 +00:00
a144a1c76d workspace: Use graphene instead of clutter
This was forgotten after the graphene type port landed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/770
2019-10-17 11:31:59 +02:00
d91927674d workspace: Sort windows in overview grid using cached center
When accessing properties on ClutterActor for size and position there is
a notable access time overhead. This overhead adds considerable user lag
when opening the overview if many windows are open.

This is primarily due to these properties being accessed while sorting
WindowClone instances by their window's center for placement in the
overview. By pre-computing this center value only once when
initializing WindowClone, the induced lag can be significantly reduced.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/763
2019-10-17 07:27:59 +00:00
d12cd12e1b ci: Make run-eslint more convenient for local use
The script can be helpful outside of CI, in particular for gradually
transitioning to the new style.

Reverting commit f00201fa6c it is already possible to do something
like

 $ CI_MERGE_REQUEST_PROJECT_URL=https://gitlab.gnome.org/GNOME/gnome-shell \
   CI_MERGE_REQUEST_TARGET_BRANCH_NAME=master CI_COMMIT_SHA=HEAD \
   .gitlab-ci/run-eslint.sh

but that is hardly convenient.

Instead, allow passing the required parameters on the command line:

 $ .gitlab-ci/run-eslint.sh origin master

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/730
2019-10-16 15:37:12 +00:00
caa50dc1a3 ci: Ensure eslint output exists
We are a long time away from an error-free eslint run,
but when we get there eventually, let's not trip over
non-existent files ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/730
2019-10-16 15:37:12 +00:00
55b57421dc cleanup: Replace signal connections with virtual functions
Inheriting from actors allows to use virtual functions instead of signal
connections for multiple cases, so just use them when possible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
320df13b65 st/button: Add the clicked button to virtual function signature
clicked signal includes a clicked mouse button parameter, but the vfunc
signature doesn't include it, so it won't be passed to the functions when
the signal is emitted.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
e4920b2f80 pageIndicators: Use Clutter.Orientation as orientation parameter
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
c9fbae3408 docs: Update actor and delegate_ paragraph in HACKING
Deprecate the usage of the `actor` property, while keep the `_delegate` part
as it is needed for DnD for now.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
a3c6217875 overview: Make public properties read-only
Overview's animationInProgress, visible and visibleTarget properties are not
meant to be modified from others, but be read only.

So make this clearer using properties getters and private values.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
db7726c5bf avatar: Use Property bindings to sync reactivity
Instead of manually updating properties on change, use native properties
bindings to keep the them synchronized.

Disable hover-tracking and focus-ability when the avatar is not sensitive.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
0b91dee5a9 windowManager: Inherit WindowDimmer from Clutter.BrightnessContrastEffect
As result add the effect to the actor on the caller function.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
3838220961 calendarMessageList: Remove sections map and use clutter children
Now that the calendar message list and the message sections are actors, there's
no need to keep track of the sections in a different Map as we can just use the
native clutter functions to manage the children and access to their properties.

Also cleanup the signal connection/disconnection.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
9bb12f6f87 messageList: Use St.Bin as message container and use clutter to manage the list
When messages are added to the message list, we create a container for those,
however since now the messages are actor themselves we can just create a list
item actor that holds the message actor and refer to the message parent in order
to get their container.

This allows to remove the obj container map we used, using the native clutter
parent-child hierarchy and handle signal connections cleanly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
4dea1f801a lookingGlass: Use resultsArea to keep track of results
Now that results are actors we can just use their container to keep
track of them

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
91a5133116 search: Define SearchResultInterface and implement valid results with it
Since all the search result classes are now GObject classes, we can enforce
the methods we want to have in there (just activate() for now) using an
interface, to make sure they are implementing what we require and to easily
group all the classes that can be used as search results, even though they
are not extending SearchResult.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
c4c5c4fd5c cleanup: Use inheritance for Actor classes instead of composition
Remove the `this.actor = ...` and `this.actor._delegate = this` patterns in most
of classes, by inheriting all the actor container classes.

Uses interfaces when needed for making sure that multiple classes will implement
some required methods or to avoid redefining the same code multiple times.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
f67b409fc1 screenshot: Pass a Graphene.Point as PickPixel 'finished' signal
This will allow to pass the data as native object when porting this to Clutter
actor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
22fe4e92c7 screenshot: Return a Meta.Rectangle as geometry
Since the geometry is used as a signal parameter, this can't be used when using
a GObject based class, so use the Meta boxed type instead of a JS object.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
91eb84fa4e overview: Add OverviewActor and use as main actor of the Overlay
Use the Overview class as controller, while create the actual overlay actor
using a GObject-derived class.

Replace actual properties with getter-only properties.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
4e1492c926 messageTray: Dispose Source on destruction
Dispose the Source Object when dispose() is called, avoiding that it could be
called twice on a destroyed Source.

So, notify count changes before destroying the object, and don't emit this
twice on destroyNonResidentNotifications (as if a notification is destroyed
the property notify will happen in the notification destroy callback anyways).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:13 +00:00
ed97f61750 messageTray: Dispose Notification on destroy
When the notification is destroyed we should also dispose the underneath GLib
object, and ensure that we don't dispose this twice.

In order to avoid this, don't destroy transient notifications that have been
already been removed and only destroy the resident notifications on activation
if they have not been destroyed earlier.
Thus connect after to the 'activated' signal and once the default handler has
been called destroy the notification if not requested earlier.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
b5676a2a5c messageTray: Inherit Notification, Source and NotificationPolicy from GObject
Register notifications, sources and policies as GObject gtypes so that they can
be passed in signals and use native properties and signals.

Reimplement all the extending classes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
7059dcced3 keyboard: Add KeyboardManager to manage the lifetime of the keyboard actor
The Keyboard class used to be both a view and controller class, however in order
to make the keyboard a native Clutter.Actor, we need to separate the widget from
the controller class, so that we can manage the actor lifetime from the JS side.

Thus, initialize the keyboard actor on the Keyboard constructor and create a
KeyboardManager class to manage its state and lifetime.

Add proxy methods for the public functions that were used by other shell
components

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
c7e0c7eb79 background: Rename Background 'changed' signal to 'bg-changed'
Meta.Background has already a 'changed' signal and not to confuse the source
signal with the wrapper one, rename the wrapper class signal into 'bg-changed'.

This will be relevant when we'll inherit from Meta.Background, as signal
emissions from the base class could interfere with the wanted derived class
behavior and with the the grouping of successive changes into a single ::change
emission.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
ff775213a5 calendar: Use GDateTime for selected-date-changed signal
Since GObject derived classes can't use JS objects as signal parameters, let's
go native and use GLib.DateTime instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
7f9c709c85 appDisplay: Use an St.Widget as base actor for FolderView
This is needed to make possible to convert BaseAppView into a St.Widget so that
all views can inherit from it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
74d7d3e259 animation: Don't sync animation sizes on change
When the actor size changes, we might incur into an allocation cycle.

This was introduced by commit b6ec02ce, but when the animation will be an actor
itself, there will be no need to update the children size on actor size update,
as this will be managed by the actor allocation cycle itself.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1384
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
0353a5bf2c cleanup: Rename signals/methods that will conflict with Clutter.Actor
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-10-16 15:26:12 +00:00
ab6a629955 screenShield: Compute lock timeout fade duration using animation settings
When the screen is marked as idle, we normally start a fading animation and
a timeout to finally lock the screen. This timeout is configured using the
fade time if no longer delay is set in settings.

However if animations are disabled or slowed-down/up, the fade time is
different from the STANDARD_FADE_TIME and so we might end up showing the
lock shield without actually locking for STANDARD_FADE_TIME in the disabled
or slowed-up animations case, or locking too early in case of slowed-down
animations.

So, just adjust the timeout time using the same logic of animations so that
this value is matching all the times.

Related to https://gitlab.gnome.org/GNOME/gnome-shell/issues/1744

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/749
2019-10-16 15:20:58 +00:00
6cad251187 volume: Show indicator when microphone is active
Devices like cameras and microphones are privacy sensitive, as they can
be used to spy on the user. We cannot prevent non-sandboxed apps from
doing that, but as we already track when the microphone is recording,
we can at least show an indicator to make sure it doesn't happen behind
the user's back.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/729
2019-10-16 13:08:20 +00:00
d7c569c692 st: Remove color from ClutterActor pick virtual function
It's unused since commit mutter@14c706e51

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/759
2019-10-16 12:01:41 +00:00
0615370930 Replace Clutter.Point by Graphene.Point
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/421
2019-10-16 10:49:04 +00:00
7a92a9ba21 st: Replace ClutterSize by graphene_size_t
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/421
2019-10-16 10:49:04 +00:00
0199857c5b Replace ClutterVertex by graphene_point3d_t
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/421
2019-10-16 10:49:04 +00:00
59e3a1a816 doap: Clean up list of maintainers
Move historic entries from "maintainers" to "authors" to reflect
current reality :-(
2019-10-16 12:47:05 +02:00
6533690fff search: Activate SearchResult from the result itself
Search result views can include also objects that are not inheriting from
SearchResults (such as the AppIcon) that has not any 'activate' signal, to
connect to. Since we want to enforce a more formal interface, we want to
have just a simpler requirement as an activate() method.

So, instead using the 'activate' signal in SearchResult to activate a result
via SearchResultsBase just implement activate() in the result.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/765
2019-10-16 12:27:49 +02:00
d0d1845bb6 search: Rename SearchResults to SearchResultsView
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/765
2019-10-16 11:52:55 +02:00
20f4fc7c87 shell-screenshots: Do not pass a clip for window screenshots
Design team wants us not to clip away the shadows, lets do that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/762
2019-10-14 17:56:01 +02:00
b4128967a1 st/scroll-view: Remove container foreach vfunc
foreach_with_internals vfunc is deprecated for long time and not used
anymore, so remove it

Related to: https://gitlab.gnome.org/GNOME/mutter/merge_requests/816

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/747
2019-10-14 14:57:49 +00:00
38ad1d7c13 environment: Only disable unredirection of ongoing transitions
When a transition is set up with a delay, it may be removed before it
actually started. We won't get a ::stopped signal in that case, with
the result that we currently end up with a mismatched unredirection
disabling.

Address this by only disable unredirection once the transition has
actually started.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1788
2019-10-14 10:47:36 +02:00
f78136182f Updated Spanish translation 2019-10-14 09:15:23 +02:00
94 changed files with 4424 additions and 3760 deletions

View File

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

View File

@ -186,15 +186,27 @@ and "double quotes" for strings that the user may see. This allows us to
quickly find untranslated or mistranslated strings by grepping through the quickly find untranslated or mistranslated strings by grepping through the
sources for double quotes without a gettext call around them. sources for double quotes without a gettext call around them.
## `actor` and `_delegate` ## `actor` (deprecated) and `_delegate`
gjs allows us to set so-called "expando properties" on introspected objects, 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 allowing us to treat them like any other. Because the Shell was built before
you could inherit from GTypes natively in JS, we usually have a wrapper class you could inherit from GTypes natively in JS, in some cases we have a wrapper
that has a property called `actor`. We call this wrapper class the "delegate". class that has a property called `actor` (now deprecated). We call this
wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on We sometimes use expando properties to set a property called `_delegate` on
the actor itself: 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 ```javascript
var MyClass = class { var MyClass = class {
constructor() { constructor() {
@ -215,6 +227,7 @@ delegate object from an associated actor. For instance, the drag and drop
system calls the `handleDragOver` function on the delegate of a "drop target" 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` 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. 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 ## Functional style

View File

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

View File

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

View File

@ -1,11 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AuthPrompt */
const { Clutter, Pango, Shell, St } = imports.gi; const { Clutter, GObject, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Util = imports.misc.util;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
@ -16,6 +17,10 @@ var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500; var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
const WIGGLE_OFFSET = 6;
const WIGGLE_DURATION = 65;
const N_WIGGLES = 3;
var AuthPromptMode = { var AuthPromptMode = {
UNLOCK_ONLY: 0, UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1 UNLOCK_OR_LOG_IN: 1
@ -33,8 +38,21 @@ var BeginRequestType = {
DONT_PROVIDE_USERNAME: 1 DONT_PROVIDE_USERNAME: 1
}; };
var AuthPrompt = class { var AuthPrompt = GObject.registerClass({
constructor(gdmClient, mode) { 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
});
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient; this._gdmClient = gdmClient;
@ -67,38 +85,33 @@ var AuthPrompt = class {
} }
}); });
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout', this.connect('destroy', this._onDestroy.bind(this));
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._userWell = new St.Bin({ x_fill: true, this._userWell = new St.Bin({ x_fill: true, x_align: St.Align.START });
x_align: St.Align.START }); this.add(this._userWell, {
this.actor.add(this._userWell, x_align: St.Align.START,
{ x_align: St.Align.START,
x_fill: true, x_fill: true,
y_fill: true, y_fill: true,
expand: true }); expand: true
});
this._label = new St.Label({ style_class: 'login-dialog-prompt-label' }); this._label = new St.Label({ style_class: 'login-dialog-prompt-label' });
this.actor.add(this._label, this.add(this._label, {
{ expand: true, expand: true,
x_fill: false, x_fill: false,
y_fill: true, y_fill: true,
x_align: St.Align.START }); x_align: St.Align.START
});
this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry', this._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true }); can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE }); ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
this.actor.add(this._entry, this.add(this._entry, {
{ expand: true, expand: true,
x_fill: true, x_fill: true,
y_fill: false, y_fill: false,
x_align: St.Align.START }); x_align: St.Align.START
});
this._entry.grab_key_focus(); this._entry.grab_key_focus();
@ -106,14 +119,15 @@ var AuthPrompt = class {
styleClass: 'login-dialog-message' }); styleClass: 'login-dialog-message' });
this._message.clutter_text.line_wrap = true; this._message.clutter_text.line_wrap = true;
this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START }); this.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box', this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
vertical: false }); vertical: false });
this.actor.add(this._buttonBox, this.add(this._buttonBox, {
{ expand: true, expand: true,
x_align: St.Align.MIDDLE, x_align: St.Align.MIDDLE,
y_align: St.Align.END }); y_align: St.Align.END
});
this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() }); this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._defaultButtonWellActor = null; this._defaultButtonWellActor = null;
@ -121,9 +135,9 @@ var AuthPrompt = class {
this._initButtons(); this._initButtons();
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE); this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.actor.opacity = 0; this._spinner.opacity = 0;
this._spinner.actor.show(); this._spinner.show();
this._defaultButtonWell.add_child(this._spinner.actor); this._defaultButtonWell.add_child(this._spinner);
} }
_onDestroy() { _onDestroy() {
@ -131,6 +145,12 @@ var AuthPrompt = class {
this._userVerifier = null; this._userVerifier = null;
} }
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
}
_initButtons() { _initButtons() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button', this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
@ -241,6 +261,12 @@ var AuthPrompt = class {
this.updateSensitivity(canRetry); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
Util.wiggle(this._entry, {
offset: WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
wiggleCount: N_WIGGLES,
});
} }
_onVerificationComplete() { _onVerificationComplete() {
@ -269,13 +295,13 @@ var AuthPrompt = class {
oldActor.remove_all_transitions(); oldActor.remove_all_transitions();
let wasSpinner; let wasSpinner;
if (oldActor == this._spinner.actor) if (oldActor == this._spinner)
wasSpinner = true; wasSpinner = true;
else else
wasSpinner = false; wasSpinner = false;
let isSpinner; let isSpinner;
if (actor == this._spinner.actor) if (actor == this._spinner)
isSpinner = true; isSpinner = true;
else else
isSpinner = false; isSpinner = false;
@ -323,7 +349,7 @@ var AuthPrompt = class {
} }
startSpinning() { startSpinning() {
this.setActorInDefaultButtonWell(this._spinner.actor, true); this.setActorInDefaultButtonWell(this._spinner, true);
} }
stopSpinning() { stopSpinning() {
@ -404,9 +430,9 @@ var AuthPrompt = class {
this._entry.clutter_text.editable = sensitive; this._entry.clutter_text.editable = sensitive;
} }
hide() { vfunc_hide() {
this.setActorInDefaultButtonWell(null, true); this.setActorInDefaultButtonWell(null, true);
this.actor.hide(); super.vfunc_hide();
this._message.opacity = 0; this._message.opacity = 0;
this.setUser(null); this.setUser(null);
@ -422,7 +448,7 @@ var AuthPrompt = class {
if (user) { if (user) {
let userWidget = new UserWidget.UserWidget(user); let userWidget = new UserWidget.UserWidget(user);
this._userWell.set_child(userWidget.actor); this._userWell.set_child(userWidget);
} }
} }
@ -507,5 +533,4 @@ var AuthPrompt = class {
this.reset(); this.reset();
this.emit('cancelled'); this.emit('cancelled');
} }
}; });
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@ -19,7 +19,6 @@
const { AccountsService, Atk, Clutter, Gdm, Gio, const { AccountsService, Atk, Clutter, Gdm, Gio,
GLib, GObject, Meta, Pango, Shell, St } = imports.gi; GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const AuthPrompt = imports.gdm.authPrompt; const AuthPrompt = imports.gdm.authPrompt;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
@ -39,36 +38,35 @@ const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 48; const _LOGO_ICON_HEIGHT = 48;
const _MAX_BOTTOM_MENU_ITEMS = 5; const _MAX_BOTTOM_MENU_ITEMS = 5;
var UserListItem = class { var UserListItem = GObject.registerClass({
constructor(user) { GTypeName: 'LoginDialog_UserListItem',
this.user = user; Signals: { 'activate': {} }
this._userChangedId = this.user.connect('changed', }, class UserListItem extends St.Button {
this._onUserChanged.bind(this)); _init(user) {
let layout = new St.BoxLayout({ vertical: true }); let layout = new St.BoxLayout({ vertical: true });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', super._init({
style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true, can_focus: true,
child: layout, child: layout,
reactive: true, reactive: true,
x_align: St.Align.START, x_align: St.Align.START,
x_fill: true }); x_fill: true
this.actor.connect('destroy', this._onDestroy.bind(this)); });
this.actor.connect('key-focus-in', () => { this.user = user;
this._setSelected(true); this._userChangedId = this.user.connect('changed',
}); this._onUserChanged.bind(this));
this.actor.connect('key-focus-out', () => {
this._setSelected(false); this.connect('destroy', this._onDestroy.bind(this));
}); this.connect('notify::hover', () => {
this.actor.connect('notify::hover', () => { this._setSelected(this.hover);
this._setSelected(this.actor.hover);
}); });
this._userWidget = new UserWidget.UserWidget(this.user); this._userWidget = new UserWidget.UserWidget(this.user);
layout.add(this._userWidget.actor); layout.add(this._userWidget);
this._userWidget.actor.bind_property('label-actor', this.actor, 'label-actor', this._userWidget.bind_property('label-actor', this, 'label-actor',
GObject.BindingFlags.SYNC_CREATE); GObject.BindingFlags.SYNC_CREATE);
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
@ -76,35 +74,44 @@ var UserListItem = class {
visible: false }); visible: false });
layout.add(this._timedLoginIndicator); layout.add(this._timedLoginIndicator);
this.actor.connect('clicked', this._onClicked.bind(this));
this._onUserChanged(); 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() { _onUserChanged() {
this._updateLoggedIn(); this._updateLoggedIn();
} }
_updateLoggedIn() { _updateLoggedIn() {
if (this.user.is_logged_in()) if (this.user.is_logged_in())
this.actor.add_style_pseudo_class('logged-in'); this.add_style_pseudo_class('logged-in');
else else
this.actor.remove_style_pseudo_class('logged-in'); this.remove_style_pseudo_class('logged-in');
} }
_onDestroy() { _onDestroy() {
this.user.disconnect(this._userChangedId); this.user.disconnect(this._userChangedId);
} }
_onClicked() { vfunc_clicked() {
this.emit('activate'); this.emit('activate');
} }
_setSelected(selected) { _setSelected(selected) {
if (selected) { if (selected) {
this.actor.add_style_pseudo_class('selected'); this.add_style_pseudo_class('selected');
this.actor.grab_key_focus(); this.grab_key_focus();
} else { } else {
this.actor.remove_style_pseudo_class('selected'); this.remove_style_pseudo_class('selected');
} }
} }
@ -145,23 +152,30 @@ var UserListItem = class {
this._timedLoginIndicator.visible = false; this._timedLoginIndicator.visible = false;
this._timedLoginIndicator.scale_x = 0.; this._timedLoginIndicator.scale_x = 0.;
} }
}; });
Signals.addSignalMethods(UserListItem.prototype);
var UserList = class { var UserList = GObject.registerClass({
constructor() { GTypeName: 'LoginDialog_UserList',
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' }); Signals: {
this.actor.set_policy(St.PolicyType.NEVER, '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' });
this.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC); St.PolicyType.AUTOMATIC);
this._box = new St.BoxLayout({ vertical: true, this._box = new St.BoxLayout({ vertical: true,
style_class: 'login-dialog-user-list', style_class: 'login-dialog-user-list',
pseudo_class: 'expanded' }); pseudo_class: 'expanded' });
this.actor.add_actor(this._box); this.add_actor(this._box);
this._items = {}; this._items = {};
}
this.actor.connect('key-focus-in', this._moveFocusToItems.bind(this)); vfunc_key_focus_in() {
this._moveFocusToItems();
} }
_moveFocusToItems() { _moveFocusToItems() {
@ -170,10 +184,10 @@ var UserList = class {
if (!hasItems) if (!hasItems)
return; return;
if (global.stage.get_key_focus() != this.actor) if (global.stage.get_key_focus() != this)
return; return;
let focusSet = this.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false); let focusSet = this.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
if (!focusSet) { if (!focusSet) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._moveFocusToItems(); this._moveFocusToItems();
@ -194,14 +208,14 @@ var UserList = class {
for (let userName in this._items) { for (let userName in this._items) {
let item = this._items[userName]; let item = this._items[userName];
item.actor.sync_hover(); item.sync_hover();
} }
} }
scrollToItem(item) { scrollToItem(item) {
let box = item.actor.get_allocation_box(); let box = item.get_allocation_box();
let adjustment = this.actor.get_vscroll_bar().get_adjustment(); let adjustment = this.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
adjustment.ease(value, { adjustment.ease(value, {
@ -211,9 +225,9 @@ var UserList = class {
} }
jumpToItem(item) { jumpToItem(item) {
let box = item.actor.get_allocation_box(); let box = item.get_allocation_box();
let adjustment = this.actor.get_vscroll_bar().get_adjustment(); let adjustment = this.get_vscroll_bar().get_adjustment();
let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0); let value = (box.y1 + adjustment.step_increment / 2.0) - (adjustment.page_size / 2.0);
@ -251,14 +265,14 @@ var UserList = class {
this.removeUser(user); this.removeUser(user);
let item = new UserListItem(user); let item = new UserListItem(user);
this._box.add(item.actor, { x_fill: true }); this._box.add(item, { x_fill: true });
this._items[userName] = item; this._items[userName] = item;
item.connect('activate', this._onItemActivated.bind(this)); item.connect('activate', this._onItemActivated.bind(this));
// Try to keep the focused item front-and-center // Try to keep the focused item front-and-center
item.actor.connect('key-focus-in', () => this.scrollToItem(item)); item.connect('key-focus-in', () => this.scrollToItem(item));
this._moveFocusToItems(); this._moveFocusToItems();
@ -279,33 +293,38 @@ var UserList = class {
if (!item) if (!item)
return; return;
item.actor.destroy(); item.destroy();
delete this._items[userName]; delete this._items[userName];
} }
numItems() { numItems() {
return Object.keys(this._items).length; return Object.keys(this._items).length;
} }
}; });
Signals.addSignalMethods(UserList.prototype);
var SessionMenuButton = class { var SessionMenuButton = GObject.registerClass({
constructor() { GTypeName: 'LoginDialog_SessionMenuButton',
Signals: { 'session-activated': { param_types: [GObject.TYPE_STRING] } }
}, class SessionMenuButton extends St.Bin {
_init() {
let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' }); let gearIcon = new St.Icon({ icon_name: 'emblem-system-symbolic' });
this._button = new St.Button({ style_class: 'login-dialog-session-list-button', let button = new St.Button({
style_class: 'login-dialog-session-list-button',
reactive: true, reactive: true,
track_hover: true, track_hover: true,
can_focus: true, can_focus: true,
accessible_name: _("Choose Session"), accessible_name: _("Choose Session"),
accessible_role: Atk.Role.MENU, accessible_role: Atk.Role.MENU,
child: gearIcon }); child: gearIcon
});
this.actor = new St.Bin({ child: this._button }); super._init({ child: button });
this._button = button;
let side = St.Side.TOP; let side = St.Side.TOP;
let align = 0; let align = 0;
if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) { if (Gdm.get_session_ids().length > _MAX_BOTTOM_MENU_ITEMS) {
if (this.actor.text_direction == Clutter.TextDirection.RTL) if (this.text_direction == Clutter.TextDirection.RTL)
side = St.Side.RIGHT; side = St.Side.RIGHT;
else else
side = St.Side.LEFT; side = St.Side.LEFT;
@ -384,15 +403,13 @@ var SessionMenuButton = class {
}); });
} }
} }
}; });
Signals.addSignalMethods(SessionMenuButton.prototype);
var LoginDialog = GObject.registerClass({ var LoginDialog = GObject.registerClass({
Signals: { 'failed': {} }, Signals: { 'failed': {} },
}, class LoginDialog extends St.Widget { }, class LoginDialog extends St.Widget {
_init(parentActor) { _init(parentActor) {
super._init({ style_class: 'login-dialog', super._init({ style_class: 'login-dialog', visible: false });
visible: false });
this.get_accessible().set_role(Atk.Role.WINDOW); this.get_accessible().set_role(Atk.Role.WINDOW);
@ -426,7 +443,7 @@ var LoginDialog = GObject.registerClass({
this.add_child(this._userSelectionBox); this.add_child(this._userSelectionBox);
this._userList = new UserList(); this._userList = new UserList();
this._userSelectionBox.add(this._userList.actor, this._userSelectionBox.add(this._userList,
{ expand: true, { expand: true,
x_fill: true, x_fill: true,
y_fill: true }); y_fill: true });
@ -435,7 +452,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.connect('prompted', this._onPrompted.bind(this)); this._authPrompt.connect('prompted', this._onPrompted.bind(this));
this._authPrompt.connect('reset', this._onReset.bind(this)); this._authPrompt.connect('reset', this._onReset.bind(this));
this._authPrompt.hide(); this._authPrompt.hide();
this.add_child(this._authPrompt.actor); this.add_child(this._authPrompt);
// translators: this message is shown below the user list on the // translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for // login screen. It can be activated to reveal an entry for
@ -494,9 +511,9 @@ var LoginDialog = GObject.registerClass({
(list, sessionId) => { (list, sessionId) => {
this._greeter.call_select_session_sync (sessionId, null); this._greeter.call_select_session_sync (sessionId, null);
}); });
this._sessionMenuButton.actor.opacity = 0; this._sessionMenuButton.opacity = 0;
this._sessionMenuButton.actor.show(); this._sessionMenuButton.show();
this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton.actor); this._authPrompt.addActorToDefaultButtonWell(this._sessionMenuButton);
this._disableUserList = undefined; this._disableUserList = undefined;
this._userListLoaded = false; this._userListLoaded = false;
@ -579,8 +596,8 @@ var LoginDialog = GObject.registerClass({
let authPromptAllocation = null; let authPromptAllocation = null;
let authPromptWidth = 0; let authPromptWidth = 0;
if (this._authPrompt.actor.visible) { if (this._authPrompt.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor); authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt);
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1; authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
} }
@ -690,7 +707,7 @@ var LoginDialog = GObject.registerClass({
} }
if (authPromptAllocation) if (authPromptAllocation)
this._authPrompt.actor.allocate(authPromptAllocation, flags); this._authPrompt.allocate(authPromptAllocation, flags);
if (userSelectionAllocation) if (userSelectionAllocation)
this._userSelectionBox.allocate(userSelectionAllocation, flags); this._userSelectionBox.allocate(userSelectionAllocation, flags);
@ -794,7 +811,7 @@ var LoginDialog = GObject.registerClass({
_onPrompted() { _onPrompted() {
if (this._shouldShowSessionMenuButton()) { if (this._shouldShowSessionMenuButton()) {
this._sessionMenuButton.updateSensitivity(true); this._sessionMenuButton.updateSensitivity(true);
this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton.actor); this._authPrompt.setActorInDefaultButtonWell(this._sessionMenuButton);
} else { } else {
this._sessionMenuButton.updateSensitivity(false); this._sessionMenuButton.updateSensitivity(false);
} }
@ -854,11 +871,11 @@ var LoginDialog = GObject.registerClass({
} }
_showPrompt() { _showPrompt() {
if (this._authPrompt.actor.visible) if (this._authPrompt.visible)
return; return;
this._authPrompt.actor.opacity = 0; this._authPrompt.opacity = 0;
this._authPrompt.actor.show(); this._authPrompt.show();
this._authPrompt.actor.ease({ this._authPrompt.ease({
opacity: 255, opacity: 255,
duration: _FADE_ANIMATION_TIME, duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
@ -1045,12 +1062,12 @@ var LoginDialog = GObject.registerClass({
() => { () => {
// If idle timeout is done, make sure the timed login indicator is shown // If idle timeout is done, make sure the timed login indicator is shown
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD && if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
this._authPrompt.actor.visible) this._authPrompt.visible)
this._authPrompt.cancel(); this._authPrompt.cancel();
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) { if (delay > _TIMED_LOGIN_IDLE_THRESHOLD || firstRun) {
this._userList.scrollToItem(loginItem); this._userList.scrollToItem(loginItem);
loginItem.actor.grab_key_focus(); loginItem.grab_key_focus();
} }
}, },
@ -1111,7 +1128,7 @@ var LoginDialog = GObject.registerClass({
this._sessionMenuButton.close(); this._sessionMenuButton.close();
this._setUserListExpanded(true); this._setUserListExpanded(true);
this._notListedButton.show(); this._notListedButton.show();
this._userList.actor.grab_key_focus(); this._userList.grab_key_focus();
} }
_beginVerificationForItem(item) { _beginVerificationForItem(item) {
@ -1219,7 +1236,7 @@ var LoginDialog = GObject.registerClass({
_("Login Window"), _("Login Window"),
'dialog-password-symbolic', 'dialog-password-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE }); { sortGroup: CtrlAltTab.SortGroup.MIDDLE });
this._userList.actor.grab_key_focus(); this._userList.grab_key_focus();
this.show(); this.show();
this.opacity = 0; this.opacity = 0;

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine, /* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted, formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView */ makeCloseButton, ensureActorVisibleInScrollView, wiggle */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
@ -429,3 +429,37 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
duration: SCROLL_TIME 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,
});
}
});
}
});
}

View File

@ -127,11 +127,11 @@ function *run() {
for (let i = 0; i < 2; i++) { for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true; Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = false; Main.overview.dash.showAppsButton.checked = false;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
} }
} }

View File

@ -127,7 +127,7 @@ function *run() {
Scripting.scriptEvent('applicationsShowStart'); Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates // eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true; Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone'); Scripting.scriptEvent('applicationsShowDone');

View File

@ -56,8 +56,8 @@ class AccessDialog extends ModalDialog.ModalDialog {
let check = new CheckBox.CheckBox(); let check = new CheckBox.CheckBox();
check.getLabelActor().text = name; check.getLabelActor().text = name;
check.actor.checked = selected == "true"; check.checked = selected == "true";
content.insertBeforeBody(check.actor); content.insertBeforeBody(check);
this._choices.set(id, check); this._choices.set(id, check);
} }
@ -99,7 +99,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
let results = {}; let results = {};
if (response == DialogResponse.OK) { if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) { for (let [id, check] of this._choices) {
let checked = check.actor.checked ? 'true' : 'false'; let checked = check.checked ? 'true' : 'false';
results[id] = new GLib.Variant('s', checked); results[id] = new GLib.Variant('s', checked);
} }
} }

View File

@ -405,27 +405,26 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
} }
}); });
class CyclerHighlight { var CyclerHighlight = GObject.registerClass(
constructor() { class CyclerHighlight extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null; this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._clone = new Clutter.Clone(); this._clone = new Clutter.Clone();
this.actor.add_actor(this._clone); this.add_actor(this._clone);
this._highlight = new St.Widget({ style_class: 'cycler-highlight' }); this._highlight = new St.Widget({ style_class: 'cycler-highlight' });
this.actor.add_actor(this._highlight); this.add_actor(this._highlight);
let coordinate = Clutter.BindCoordinate.ALL; let coordinate = Clutter.BindCoordinate.ALL;
let constraint = new Clutter.BindConstraint({ coordinate: coordinate }); let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
this._clone.bind_property('source', constraint, 'source', 0); this._clone.bind_property('source', constraint, 'source', 0);
this.actor.add_constraint(constraint); this.add_constraint(constraint);
this.actor.connect('notify::allocation', this.connect('notify::allocation', this._onAllocationChanged.bind(this));
this._onAllocationChanged.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
} }
set window(w) { set window(w) {
@ -451,7 +450,7 @@ class CyclerHighlight {
this._highlight.set_size(0, 0); this._highlight.set_size(0, 0);
this._highlight.hide(); this._highlight.hide();
} else { } else {
let [x, y] = this.actor.allocation.get_origin(); let [x, y] = this.allocation.get_origin();
let rect = this._window.get_frame_rect(); let rect = this._window.get_frame_rect();
this._highlight.set_size(rect.width, rect.height); this._highlight.set_size(rect.width, rect.height);
this._highlight.set_position(rect.x - x, rect.y - y); this._highlight.set_position(rect.x - x, rect.y - y);
@ -462,7 +461,7 @@ class CyclerHighlight {
_onDestroy() { _onDestroy() {
this.window = null; this.window = null;
} }
} });
// We don't show an actual popup, so just provide what SwitcherPopup // We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList // expects instead of inheriting from SwitcherList
@ -489,7 +488,7 @@ var CyclerPopup = GObject.registerClass({
return; return;
this._highlight = new CyclerHighlight(); this._highlight = new CyclerHighlight();
global.window_group.add_actor(this._highlight.actor); global.window_group.add_actor(this._highlight);
this._switcherList = new CyclerList(); this._switcherList = new CyclerList();
this._switcherList.connect('item-highlighted', (list, index) => { this._switcherList.connect('item-highlighted', (list, index) => {
@ -499,7 +498,7 @@ var CyclerPopup = GObject.registerClass({
_highlightItem(index, _justOutline) { _highlightItem(index, _justOutline) {
this._highlight.window = this._items[index]; this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null); global.window_group.set_child_above_sibling(this._highlight, null);
} }
_finish() { _finish() {
@ -529,7 +528,7 @@ var CyclerPopup = GObject.registerClass({
} }
_onDestroy() { _onDestroy() {
this._highlight.actor.destroy(); this._highlight.destroy();
super._onDestroy(); super._onDestroy();
} }

View File

@ -1,19 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */ /* exported Animation, AnimatedIcon, Spinner */
const { Clutter, GLib, Gio, St } = imports.gi; const { Clutter, GLib, GObject, Gio, St } = imports.gi;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16; var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300; var SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000; var SPINNER_ANIMATION_DELAY = 1000;
var Animation = class { var Animation = GObject.registerClass(
constructor(file, width, height, speed) { class Animation extends St.Bin {
this.actor = new St.Bin(); _init(file, width, height, speed) {
this.actor.set_size(width, height); super._init({ width: width, height: height });
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::size', this._syncAnimationSize.bind(this)); this.connect('resource-scale-changed',
this.actor.connect('resource-scale-changed',
this._loadFile.bind(this, file, width, height)); this._loadFile.bind(this, file, width, height));
let themeContext = St.ThemeContext.get_for_stage(global.stage); let themeContext = St.ThemeContext.get_for_stage(global.stage);
@ -52,14 +51,14 @@ var Animation = class {
} }
_loadFile(file, width, height) { _loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale(); let [validResourceScale, resourceScale] = this.get_resource_scale();
let wasPlaying = this._isPlaying; let wasPlaying = this._isPlaying;
if (this._isPlaying) if (this._isPlaying)
this.stop(); this.stop();
this._isLoaded = false; this._isLoaded = false;
this.actor.destroy_all_children(); this.destroy_all_children();
if (!validResourceScale) { if (!validResourceScale) {
if (wasPlaying) if (wasPlaying)
@ -72,7 +71,7 @@ var Animation = class {
this._animations = textureCache.load_sliced_image(file, width, height, this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale, scaleFactor, resourceScale,
this._animationsLoaded.bind(this)); this._animationsLoaded.bind(this));
this.actor.set_child(this._animations); this.set_child(this._animations);
if (wasPlaying) if (wasPlaying)
this.play(); this.play();
@ -99,7 +98,7 @@ var Animation = class {
if (!this._isLoaded) if (!this._isLoaded)
return; return;
let [width, height] = this.actor.get_size(); let [width, height] = this.get_size();
for (let i = 0; i < this._animations.get_n_children(); ++i) for (let i = 0; i < this._animations.get_n_children(); ++i)
this._animations.get_child_at_index(i).set_size(width, height); this._animations.get_child_at_index(i).set_size(width, height);
@ -122,20 +121,22 @@ var Animation = class {
themeContext.disconnect(this._scaleChangedId); themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0; this._scaleChangedId = 0;
} }
}; });
var AnimatedIcon = class extends Animation { var AnimatedIcon = GObject.registerClass(
constructor(file, size) { class AnimatedIcon extends Animation {
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT); _init(file, size) {
super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
} }
}; });
var Spinner = class extends AnimatedIcon { var Spinner = GObject.registerClass(
constructor(size, animate = false) { class Spinner extends AnimatedIcon {
_init(size, animate = false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size); super._init(file, size);
this.actor.opacity = 0; this.opacity = 0;
this._animate = animate; this._animate = animate;
} }
@ -145,35 +146,35 @@ var Spinner = class extends AnimatedIcon {
} }
play() { play() {
this.actor.remove_all_transitions(); this.remove_all_transitions();
if (this._animate) { if (this._animate) {
super.play(); super.play();
this.actor.ease({ this.ease({
opacity: 255, opacity: 255,
delay: SPINNER_ANIMATION_DELAY, delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME, duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR mode: Clutter.AnimationMode.LINEAR
}); });
} else { } else {
this.actor.opacity = 255; this.opacity = 255;
super.play(); super.play();
} }
} }
stop() { stop() {
this.actor.remove_all_transitions(); this.remove_all_transitions();
if (this._animate) { if (this._animate) {
this.actor.ease({ this.ease({
opacity: 0, opacity: 0,
duration: SPINNER_ANIMATION_TIME, duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR,
onComplete: () => super.stop() onComplete: () => super.stop()
}); });
} else { } else {
this.actor.opacity = 0; this.opacity = 0;
super.stop(); super.stop();
} }
} }
}; });

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SystemBackground */
// READ THIS FIRST // READ THIS FIRST
// Background handling is a maze of objects, both objects in this file, and // Background handling is a maze of objects, both objects in this file, and
@ -93,7 +94,7 @@
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage // MetaBackgroundImage MetaBackgroundImage
const { Clutter, GDesktopEnums, Gio, GLib, GnomeDesktop, Meta } = imports.gi; const { Clutter, GDesktopEnums, Gio, GLib, GObject, GnomeDesktop, Meta } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const LoginManager = imports.misc.loginManager; const LoginManager = imports.misc.loginManager;
@ -220,16 +221,17 @@ function getBackgroundCache() {
return _backgroundCache; return _backgroundCache;
} }
var Background = class Background { var Background = GObject.registerClass({
constructor(params) { Signals: { 'loaded': {}, 'bg-changed': {} }
}, class Background extends Meta.Background {
_init(params) {
params = Params.parse(params, { monitorIndex: 0, params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager, layoutManager: Main.layoutManager,
settings: null, settings: null,
file: null, file: null,
style: null }); style: null });
this.background = new Meta.Background({ meta_display: global.display }); super._init({ meta_display: global.display });
this.background._delegate = this;
this._settings = params.settings; this._settings = params.settings;
this._file = params.file; this._file = params.file;
@ -262,8 +264,6 @@ var Background = class Background {
} }
destroy() { destroy() {
this.background = null;
this._cancellable.cancel(); this._cancellable.cancel();
this._removeAnimationTimeout(); this._removeAnimationTimeout();
@ -300,9 +300,11 @@ var Background = class Background {
this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._changedIdleId = 0; this._changedIdleId = 0;
this.emit('changed'); this.emit('bg-changed');
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._changedIdleId,
'[gnome-shell] Background._emitChangedSignal');
} }
updateResolution() { updateResolution() {
@ -328,7 +330,7 @@ var Background = class Background {
this.emit('loaded'); this.emit('loaded');
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit'); GLib.Source.set_name_by_id(id, '[gnome-shell] Background._setLoaded Idle');
} }
_loadPattern() { _loadPattern() {
@ -342,9 +344,9 @@ var Background = class Background {
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY); let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
if (shadingType == GDesktopEnums.BackgroundShading.SOLID) if (shadingType == GDesktopEnums.BackgroundShading.SOLID)
this.background.set_color(color); this.set_color(color);
else else
this.background.set_gradient(shadingType, color, secondColor); this.set_gradient(shadingType, color, secondColor);
} }
_watchFile(file) { _watchFile(file) {
@ -380,13 +382,13 @@ var Background = class Background {
let finish = () => { let finish = () => {
this._setLoaded(); this._setLoaded();
if (files.length > 1) { if (files.length > 1) {
this.background.set_blend(files[0], files[1], this.set_blend(files[0], files[1],
this._animation.transitionProgress, this._animation.transitionProgress,
this._style); this._style);
} else if (files.length > 0) { } else if (files.length > 0) {
this.background.set_file(files[0], this._style); this.set_file(files[0], this._style);
} else { } else {
this.background.set_file(null, this._style); this.set_file(null, this._style);
} }
this._queueUpdateAnimation(); this._queueUpdateAnimation();
}; };
@ -459,7 +461,7 @@ var Background = class Background {
} }
_loadImage(file) { _loadImage(file) {
this.background.set_file(file, this._style); this.set_file(file, this._style);
this._watchFile(file); this._watchFile(file);
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
@ -493,13 +495,14 @@ var Background = class Background {
this._loadFile(this._file); this._loadFile(this._file);
} }
}; });
Signals.addSignalMethods(Background.prototype);
let _systemBackground; let _systemBackground;
var SystemBackground = class SystemBackground { var SystemBackground = GObject.registerClass({
constructor() { Signals: { 'loaded': {} }
}, class SystemBackground extends Meta.BackgroundActor {
_init() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) { if (_systemBackground == null) {
@ -508,9 +511,11 @@ var SystemBackground = class SystemBackground {
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER); _systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
} }
this.actor = new Meta.BackgroundActor({ meta_display: global.display, super._init({
meta_display: global.display,
monitor: 0, monitor: 0,
background: _systemBackground }); background: _systemBackground
});
let cache = Meta.BackgroundImageCache.get_default(); let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file); let image = cache.load(file);
@ -529,8 +534,7 @@ var SystemBackground = class SystemBackground {
}); });
} }
} }
}; });
Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = class BackgroundSource { var BackgroundSource = class BackgroundSource {
constructor(layoutManager, settingsSchema) { constructor(layoutManager, settingsSchema) {
@ -566,7 +570,7 @@ var BackgroundSource = class BackgroundSource {
// We don't watch changes to settings here, // We don't watch changes to settings here,
// instead we rely on Background to watch those // instead we rely on Background to watch those
// and emit 'changed' at the right time // and emit 'bg-changed' at the right time
if (this._overrideImage != null) { if (this._overrideImage != null) {
file = Gio.File.new_for_path(this._overrideImage); file = Gio.File.new_for_path(this._overrideImage);
@ -595,7 +599,7 @@ var BackgroundSource = class BackgroundSource {
style: style style: style
}); });
background._changedId = background.connect('changed', () => { background._changedId = background.connect('bg-changed', () => {
background.disconnect(background._changedId); background.disconnect(background._changedId);
background.destroy(); background.destroy();
delete this._backgrounds[monitorIndex]; delete this._backgrounds[monitorIndex];
@ -732,7 +736,7 @@ var BackgroundManager = class BackgroundManager {
this._newBackgroundActor = newBackgroundActor; this._newBackgroundActor = newBackgroundActor;
let background = newBackgroundActor.background._delegate; let background = newBackgroundActor.background;
if (background.isLoaded) { if (background.isLoaded) {
this._swapBackgroundActor(); this._swapBackgroundActor();
@ -752,7 +756,7 @@ var BackgroundManager = class BackgroundManager {
let backgroundActor = new Meta.BackgroundActor({ let backgroundActor = new Meta.BackgroundActor({
meta_display: global.display, meta_display: global.display,
monitor: this._monitorIndex, monitor: this._monitorIndex,
background: background.background, background,
vignette: this._vignette, vignette: this._vignette,
vignette_sharpness: 0.5, vignette_sharpness: 0.5,
brightness: 0.5, brightness: 0.5,
@ -766,7 +770,7 @@ var BackgroundManager = class BackgroundManager {
backgroundActor.lower_bottom(); backgroundActor.lower_bottom();
} }
let changeSignalId = background.connect('changed', () => { let changeSignalId = background.connect('bg-changed', () => {
background.disconnect(changeSignalId); background.disconnect(changeSignalId);
changeSignalId = null; changeSignalId = null;
this._updateBackgroundActor(); this._updateBackgroundActor();

View File

@ -46,12 +46,18 @@ var BoxPointer = GObject.registerClass({
this.add_actor(this._border); this.add_actor(this._border);
this.bin.raise(this._border); this.bin.raise(this._border);
this._sourceAlignment = 0.5; this._sourceAlignment = 0.5;
this._capturedEventId = 0; this._muteInput = true;
this._muteInput();
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} }
vfunc_captured_event() {
if (this._muteInput)
return Clutter.EVENT_STOP;
return Clutter.EVENT_PROPAGATE;
}
_onDestroy() { _onDestroy() {
if (this._sourceActorDestroyId) { if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId); this._sourceActor.disconnect(this._sourceActorDestroyId);
@ -63,19 +69,6 @@ var BoxPointer = GObject.registerClass({
return this._arrowSide; 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) { open(animate, onComplete) {
let themeNode = this.get_theme_node(); let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
@ -112,7 +105,7 @@ var BoxPointer = GObject.registerClass({
duration: animationTime, duration: animationTime,
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR,
onComplete: () => { onComplete: () => {
this._unmuteInput(); this._muteInput = false;
if (onComplete) if (onComplete)
onComplete(); onComplete();
} }
@ -147,7 +140,7 @@ var BoxPointer = GObject.registerClass({
} }
} }
this._muteInput(); this._muteInput = true;
this.remove_all_transitions(); this.remove_all_transitions();
this.ease({ this.ease({

View File

@ -313,8 +313,10 @@ var DBusEventSource = class DBusEventSource {
}; };
Signals.addSignalMethods(DBusEventSource.prototype); Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = class Calendar { var Calendar = GObject.registerClass({
constructor() { Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } }
}, class Calendar extends St.Widget {
_init() {
this._weekStart = Shell.util_get_week_start(); this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' }); this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
@ -344,12 +346,11 @@ var Calendar = class Calendar {
this._shouldDateGrabFocus = false; this._shouldDateGrabFocus = false;
this.actor = new St.Widget({ style_class: 'calendar', super._init({
style_class: 'calendar',
layout_manager: new Clutter.TableLayout(), layout_manager: new Clutter.TableLayout(),
reactive: true }); reactive: true
});
this.actor.connect('scroll-event',
this._onScroll.bind(this));
this._buildHeader (); this._buildHeader ();
} }
@ -373,7 +374,10 @@ var Calendar = class Calendar {
this._selectedDate = date; this._selectedDate = date;
this._update(); this._update();
this.emit('selected-date-changed', new Date(this._selectedDate));
let datetime = GLib.DateTime.new_from_unix_local(
this._selectedDate.getTime() / 1000);
this.emit('selected-date-changed', datetime);
} }
updateTimeZone() { updateTimeZone() {
@ -384,9 +388,9 @@ var Calendar = class Calendar {
} }
_buildHeader() { _buildHeader() {
let layout = this.actor.layout_manager; let layout = this.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_all_children(); this.destroy_all_children();
// Top line of the calendar '<| September 2009 |>' // Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout(); this._topBox = new St.BoxLayout();
@ -428,7 +432,7 @@ var Calendar = class Calendar {
can_focus: true }); can_focus: true });
label.accessible_name = iter.toLocaleFormat('%A'); label.accessible_name = iter.toLocaleFormat('%A');
let col; let col;
if (this.actor.get_text_direction() == Clutter.TextDirection.RTL) if (this.get_text_direction() == Clutter.TextDirection.RTL)
col = 6 - (7 + iter.getDay() - this._weekStart) % 7; col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7; col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
@ -437,11 +441,11 @@ var Calendar = class Calendar {
} }
// All the children after this are days, and get removed when we update the calendar // All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.actor.get_n_children(); this._firstDayIndex = this.get_n_children();
} }
_onScroll(actor, event) { vfunc_scroll_event(scrollEvent) {
switch (event.get_scroll_direction()) { switch (scrollEvent.direction) {
case Clutter.ScrollDirection.UP: case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT: case Clutter.ScrollDirection.LEFT:
this._onPrevMonthButtonClicked(); this._onPrevMonthButtonClicked();
@ -511,7 +515,7 @@ var Calendar = class Calendar {
let now = new Date(); let now = new Date();
// Remove everything but the topBox and the weekday labels // Remove everything but the topBox and the weekday labels
let children = this.actor.get_children(); let children = this.get_children();
for (let i = this._firstDayIndex; i < children.length; i++) for (let i = this._firstDayIndex; i < children.length; i++)
children[i].destroy(); children[i].destroy();
@ -548,7 +552,7 @@ var Calendar = class Calendar {
beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY); beginDate.setTime(beginDate.getTime() - (weekPadding + daysToWeekStart) * MSECS_IN_DAY);
let layout = this.actor.layout_manager; let layout = this.layout_manager;
let iter = new Date(beginDate); let iter = new Date(beginDate);
let row = 2; let row = 2;
// nRows here means 6 weeks + one header + one navbar // nRows here means 6 weeks + one header + one navbar
@ -648,12 +652,12 @@ var Calendar = class Calendar {
} }
}); });
} }
}; });
Signals.addSignalMethods(Calendar.prototype);
var EventMessage = class EventMessage extends MessageList.Message { var EventMessage = GObject.registerClass(
constructor(event, date) { class EventMessage extends MessageList.Message {
super('', event.summary); _init(event, date) {
super._init('', event.summary);
this._event = event; this._event = event;
this._date = date; this._date = date;
@ -662,11 +666,12 @@ var EventMessage = class EventMessage extends MessageList.Message {
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' }); this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon); this.setIcon(this._icon);
}
this.actor.connect('style-changed', () => { vfunc_style_changed() {
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child'); let iconVisible = this.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0); this._icon.opacity = (iconVisible ? 255 : 0);
}); super.vfunc_style_changed();
} }
_formatEventTime() { _formatEventTime() {
@ -702,12 +707,12 @@ var EventMessage = class EventMessage extends MessageList.Message {
} }
return title; return title;
} }
}; });
var NotificationMessage = var NotificationMessage = GObject.registerClass(
class NotificationMessage extends MessageList.Message { class NotificationMessage extends MessageList.Message {
constructor(notification) { _init(notification) {
super(notification.title, notification.bannerBodyText); super._init(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup); this.setUseBodyMarkup(notification.bannerBodyMarkup);
this.notification = notification; this.notification = notification;
@ -744,7 +749,7 @@ class NotificationMessage extends MessageList.Message {
this.setUseBodyMarkup(n.bannerBodyMarkup); this.setUseBodyMarkup(n.bannerBodyMarkup);
} }
_onClicked() { vfunc_clicked() {
this.notification.activate(); this.notification.activate();
} }
@ -766,11 +771,12 @@ class NotificationMessage extends MessageList.Message {
canClose() { canClose() {
return true; return true;
} }
}; });
var EventsSection = class EventsSection extends MessageList.MessageListSection { var EventsSection = GObject.registerClass(
constructor() { class EventsSection extends MessageList.MessageListSection {
super(); _init() {
super._init();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', this._reloadEvents.bind(this)); this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
@ -782,7 +788,7 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
label: '', label: '',
x_align: St.Align.START, x_align: St.Align.START,
can_focus: true }); can_focus: true });
this.actor.insert_child_below(this._title, null); this.insert_child_below(this._title, null);
this._title.connect('clicked', this._onTitleClicked.bind(this)); this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this)); this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
@ -901,12 +907,29 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
super._sync(); super._sync();
} }
}; });
var NotificationSection = 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(
class NotificationSection extends MessageList.MessageListSection { class NotificationSection extends MessageList.MessageListSection {
constructor() { _init() {
super(); super._init();
this._sources = new Map(); this._sources = new Map();
this._nUrgent = 0; this._nUrgent = 0;
@ -915,8 +938,6 @@ class NotificationSection extends MessageList.MessageListSection {
Main.messageTray.getSources().forEach(source => { Main.messageTray.getSources().forEach(source => {
this._sourceAdded(Main.messageTray, source); this._sourceAdded(Main.messageTray, source);
}); });
this.actor.connect('notify::mapped', this._onMapped.bind(this));
} }
get allowed() { get allowed() {
@ -924,17 +945,6 @@ class NotificationSection extends MessageList.MessageListSection {
!Main.sessionMode.isGreeter; !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) { _sourceAdded(tray, source) {
let obj = { let obj = {
destroyId: 0, destroyId: 0,
@ -952,13 +962,13 @@ class NotificationSection extends MessageList.MessageListSection {
_onNotificationAdded(source, notification) { _onNotificationAdded(source, notification) {
let message = new NotificationMessage(notification); let message = new NotificationMessage(notification);
message.setSecondaryActor(this._createTimeLabel(notification.datetime)); message.setSecondaryActor(new TimeLabel(notification.datetime));
let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL; let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL;
let updatedId = notification.connect('updated', () => { let updatedId = notification.connect('updated', () => {
message.setSecondaryActor(this._createTimeLabel(notification.datetime)); message.setSecondaryActor(new TimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped); this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.mapped);
}); });
let destroyId = notification.connect('destroy', () => { let destroyId = notification.connect('destroy', () => {
notification.disconnect(destroyId); notification.disconnect(destroyId);
@ -978,7 +988,7 @@ class NotificationSection extends MessageList.MessageListSection {
} }
let index = isUrgent ? 0 : this._nUrgent; let index = isUrgent ? 0 : this._nUrgent;
this.addMessageAtIndex(message, index, this.actor.mapped); this.addMessageAtIndex(message, index, this.mapped);
} }
_onSourceDestroy(source, obj) { _onSourceDestroy(source, obj) {
@ -988,25 +998,23 @@ class NotificationSection extends MessageList.MessageListSection {
this._sources.delete(source); this._sources.delete(source);
} }
_onMapped() { vfunc_map() {
if (!this.actor.mapped) this._messages.forEach(message => {
return;
for (let message of this._messages.keys())
if (message.notification.urgency != MessageTray.Urgency.CRITICAL) if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
message.notification.acknowledged = true; message.notification.acknowledged = true;
});
super.vfunc_map();
} }
_shouldShow() { _shouldShow() {
return !this.empty && isToday(this._date); 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(); this._date = new Date();
let todayFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/no-notifications.svg'); let todayFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/no-notifications.svg');
@ -1015,10 +1023,10 @@ var Placeholder = class Placeholder {
this._otherIcon = new Gio.FileIcon({ file: otherFile }); this._otherIcon = new Gio.FileIcon({ file: otherFile });
this._icon = new St.Icon(); this._icon = new St.Icon();
this.actor.add_actor(this._icon); this.add_actor(this._icon);
this._label = new St.Label(); this._label = new St.Label();
this.actor.add_actor(this._label); this.add_actor(this._label);
this._sync(); this._sync();
} }
@ -1045,20 +1053,24 @@ var Placeholder = class Placeholder {
this._label.text = _("No Events"); this._label.text = _("No Events");
} }
} }
}; });
var CalendarMessageList = class CalendarMessageList { var CalendarMessageList = GObject.registerClass(
constructor() { class CalendarMessageList extends St.Widget {
this.actor = new St.Widget({ style_class: 'message-list', _init() {
super._init({
style_class: 'message-list',
layout_manager: new Clutter.BinLayout(), layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true }); x_expand: true,
y_expand: true
});
this._placeholder = new Placeholder(); this._placeholder = new Placeholder();
this.actor.add_actor(this._placeholder.actor); this.add_actor(this._placeholder);
let box = new St.BoxLayout({ vertical: true, let box = new St.BoxLayout({ vertical: true,
x_expand: true, y_expand: true }); x_expand: true, y_expand: true });
this.actor.add_actor(box); this.add_actor(box);
this._scrollView = new St.ScrollView({ style_class: 'vfade', this._scrollView = new St.ScrollView({ style_class: 'vfade',
overlay_scrollbars: true, overlay_scrollbars: true,
@ -1072,12 +1084,11 @@ var CalendarMessageList = class CalendarMessageList {
can_focus: true }); can_focus: true });
this._clearButton.set_x_align(Clutter.ActorAlign.END); this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => { this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()]; this._sectionList.get_children().forEach(s => s.clear());
sections.forEach(s => s.clear());
}); });
box.add_actor(this._clearButton); box.add_actor(this._clearButton);
this._placeholder.actor.bind_property('visible', this._placeholder.bind_property('visible',
this._clearButton, 'visible', this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN); GObject.BindingFlags.INVERT_BOOLEAN);
@ -1085,8 +1096,9 @@ var CalendarMessageList = class CalendarMessageList {
vertical: true, vertical: true,
y_expand: true, y_expand: true,
y_align: Clutter.ActorAlign.START }); 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._scrollView.add_actor(this._sectionList);
this._sections = new Map();
this._mediaSection = new Mpris.MediaSection(); this._mediaSection = new Mpris.MediaSection();
this._addSection(this._mediaSection); this._addSection(this._mediaSection);
@ -1101,58 +1113,35 @@ var CalendarMessageList = class CalendarMessageList {
} }
_addSection(section) { _addSection(section) {
let obj = { let connectionsIds = [];
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));
this._sections.set(section, obj); for (let prop of ['visible', 'empty', 'can-clear']) {
this._sectionList.add_actor(section.actor); connectionsIds.push(
this._sync(); section.connect(`notify::${prop}`, this._sync.bind(this)));
} }
connectionsIds.push(section.connect('message-focused', (_s, messageActor) => {
Util.ensureActorVisibleInScrollView(this._scrollView, messageActor);
}));
_removeSection(section) { connectionsIds.push(section.connect('destroy', (section) => {
let obj = this._sections.get(section); connectionsIds.forEach(id => section.disconnect(id));
section.actor.disconnect(obj.destroyId); this._sectionList.remove_actor(section);
section.actor.disconnect(obj.visibleId); }));
section.disconnect(obj.emptyChangedId);
section.disconnect(obj.canClearChangedId);
section.disconnect(obj.keyFocusId);
this._sections.delete(section); this._sectionList.add_actor(section);
this._sectionList.remove_actor(section.actor);
this._sync();
}
_onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
} }
_sync() { _sync() {
let sections = [...this._sections.keys()]; let sections = this._sectionList.get_children();
let visible = sections.some(s => s.allowed); let visible = sections.some(s => s.allowed);
this.actor.visible = visible; this.visible = visible;
if (!visible) if (!visible)
return; return;
let empty = sections.every(s => s.empty || !s.actor.visible); let empty = sections.every(s => s.empty || !s.visible);
this._placeholder.actor.visible = empty; this._placeholder.visible = empty;
let canClear = sections.some(s => s.canClear && s.actor.visible); let canClear = sections.some(s => s.canClear && s.visible);
this._clearButton.reactive = canClear; this._clearButton.reactive = canClear;
} }
@ -1161,8 +1150,7 @@ var CalendarMessageList = class CalendarMessageList {
} }
setDate(date) { setDate(date) {
for (let section of this._sections.keys()) this._sectionList.get_children().forEach(s => s.setDate(date));
section.setDate(date);
this._placeholder.setDate(date); this._placeholder.setDate(date);
} }
}; });

View File

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

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */ /* exported Component */
const { Gio, St } = imports.gi; const { Gio, GObject, St } = imports.gi;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -272,9 +272,10 @@ var AutorunDispatcher = class {
} }
}; };
var AutorunSource = class extends MessageTray.Source { var AutorunSource = GObject.registerClass(
constructor(manager, mount, apps) { class AutorunSource extends MessageTray.Source {
super(mount.get_name()); _init(manager, mount, apps) {
super._init(mount.get_name());
this._manager = manager; this._manager = manager;
this.mount = mount; this.mount = mount;
@ -284,7 +285,7 @@ var AutorunSource = class extends MessageTray.Source {
// add ourselves as a source, and popup the notification // add ourselves as a source, and popup the notification
Main.messageTray.add(this); Main.messageTray.add(this);
this.notify(this._notification); this.showNotification(this._notification);
} }
getIcon() { getIcon() {
@ -294,11 +295,12 @@ var AutorunSource = class extends MessageTray.Source {
_createPolicy() { _createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus'); return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
} }
}; });
var AutorunNotification = class extends MessageTray.Notification { var AutorunNotification = GObject.registerClass(
constructor(manager, source) { class AutorunNotification extends MessageTray.Notification {
super(source, source.title); _init(manager, source) {
super._init(source, source.title);
this._manager = manager; this._manager = manager;
this._mount = source.mount; this._mount = source.mount;
@ -350,6 +352,6 @@ var AutorunNotification = class extends MessageTray.Notification {
let app = Gio.app_info_get_default_for_type('inode/directory', false); let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount); startAppForMount(app, this._mount);
} }
}; });
var Component = AutorunManager; var Component = AutorunManager;

View File

@ -77,13 +77,13 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true); this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
if (rtl) { if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1); layout.attach(this._workSpinner, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1); layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(label, 2, row, 1, 1); layout.attach(label, 2, row, 1, 1);
} else { } else {
layout.attach(label, 0, row, 1, 1); layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1); layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(this._workSpinner.actor, 2, row, 1, 1); layout.attach(this._workSpinner, 2, row, 1, 1);
} }
row++; row++;
} else { } else {
@ -121,8 +121,8 @@ class KeyringDialog extends ModalDialog.ModalDialog {
if (this.prompt.choice_visible) { if (this.prompt.choice_visible) {
let choice = new CheckBox.CheckBox(); let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE); this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL); this.prompt.bind_property('choice-chosen', choice, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1); layout.attach(choice, rtl ? 0 : 1, row, 1, 1);
row++; row++;
} }

View File

@ -734,7 +734,7 @@ var NetworkAgent = class {
}); });
Main.messageTray.add(source); Main.messageTray.add(source);
source.notify(notification); source.showNotification(notification);
} }
_newRequest(agent, requestId, connection, settingName, hints, flags) { _newRequest(agent, requestId, connection, settingName, hints, flags) {

View File

@ -76,8 +76,8 @@ var AuthenticationDialog = GObject.registerClass({
this._userAvatar = new UserWidget.Avatar(this._user, this._userAvatar = new UserWidget.Avatar(this._user,
{ iconSize: DIALOG_ICON_SIZE, { iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' }); styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide(); this._userAvatar.hide();
userBox.add(this._userAvatar.actor, userBox.add(this._userAvatar,
{ x_fill: true, { x_fill: true,
y_fill: false, y_fill: false,
x_align: St.Align.END, x_align: St.Align.END,
@ -106,7 +106,7 @@ var AuthenticationDialog = GObject.registerClass({
{ expand: true }); { expand: true });
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true); this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._passwordBox.add(this._workSpinner.actor); this._passwordBox.add(this._workSpinner);
this.setInitialKeyFocus(this._passwordEntry); this.setInitialKeyFocus(this._passwordEntry);
this._passwordBox.hide(); this._passwordBox.hide();
@ -305,7 +305,7 @@ var AuthenticationDialog = GObject.registerClass({
_onUserChanged() { _onUserChanged() {
if (this._user.is_loaded && this._userAvatar) { if (this._user.is_loaded && this._userAvatar) {
this._userAvatar.update(); this._userAvatar.update();
this._userAvatar.actor.show(); this._userAvatar.show();
} }
} }

View File

@ -215,7 +215,7 @@ class TelepathyClient extends Tp.BaseClient {
// We are already handling the channel, display the source // We are already handling the channel, display the source
let source = this._chatSources[channel.get_object_path()]; let source = this._chatSources[channel.get_object_path()];
if (source) if (source)
source.notify(); source.showNotification();
} }
} }
} }
@ -266,9 +266,10 @@ class TelepathyClient extends Tp.BaseClient {
} }
}) : null; }) : null;
var ChatSource = class extends MessageTray.Source { var ChatSource = HAVE_TP ? GObject.registerClass(
constructor(account, conn, channel, contact, client) { class ChatSource extends MessageTray.Source {
super(contact.get_alias()); _init(account, conn, channel, contact, client) {
super._init(contact.get_alias());
this._account = account; this._account = account;
this._contact = contact; this._contact = contact;
@ -326,7 +327,7 @@ var ChatSource = class extends MessageTray.Source {
// We ack messages when the user expands the new notification // We ack messages when the user expands the new notification
let id = this._banner.connect('expanded', this._ackMessages.bind(this)); let id = this._banner.connect('expanded', this._ackMessages.bind(this));
this._banner.actor.connect('destroy', () => { this._banner.connect('destroy', () => {
this._banner.disconnect(id); this._banner.disconnect(id);
this._banner = null; this._banner = null;
}); });
@ -476,7 +477,7 @@ var ChatSource = class extends MessageTray.Source {
this._notification.appendMessage(pendingMessages[i], true); this._notification.appendMessage(pendingMessages[i], true);
if (pendingMessages.length > 0) if (pendingMessages.length > 0)
this.notify(); this.showNotification();
} }
destroy(reason) { destroy(reason) {
@ -553,7 +554,7 @@ var ChatSource = class extends MessageTray.Source {
_notifyTimeout() { _notifyTimeout() {
if (this._pendingMessages.length != 0) if (this._pendingMessages.length != 0)
this.notify(); this.showNotification();
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
@ -568,8 +569,8 @@ var ChatSource = class extends MessageTray.Source {
this._notification.appendMessage(message); this._notification.appendMessage(message);
} }
notify() { showNotification() {
super.notify(this._notification); super.showNotification(this._notification);
} }
respond(text) { respond(text) {
@ -625,11 +626,17 @@ var ChatSource = class extends MessageTray.Source {
// 'pending-message-removed' for each one. // 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null); this._channel.ack_all_pending_messages_async(null);
} }
}; }) : null;
var ChatNotification = class extends MessageTray.Notification { var ChatNotification = HAVE_TP ? GObject.registerClass({
constructor(source) { Signals: {
super(source, source.title, null, '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() }); { secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH); this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true); this.setResident(true);
@ -782,7 +789,7 @@ var ChatNotification = class extends MessageTray.Notification {
this._filterMessages(); this._filterMessages();
} }
}; }) : null;
var ChatLineBox = GObject.registerClass( var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout { class ChatLineBox extends St.BoxLayout {
@ -792,9 +799,10 @@ class ChatLineBox extends St.BoxLayout {
} }
}); });
var ChatNotificationBanner = class extends MessageTray.NotificationBanner { var ChatNotificationBanner = GObject.registerClass(
constructor(notification) { class ChatNotificationBanner extends MessageTray.NotificationBanner {
super(notification); _init(notification) {
super._init(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response', this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true, x_expand: true,
@ -879,8 +887,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
} }
_addMessage(message) { _addMessage(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true); let body = new MessageList.URLHighlighter(message.body, true, true);
let body = highlighter.actor;
let styles = message.styles; let styles = message.styles;
for (let i = 0; i < styles.length; i++) for (let i = 0; i < styles.length; i++)
@ -968,6 +975,6 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE); this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);
} }
} }
}; });
var Component = TelepathyComponent; var Component = TelepathyComponent;

View File

@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */ /* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, GLib, GObject,
const Signals = imports.signals; Graphene, Meta, Shell, St } = imports.gi;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites; const AppFavorites = imports.ui.appFavorites;
@ -23,9 +23,10 @@ function getAppFromSource(source) {
} }
} }
var DashIcon = class DashIcon extends AppDisplay.AppIcon { var DashIcon = GObject.registerClass(
constructor(app) { class DashIcon extends AppDisplay.AppIcon {
super(app, { _init(app) {
super._init(app, {
setSizeManually: true, setSizeManually: true,
showLabel: false showLabel: false
}); });
@ -45,7 +46,7 @@ var DashIcon = class DashIcon extends AppDisplay.AppIcon {
acceptDrop() { acceptDrop() {
return false; return false;
} }
}; });
// A container like StBin, but taking the child's scale into account // A container like StBin, but taking the child's scale into account
// when requesting a size // when requesting a size
@ -53,7 +54,7 @@ var DashItemContainer = GObject.registerClass(
class DashItemContainer extends St.Widget { class DashItemContainer extends St.Widget {
_init() { _init() {
super._init({ style_class: 'dash-item-container', super._init({ style_class: 'dash-item-container',
pivot_point: new Clutter.Point({ x: .5, y: .5 }), pivot_point: new Graphene.Point({ x: .5, y: .5 }),
scale_x: 0, scale_x: 0,
scale_y: 0, scale_y: 0,
opacity: 0, opacity: 0,
@ -330,8 +331,10 @@ class DashActor extends St.Widget {
const baseIconSizes = [16, 22, 24, 32, 48, 64]; const baseIconSizes = [16, 22, 24, 32, 48, 64];
var Dash = class Dash { var Dash = GObject.registerClass({
constructor() { Signals: { 'icon-size-changed': {} }
}, class Dash extends St.Bin {
_init() {
this._maxHeight = -1; this._maxHeight = -1;
this.iconSize = 64; this.iconSize = 64;
this._shownInitially = false; this._shownInitially = false;
@ -359,11 +362,11 @@ var Dash = class Dash {
this._container.add_actor(this._showAppsIcon); this._container.add_actor(this._showAppsIcon);
this.actor = new St.Bin({ child: this._container }); super._init({ child: this._container });
this.actor.connect('notify::height', () => { this.connect('notify::height', () => {
if (this._maxHeight != this.actor.height) if (this._maxHeight != this.height)
this._queueRedisplay(); this._queueRedisplay();
this._maxHeight = this.actor.height; this._maxHeight = this.height;
}); });
this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this)); this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
@ -386,7 +389,7 @@ var Dash = class Dash {
// Translators: this is the name of the dock/favorites area on // Translators: this is the name of the dock/favorites area on
// the left of the overview // the left of the overview
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic'); Main.ctrlAltTabManager.addGroup(this, _("Dash"), 'user-bookmarks-symbolic');
} }
_onDragBegin() { _onDragBegin() {
@ -481,11 +484,11 @@ var Dash = class Dash {
}); });
let item = new DashItemContainer(); let item = new DashItemContainer();
item.setChild(appIcon.actor); item.setChild(appIcon);
// Override default AppIcon label_actor, now the // Override default AppIcon label_actor, now the
// accessible_name is set at DashItemContainer.setLabelText // accessible_name is set at DashItemContainer.setLabelText
appIcon.actor.label_actor = null; appIcon.label_actor = null;
item.setLabelText(app.get_name()); item.setLabelText(app.get_name());
appIcon.icon.setIconSize(this.iconSize); appIcon.icon.setIconSize(this.iconSize);
@ -902,5 +905,4 @@ var Dash = class Dash {
return true; return true;
} }
}; });
Signals.addSignalMethods(Dash.prototype);

View File

@ -25,24 +25,26 @@ function _isToday(date) {
now.getDate() == date.getDate(); now.getDate() == date.getDate();
} }
var TodayButton = class TodayButton { function _gDateTimeToDate(datetime) {
constructor(calendar) { return new Date(datetime.to_unix() * 1000 + datetime.get_microsecond() / 1000);
}
var TodayButton = GObject.registerClass(
class TodayButton extends St.Button {
_init(calendar) {
// Having the ability to go to the current date if the user is already // Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive // on the current date can be confusing. So don't make the button reactive
// until the selected date changes. // until the selected date changes.
this.actor = new St.Button({ super._init({
style_class: 'datemenu-today-button', style_class: 'datemenu-today-button',
x_align: St.Align.START, x_align: St.Align.START,
x_expand: true, x_expand: true,
can_focus: true, can_focus: true,
reactive: false, reactive: false
});
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
}); });
let hbox = new St.BoxLayout({ vertical: true }); let hbox = new St.BoxLayout({ vertical: true });
this.actor.add_actor(hbox); this.add_actor(hbox);
this._dayLabel = new St.Label({ style_class: 'day-label', this._dayLabel = new St.Label({ style_class: 'day-label',
x_align: Clutter.ActorAlign.START }); x_align: Clutter.ActorAlign.START });
@ -52,13 +54,17 @@ var TodayButton = class TodayButton {
hbox.add_actor(this._dateLabel); hbox.add_actor(this._dateLabel);
this._calendar = calendar; this._calendar = calendar;
this._calendar.connect('selected-date-changed', (calendar, date) => { this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
// Make the button reactive only if the selected date is not the // Make the button reactive only if the selected date is not the
// current date. // current date.
this.actor.reactive = !_isToday(date); this.reactive = !_isToday(_gDateTimeToDate(datetime));
}); });
} }
vfunc_clicked() {
this._calendar.setDate(new Date(), false);
}
setDate(date) { setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A')); this._dayLabel.set_text(date.toLocaleFormat('%A'));
@ -75,34 +81,29 @@ var TodayButton = class TodayButton {
* date, e.g. "Tuesday February 17 2015". * date, e.g. "Tuesday February 17 2015".
*/ */
dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y")); dateFormat = Shell.util_translate_time_string (N_("%A %B %e %Y"));
this.actor.accessible_name = date.toLocaleFormat(dateFormat); this.accessible_name = date.toLocaleFormat(dateFormat);
} }
}; });
var WorldClocksSection = class WorldClocksSection { var WorldClocksSection = GObject.registerClass(
constructor() { class WorldClocksSection extends St.Button {
_init() {
super._init({
style_class: 'world-clocks-button',
x_fill: true,
can_focus: true
});
this._clock = new GnomeDesktop.WallClock(); this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0; this._clockNotifyId = 0;
this._locations = []; 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 }); let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._grid = new St.Widget({ style_class: 'world-clocks-grid', this._grid = new St.Widget({ style_class: 'world-clocks-grid',
layout_manager: layout }); layout_manager: layout });
layout.hookup_style(this._grid); layout.hookup_style(this._grid);
this.actor.child = this._grid; this.child = this._grid;
this._clocksApp = null; this._clocksApp = null;
this._clocksProxy = new ClocksProxy( this._clocksProxy = new ClocksProxy(
@ -125,9 +126,17 @@ var WorldClocksSection = class WorldClocksSection {
this._sync(); this._sync();
} }
vfunc_clicked() {
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
}
_sync() { _sync() {
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop'); this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
this.actor.visible = this._clocksApp != null; this.visible = this._clocksApp != null;
} }
_clocksChanged() { _clocksChanged() {
@ -155,7 +164,7 @@ var WorldClocksSection = class WorldClocksSection {
x_align: Clutter.ActorAlign.START, x_align: Clutter.ActorAlign.START,
text: title }); text: title });
layout.attach(header, 0, 0, 2, 1); layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header; this.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset(); let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
@ -236,30 +245,23 @@ var WorldClocksSection = class WorldClocksSection {
this._settings.set_value('locations', this._settings.set_value('locations',
new GLib.Variant('av', this._clocksProxy.Locations)); new GLib.Variant('av', this._clocksProxy.Locations));
} }
}; });
var WeatherSection = class WeatherSection { var WeatherSection = GObject.registerClass(
constructor() { class WeatherSection extends St.Button {
this._weatherClient = new Weather.WeatherClient(); _init() {
super._init({
this.actor = new St.Button({ style_class: 'weather-button', style_class: 'weather-button',
x_fill: true, x_fill: true,
can_focus: true }); can_focus: true
this.actor.connect('clicked', () => { });
this._weatherClient.activateApp();
Main.overview.hide(); this._weatherClient = new Weather.WeatherClient();
Main.panel.closeCalendar();
});
this.actor.connect('notify::mapped', () => {
if (this.actor.mapped)
this._weatherClient.update();
});
let box = new St.BoxLayout({ style_class: 'weather-box', let box = new St.BoxLayout({ style_class: 'weather-box',
vertical: true }); vertical: true });
this.actor.child = box; this.child = box;
let titleBox = new St.BoxLayout(); let titleBox = new St.BoxLayout();
titleBox.add_child(new St.Label({ style_class: 'weather-header', titleBox.add_child(new St.Label({ style_class: 'weather-header',
@ -282,6 +284,18 @@ var WeatherSection = class WeatherSection {
this._sync(); this._sync();
} }
vfunc_map() {
this._weatherClient.update();
super.vfunc_map();
}
vfunc_clicked() {
this._weatherClient.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
}
_getInfos() { _getInfos() {
let info = this._weatherClient.info; let info = this._weatherClient.info;
let forecasts = info.get_forecast_list(); let forecasts = info.get_forecast_list();
@ -372,23 +386,27 @@ var WeatherSection = class WeatherSection {
} }
_sync() { _sync() {
this.actor.visible = this._weatherClient.available; this.visible = this._weatherClient.available;
if (!this.actor.visible) if (!this.visible)
return; return;
this._titleLocation.visible = this._weatherClient.hasLocation; this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts(); this._updateForecasts();
} }
}; });
var MessagesIndicator = class MessagesIndicator { var MessagesIndicator = GObject.registerClass(
constructor() { class MessagesIndicator extends St.Icon {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic', _init() {
super._init({
icon_name: 'message-indicator-symbolic',
icon_size: 16, icon_size: 16,
visible: false, y_expand: true, visible: false,
y_align: Clutter.ActorAlign.CENTER }); y_expand: true,
y_align: Clutter.ActorAlign.CENTER
});
this._sources = []; this._sources = [];
@ -401,7 +419,7 @@ var MessagesIndicator = class MessagesIndicator {
} }
_onSourceAdded(tray, source) { _onSourceAdded(tray, source) {
source.connect('count-updated', this._updateCount.bind(this)); source.connect('notify::count', this._updateCount.bind(this));
this._sources.push(source); this._sources.push(source);
this._updateCount(); this._updateCount();
} }
@ -416,9 +434,9 @@ var MessagesIndicator = class MessagesIndicator {
this._sources.forEach(source => (count += source.unseenCount)); this._sources.forEach(source => (count += source.unseenCount));
count -= Main.messageTray.queueCount; count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0); this.visible = (count > 0);
} }
}; });
var IndicatorPad = GObject.registerClass( var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget { class IndicatorPad extends St.Widget {
@ -511,9 +529,9 @@ class DateMenuButton extends PanelMenu.Button {
this._indicator = new MessagesIndicator(); this._indicator = new MessagesIndicator();
let box = new St.BoxLayout(); let box = new St.BoxLayout();
box.add_actor(new IndicatorPad(this._indicator.actor)); box.add_actor(new IndicatorPad(this._indicator));
box.add_actor(this._clockDisplay); box.add_actor(this._clockDisplay);
box.add_actor(this._indicator.actor); box.add_actor(this._indicator);
this.label_actor = this._clockDisplay; this.label_actor = this._clockDisplay;
this.add_actor(box); this.add_actor(box);
@ -529,8 +547,8 @@ class DateMenuButton extends PanelMenu.Button {
bin.add_actor(hbox); bin.add_actor(hbox);
this._calendar = new Calendar.Calendar(); this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed', this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
(calendar, date) => { let date = _gDateTimeToDate(datetime);
layout.frozen = !_isToday(date); layout.frozen = !_isToday(date);
this._messageList.setDate(date); this._messageList.setDate(date);
}); });
@ -547,19 +565,19 @@ class DateMenuButton extends PanelMenu.Button {
// Fill up the first column // Fill up the first column
this._messageList = new Calendar.CalendarMessageList(); this._messageList = new Calendar.CalendarMessageList();
hbox.add(this._messageList.actor, { expand: true, y_fill: false, y_align: St.Align.START }); hbox.add(this._messageList, { expand: true, y_fill: false, y_align: St.Align.START });
// Fill up the second column // Fill up the second column
let boxLayout = new CalendarColumnLayout(this._calendar.actor); let boxLayout = new CalendarColumnLayout(this._calendar);
vbox = new St.Widget({ style_class: 'datemenu-calendar-column', vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
layout_manager: boxLayout }); layout_manager: boxLayout });
boxLayout.hookup_style(vbox); boxLayout.hookup_style(vbox);
hbox.add(vbox); hbox.add(vbox);
this._date = new TodayButton(this._calendar); this._date = new TodayButton(this._calendar);
vbox.add_actor(this._date.actor); vbox.add_actor(this._date);
vbox.add_actor(this._calendar.actor); vbox.add_actor(this._calendar);
this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade', this._displaysSection = new St.ScrollView({ style_class: 'datemenu-displays-section vfade',
x_expand: true, x_fill: true, x_expand: true, x_fill: true,
@ -572,10 +590,10 @@ class DateMenuButton extends PanelMenu.Button {
this._displaysSection.add_actor(displaysBox); this._displaysSection.add_actor(displaysBox);
this._clocksItem = new WorldClocksSection(); this._clocksItem = new WorldClocksSection();
displaysBox.add(this._clocksItem.actor, { x_fill: true }); displaysBox.add(this._clocksItem, { x_fill: true });
this._weatherItem = new WeatherSection(); this._weatherItem = new WeatherSection();
displaysBox.add(this._weatherItem.actor, { x_fill: true }); displaysBox.add(this._weatherItem, { x_fill: true });
// Done with hbox for calendar and event list // Done with hbox for calendar and event list

View File

@ -573,11 +573,15 @@ var _Draggable = class _Draggable {
while (target) { while (target) {
if (target._delegate && target._delegate.acceptDrop) { if (target._delegate && target._delegate.acceptDrop) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY); let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate, let accepted = false;
this._dragActor, try {
targX, accepted = target._delegate.acceptDrop(this.actor._delegate,
targY, this._dragActor, targX, targY, event.get_time());
event.get_time())) { } catch (e) {
// On error, skip this target
logError(e, "Skipping drag target");
}
if (accepted) {
// If it accepted the drop without taking the actor, // If it accepted the drop without taking the actor,
// handle it ourselves. // handle it ourselves.
if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) { if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {

View File

@ -207,10 +207,10 @@ function _setCheckBoxLabel(checkBox, text) {
if (text) { if (text) {
label.set_text(text); label.set_text(text);
checkBox.actor.show(); checkBox.show();
} else { } else {
label.set_text(''); label.set_text('');
checkBox.actor.hide(); checkBox.hide();
} }
} }
@ -297,8 +297,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
y_align: St.Align.START }); y_align: St.Align.START });
this._checkBox = new CheckBox.CheckBox(); this._checkBox = new CheckBox.CheckBox();
this._checkBox.actor.connect('clicked', this._sync.bind(this)); this._checkBox.connect('clicked', this._sync.bind(this));
messageLayout.add(this._checkBox.actor); messageLayout.add(this._checkBox);
this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning', this._batteryWarning = new St.Label({ style_class: 'end-session-dialog-warning',
text: _("Running on battery power: please plug in before installing updates.") }); text: _("Running on battery power: please plug in before installing updates.") });
@ -376,12 +376,12 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let subject = dialogContent.subject; let subject = dialogContent.subject;
// Use different title when we are installing updates // Use different title when we are installing updates
if (dialogContent.subjectWithUpdates && this._checkBox.actor.checked) if (dialogContent.subjectWithUpdates && this._checkBox.checked)
subject = dialogContent.subjectWithUpdates; subject = dialogContent.subjectWithUpdates;
if (dialogContent.showBatteryWarning) { if (dialogContent.showBatteryWarning) {
// Warn when running on battery power // Warn when running on battery power
if (this._powerProxy.OnBattery && this._checkBox.actor.checked) if (this._powerProxy.OnBattery && this._checkBox.checked)
this._batteryWarning.opacity = 255; this._batteryWarning.opacity = 255;
else else
this._batteryWarning.opacity = 0; this._batteryWarning.opacity = 0;
@ -429,7 +429,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let avatarWidget = new UserWidget.Avatar(this._user, let avatarWidget = new UserWidget.Avatar(this._user,
{ iconSize: _DIALOG_ICON_SIZE, { iconSize: _DIALOG_ICON_SIZE,
styleClass: dialogContent.iconStyleClass }); styleClass: dialogContent.iconStyleClass });
this._iconBin.child = avatarWidget.actor; this._iconBin.child = avatarWidget;
avatarWidget.update(); avatarWidget.update();
} }
@ -485,13 +485,13 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
}; };
// Offline update not available; just emit the signal // Offline update not available; just emit the signal
if (!this._checkBox.actor.visible) { if (!this._checkBox.visible) {
callback(); callback();
return; return;
} }
// Trigger the offline update as requested // Trigger the offline update as requested
if (this._checkBox.actor.checked) { if (this._checkBox.checked) {
switch (signal) { switch (signal) {
case "ConfirmedReboot": case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback); this._triggerOfflineUpdateReboot(callback);
@ -656,7 +656,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item', let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item',
can_focus: true }); can_focus: true });
actor.add(avatar.actor); actor.add(avatar);
let nameLabel = new St.Label({ text: userLabelText, let nameLabel = new St.Label({ text: userLabelText,
style_class: 'end-session-dialog-session-list-item-name', style_class: 'end-session-dialog-session-list-item-name',
@ -754,14 +754,14 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed; let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || ''); _setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
this._checkBox.actor.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed); this._checkBox.visible = (dialogContent.checkBoxText && updatePrepared && updatesAllowed);
this._checkBox.actor.checked = (updatePrepared && updateTriggered); this._checkBox.checked = (updatePrepared && updateTriggered);
// We show the warning either together with the checkbox, or when // We show the warning either together with the checkbox, or when
// updates have already been triggered, but the user doesn't have // updates have already been triggered, but the user doesn't have
// enough permissions to cancel them. // enough permissions to cancel them.
this._batteryWarning.visible = (dialogContent.showBatteryWarning && this._batteryWarning.visible = (dialogContent.showBatteryWarning &&
(this._checkBox.actor.visible || updatePrepared && updateTriggered && !updatesAllowed)); (this._checkBox.visible || updatePrepared && updateTriggered && !updatesAllowed));
this._updateButtons(); this._updateButtons();

View File

@ -105,12 +105,20 @@ function _easeActor(actor, params) {
actor.set_easing_delay(params.delay); actor.set_easing_delay(params.delay);
delete params.delay; delete params.delay;
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
if (params.mode != undefined) if (params.mode != undefined)
actor.set_easing_mode(params.mode); actor.set_easing_mode(params.mode);
delete params.mode; delete params.mode;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display); let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup); let callback = _makeEaseCallback(params, cleanup);
@ -124,11 +132,18 @@ function _easeActor(actor, params) {
let transition = animatedProps.map(p => actor.get_transition(p)) let transition = animatedProps.map(p => actor.get_transition(p))
.find(t => t !== null); .find(t => t !== null);
if (transition) if (transition && transition.delay)
transition.connect('stopped', (t, finished) => callback(finished)); transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
else else
Meta.disable_unredirect_for_display(global.display);
if (transition) {
transition.set({ repeatCount, autoReverse });
transition.connect('stopped', (t, finished) => callback(finished));
} else {
callback(true); callback(true);
} }
}
function _easeActorProperty(actor, propName, target, params) { function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease() // Avoid pointless difference with ease()
@ -140,13 +155,21 @@ function _easeActorProperty(actor, propName, target, params) {
params.duration = adjustAnimationTime(params.duration); params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0); let duration = Math.floor(params.duration || 0);
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
// Copy Clutter's behavior for implicit animations, see // Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition() // should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped) if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0; duration = 0;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display); let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup); let callback = _makeEaseCallback(params, cleanup);
@ -157,6 +180,7 @@ function _easeActorProperty(actor, propName, target, params) {
let [obj, prop] = _getPropertyTarget(actor, propName); let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target; obj[prop] = target;
Meta.disable_unredirect_for_display(global.display);
callback(true); callback(true);
return; return;
@ -166,12 +190,19 @@ function _easeActorProperty(actor, propName, target, params) {
let transition = new Clutter.PropertyTransition(Object.assign({ let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName, property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }), interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true remove_on_complete: true,
repeat_count: repeatCount,
auto_reverse: autoReverse,
}, params)); }, params));
actor.add_transition(propName, transition); actor.add_transition(propName, transition);
transition.set_to(target); 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)); transition.connect('stopped', (t, finished) => callback(finished));
} }

View File

@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */ /* exported CandidatePopup */
const { Clutter, IBus, St } = imports.gi; const { Clutter, GObject, IBus, St } = imports.gi;
const Signals = imports.signals;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -12,11 +11,23 @@ var MAX_CANDIDATES_PER_PAGE = 16;
var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8', var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f']; '9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
var CandidateArea = class CandidateArea { var CandidateArea = GObject.registerClass({
constructor() { Signals: {
this.actor = new St.BoxLayout({ vertical: true, '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, reactive: true,
visible: false }); visible: false
});
this._candidateBoxes = []; this._candidateBoxes = [];
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) { for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
let box = new St.BoxLayout({ style_class: 'candidate-box', let box = new St.BoxLayout({ style_class: 'candidate-box',
@ -27,7 +38,7 @@ var CandidateArea = class CandidateArea {
box.add(box._indexLabel, { y_fill: false }); box.add(box._indexLabel, { y_fill: false });
box.add(box._candidateLabel, { y_fill: false }); box.add(box._candidateLabel, { y_fill: false });
this._candidateBoxes.push(box); this._candidateBoxes.push(box);
this.actor.add(box); this.add(box);
let j = i; let j = i;
box.connect('button-release-event', (actor, event) => { box.connect('button-release-event', (actor, event) => {
@ -36,19 +47,6 @@ var CandidateArea = class CandidateArea {
}); });
} }
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._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' }); this._previousButton = new St.Button({ style_class: 'candidate-page-button candidate-page-button-previous button' });
@ -59,7 +57,7 @@ var CandidateArea = class CandidateArea {
this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' }); this._nextButton.child = new St.Icon({ style_class: 'candidate-page-button-icon' });
this._buttonBox.add(this._nextButton, { expand: true }); this._buttonBox.add(this._nextButton, { expand: true });
this.actor.add(this._buttonBox); this.add(this._buttonBox);
this._previousButton.connect('clicked', () => { this._previousButton.connect('clicked', () => {
this.emit('previous-page'); this.emit('previous-page');
@ -72,6 +70,18 @@ var CandidateArea = class CandidateArea {
this._cursorPosition = 0; 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) { setOrientation(orientation) {
if (this._orientation == orientation) if (this._orientation == orientation)
return; return;
@ -79,15 +89,15 @@ var CandidateArea = class CandidateArea {
this._orientation = orientation; this._orientation = orientation;
if (this._orientation == IBus.Orientation.HORIZONTAL) { if (this._orientation == IBus.Orientation.HORIZONTAL) {
this.actor.vertical = false; this.vertical = false;
this.actor.remove_style_class_name('vertical'); this.remove_style_class_name('vertical');
this.actor.add_style_class_name('horizontal'); this.add_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-previous-symbolic'; this._previousButton.child.icon_name = 'go-previous-symbolic';
this._nextButton.child.icon_name = 'go-next-symbolic'; this._nextButton.child.icon_name = 'go-next-symbolic';
} else { // VERTICAL || SYSTEM } else { // VERTICAL || SYSTEM
this.actor.vertical = true; this.vertical = true;
this.actor.add_style_class_name('vertical'); this.add_style_class_name('vertical');
this.actor.remove_style_class_name('horizontal'); this.remove_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-up-symbolic'; this._previousButton.child.icon_name = 'go-up-symbolic';
this._nextButton.child.icon_name = 'go-down-symbolic'; this._nextButton.child.icon_name = 'go-down-symbolic';
} }
@ -121,22 +131,23 @@ var CandidateArea = class CandidateArea {
this._previousButton.reactive = wrapsAround || page > 0; this._previousButton.reactive = wrapsAround || page > 0;
this._nextButton.reactive = wrapsAround || page < nPages - 1; this._nextButton.reactive = wrapsAround || page < nPages - 1;
} }
}; });
Signals.addSignalMethods(CandidateArea.prototype);
var CandidatePopup = GObject.registerClass(
class IbusCandidatePopup extends BoxPointer.BoxPointer {
_init() {
super._init(St.Side.TOP);
this.visible = false;
this.style_class = 'candidate-popup-boxpointer';
var CandidatePopup = class CandidatePopup {
constructor() {
this._dummyCursor = new St.Widget({ opacity: 0 }); this._dummyCursor = new St.Widget({ opacity: 0 });
Main.layoutManager.uiGroup.add_actor(this._dummyCursor); Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP); Main.layoutManager.addChrome(this);
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', let box = new St.BoxLayout({ style_class: 'candidate-popup-content',
vertical: true }); vertical: true });
this._boxPointer.bin.set_child(box); this.bin.set_child(box);
this._preeditText = new St.Label({ style_class: 'candidate-popup-text', this._preeditText = new St.Label({ style_class: 'candidate-popup-text',
visible: false }); visible: false });
@ -147,7 +158,7 @@ var CandidatePopup = class CandidatePopup {
box.add(this._auxText); box.add(this._auxText);
this._candidateArea = new CandidateArea(); this._candidateArea = new CandidateArea();
box.add(this._candidateArea.actor); box.add(this._candidateArea);
this._candidateArea.connect('previous-page', () => { this._candidateArea.connect('previous-page', () => {
this._panelService.page_up(); this._panelService.page_up();
@ -225,7 +236,7 @@ var CandidatePopup = class CandidatePopup {
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => { panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
this._candidateArea.actor.visible = visible; this._candidateArea.visible = visible;
this._updateVisibility(); this._updateVisibility();
let nCandidates = lookupTable.get_number_of_candidates(); let nCandidates = lookupTable.get_number_of_candidates();
@ -261,15 +272,15 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages); this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
}); });
panelService.connect('show-lookup-table', () => { panelService.connect('show-lookup-table', () => {
this._candidateArea.actor.show(); this._candidateArea.show();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('hide-lookup-table', () => { panelService.connect('hide-lookup-table', () => {
this._candidateArea.actor.hide(); this._candidateArea.hide();
this._updateVisibility(); this._updateVisibility();
}); });
panelService.connect('focus-out', () => { panelService.connect('focus-out', () => {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE); this.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions(); Main.keyboard.resetSuggestions();
}); });
} }
@ -278,22 +289,22 @@ var CandidatePopup = class CandidatePopup {
this._dummyCursor.set_position(Math.round(x), Math.round(y)); this._dummyCursor.set_position(Math.round(x), Math.round(y));
this._dummyCursor.set_size(Math.round(w), Math.round(h)); this._dummyCursor.set_size(Math.round(w), Math.round(h));
if (this._boxPointer.visible) if (this.visible)
this._boxPointer.setPosition(this._dummyCursor, 0); this.setPosition(this._dummyCursor, 0);
} }
_updateVisibility() { _updateVisibility() {
let isVisible = (!Main.keyboard.visible && let isVisible = (!Main.keyboard.visible &&
(this._preeditText.visible || (this._preeditText.visible ||
this._auxText.visible || this._auxText.visible ||
this._candidateArea.actor.visible)); this._candidateArea.visible));
if (isVisible) { if (isVisible) {
this._boxPointer.setPosition(this._dummyCursor, 0); this.setPosition(this._dummyCursor, 0);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE); this.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.raise_top(); this.raise_top();
} else { } else {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE); this.close(BoxPointer.PopupAnimation.NONE);
} }
} }
@ -303,4 +314,4 @@ var CandidatePopup = class CandidatePopup {
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND) if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
clutterText.set_selection(attr.get_start_index(), attr.get_end_index()); 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 -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, PaginatedIconGrid */ /* exported BaseIcon, IconGrid, PaginatedIconGrid */
const { Clutter, GLib, GObject, Meta, St } = imports.gi; const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
const Params = imports.misc.params; const Params = imports.misc.params;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -231,18 +231,18 @@ var IconGrid = GObject.registerClass({
this._fixedHItemSize = this._fixedVItemSize = undefined; this._fixedHItemSize = this._fixedVItemSize = undefined;
this.connect('style-changed', this._onStyleChanged.bind(this)); 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-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this)); this.connect('actor-removed', this._childRemoved.bind(this));
this.connect('destroy', this._onDestroy.bind(this)); 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() { _onDestroy() {
if (this._updateIconSizesLaterId) { if (this._updateIconSizesLaterId) {
Meta.later_remove (this._updateIconSizesLaterId); Meta.later_remove (this._updateIconSizesLaterId);
@ -402,7 +402,7 @@ var IconGrid = GObject.registerClass({
let allocationBox = this.get_allocation_box(); let allocationBox = this.get_allocation_box();
let paintBox = themeNode.get_paint_box(allocationBox); let paintBox = themeNode.get_paint_box(allocationBox);
let origin = new Clutter.Vertex(); let origin = new Graphene.Point3D();
origin.x = paintBox.x1 - allocationBox.x1; origin.x = paintBox.x1 - allocationBox.x1;
origin.y = paintBox.y1 - allocationBox.y1; origin.y = paintBox.y1 - allocationBox.y1;
origin.z = 0.0; origin.z = 0.0;
@ -717,13 +717,13 @@ var IconGrid = GObject.registerClass({
this._items.push(item); this._items.push(item);
if (index !== undefined) if (index !== undefined)
this.insert_child_at_index(item.actor, index); this.insert_child_at_index(item, index);
else else
this.add_actor(item.actor); this.add_actor(item);
} }
removeItem(item) { removeItem(item) {
this.remove_child(item.actor); this.remove_child(item);
} }
getItemAtIndex(index) { getItemAtIndex(index) {
@ -963,7 +963,7 @@ var PaginatedIconGrid = GObject.registerClass({
*/ */
openExtraSpace(sourceItem, side, nRows) { openExtraSpace(sourceItem, side, nRows) {
let children = this._getVisibleChildren(); let children = this._getVisibleChildren();
let index = children.indexOf(sourceItem.actor); let index = children.indexOf(sourceItem);
if (index == -1) if (index == -1)
throw new Error('Item not found.'); throw new Error('Item not found.');

View File

@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Keyboard */ /* exported KeyboardManager */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
@ -89,8 +89,11 @@ class KeyContainer extends St.Widget {
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL, let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
column_homogeneous: true, column_homogeneous: true,
row_homogeneous: true }); row_homogeneous: true });
super._init({ layout_manager: gridLayout, super._init({
x_expand: true, y_expand: true }); layout_manager: gridLayout,
x_expand: true,
y_expand: true
});
this._gridLayout = gridLayout; this._gridLayout = gridLayout;
this._currentRow = 0; this._currentRow = 0;
this._currentCol = 0; this._currentCol = 0;
@ -161,24 +164,23 @@ class KeyContainer extends St.Widget {
} }
}); });
var Suggestions = class { var Suggestions = GObject.registerClass(
constructor() { class Suggestions extends St.BoxLayout {
this.actor = new St.BoxLayout({ style_class: 'word-suggestions', _init() {
vertical: false }); super._init({ style_class: 'word-suggestions', vertical: false });
this.actor.show(); this.show();
} }
add(word, callback) { add(word, callback) {
let button = new St.Button({ label: word }); let button = new St.Button({ label: word });
button.connect('clicked', callback); button.connect('clicked', callback);
this.actor.add(button); this.add(button);
} }
clear() { clear() {
this.actor.remove_all_children(); this.remove_all_children();
} }
}; });
Signals.addSignalMethods(Suggestions.prototype);
var LanguageSelectionPopup = class extends PopupMenu.PopupMenu { var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
constructor(actor) { constructor(actor) {
@ -243,17 +245,25 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
} }
}; };
var Key = class Key { var Key = GObject.registerClass({
constructor(key, extendedKeys) { Signals: {
'activated': {},
'long-press': {},
'pressed': { param_types: [GObject.TYPE_UINT, GObject.TYPE_STRING] },
'released': { param_types: [GObject.TYPE_UINT, GObject.TYPE_STRING] },
}
}, class Key extends St.BoxLayout {
_init(key, extendedKeys) {
super._init({ style_class: 'key-container' });
this.key = key || ""; this.key = key || "";
this.keyButton = this._makeKey(this.key); this.keyButton = this._makeKey(this.key);
/* Add the key in a container, so keys can be padded without losing /* Add the key in a container, so keys can be padded without losing
* logical proportions between those. * logical proportions between those.
*/ */
this.actor = new St.BoxLayout ({ style_class: 'key-container' }); this.add(this.keyButton, { expand: true, x_fill: true });
this.actor.add(this.keyButton, { expand: true, x_fill: true }); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._extended_keys = extendedKeys; this._extended_keys = extendedKeys;
this._extended_keyboard = null; this._extended_keyboard = null;
@ -461,8 +471,7 @@ var Key = class Key {
else else
this.keyButton.remove_style_pseudo_class('latched'); this.keyButton.remove_style_pseudo_class('latched');
} }
}; });
Signals.addSignalMethods(Key.prototype);
var KeyboardModel = class { var KeyboardModel = class {
constructor(groupName) { constructor(groupName) {
@ -590,7 +599,6 @@ var EmojiPager = GObject.registerClass({
reactive: true, reactive: true,
clip_to_allocation: true clip_to_allocation: true
}); });
this._sections = sections; this._sections = sections;
this._nCols = nCols; this._nCols = nCols;
this._nRows = nRows; this._nRows = nRows;
@ -801,7 +809,7 @@ var EmojiPager = GObject.registerClass({
this.emit('emoji', str); this.emit('emoji', str);
}); });
gridLayout.attach(key.actor, col, row, 1, 1); gridLayout.attach(key, col, row, 1, 1);
col++; col++;
if (col >= this._nCols) { if (col >= this._nCols) {
@ -843,7 +851,7 @@ var EmojiPager = GObject.registerClass({
} }
let page = this._pages[nPage]; let page = this._pages[nPage];
this.emit('page-changed', page.section, page.page, page.nPages); this.emit('page-changed', page.section.label, page.page, page.nPages);
} }
setCurrentSection(section, nPage) { setCurrentSection(section, nPage) {
@ -858,8 +866,21 @@ var EmojiPager = GObject.registerClass({
} }
}); });
var EmojiSelection = class EmojiSelection { var EmojiSelection = GObject.registerClass({
constructor() { Signals: {
'emoji-selected': { param_types: [GObject.TYPE_STRING] },
'close-request': {},
'toggle': {},
}
}, class EmojiSelection extends St.BoxLayout {
_init() {
super._init({
style_class: 'emoji-panel',
x_expand: true,
y_expand: true,
vertical: true
});
this._sections = [ this._sections = [
{ first: 'grinning face', label: '🙂️' }, { first: 'grinning face', label: '🙂️' },
{ first: 'selfie', label: '👍️' }, { first: 'selfie', label: '👍️' },
@ -874,38 +895,44 @@ var EmojiSelection = class EmojiSelection {
this._populateSections(); this._populateSections();
this.actor = new St.BoxLayout({ style_class: 'emoji-panel',
x_expand: true,
y_expand: true,
vertical: true });
this.actor.connect('notify::mapped', () => this._emojiPager.setCurrentPage(0));
this._emojiPager = new EmojiPager(this._sections, 11, 3); this._emojiPager = new EmojiPager(this._sections, 11, 3);
this._emojiPager.connect('page-changed', (pager, section, page, nPages) => { this._emojiPager.connect('page-changed', (pager, sectionLabel, page, nPages) => {
this._onPageChanged(section, page, nPages); this._onPageChanged(sectionLabel, page, nPages);
}); });
this._emojiPager.connect('emoji', (pager, str) => { this._emojiPager.connect('emoji', (pager, str) => {
this.emit('emoji-selected', str); this.emit('emoji-selected', str);
}); });
this.actor.add(this._emojiPager.actor, { expand: true }); this.add(this._emojiPager, { expand: true });
this._pageIndicator = new PageIndicators.PageIndicators(false); this._pageIndicator = new PageIndicators.PageIndicators(
this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false }); Clutter.Orientation.HORIZONTAL
);
this.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
this._pageIndicator.setReactive(false); this._pageIndicator.setReactive(false);
let bottomRow = this._createBottomRow(); let bottomRow = this._createBottomRow();
this.actor.add(bottomRow, { expand: true, x_fill: false, y_fill: false }); this.add(bottomRow, { expand: true, x_fill: false, y_fill: false });
this._emojiPager.setCurrentPage(0); this._emojiPager.setCurrentPage(0);
} }
_onPageChanged(section, page, nPages) { vfunc_map() {
this._emojiPager.setCurrentPage(0);
super.vfunc_map();
}
vfunc_unmap() {
super.vfunc_unmap();
this._emojiPager.setCurrentPage(0);
}
_onPageChanged(sectionLabel, page, nPages) {
this._pageIndicator.setNPages(nPages); this._pageIndicator.setNPages(nPages);
this._pageIndicator.setCurrentPage(page); this._pageIndicator.setCurrentPage(page);
for (let i = 0; i < this._sections.length; i++) { for (let i = 0; i < this._sections.length; i++) {
let sect = this._sections[i]; let sect = this._sections[i];
sect.button.setLatched(section == sect); sect.button.setLatched(sectionLabel == sect.label);
} }
} }
@ -961,14 +988,14 @@ var EmojiSelection = class EmojiSelection {
key = new Key('ABC', []); key = new Key('ABC', []);
key.keyButton.add_style_class_name('default-key'); key.keyButton.add_style_class_name('default-key');
key.connect('released', () => this.emit('toggle')); key.connect('released', () => this.emit('toggle'));
row.appendKey(key.actor, 1.5); row.appendKey(key, 1.5);
for (let i = 0; i < this._sections.length; i++) { for (let i = 0; i < this._sections.length; i++) {
let section = this._sections[i]; let section = this._sections[i];
key = new Key(section.label, []); key = new Key(section.label, []);
key.connect('released', () => this._emojiPager.setCurrentSection(section, 0)); key.connect('released', () => this._emojiPager.setCurrentSection(section, 0));
row.appendKey(key.actor); row.appendKey(key);
section.button = key; section.button = key;
} }
@ -977,9 +1004,9 @@ var EmojiSelection = class EmojiSelection {
key.keyButton.add_style_class_name('default-key'); key.keyButton.add_style_class_name('default-key');
key.keyButton.add_style_class_name('hide-key'); key.keyButton.add_style_class_name('hide-key');
key.connect('released', () => { key.connect('released', () => {
this.emit('hide'); this.emit('close-request');
}); });
row.appendKey(key.actor); row.appendKey(key);
row.layoutButtons(); row.layoutButtons();
let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(), let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
@ -993,11 +1020,14 @@ var EmojiSelection = class EmojiSelection {
return actor; return actor;
} }
}; });
Signals.addSignalMethods(EmojiSelection.prototype);
var Keypad = class Keypad { var Keypad = GObject.registerClass({
constructor() { Signals: {
'keyval': { param_types: [GObject.TYPE_UINT] },
}
}, class Keypad extends AspectContainer {
_init() {
let keys = [ let keys = [
{ label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 }, { label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 },
{ label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 }, { label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 },
@ -1013,14 +1043,17 @@ var Keypad = class Keypad {
{ keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 }, { keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 },
]; ];
this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(), super._init({
x_expand: true, y_expand: true }); layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true
});
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL, let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
column_homogeneous: true, column_homogeneous: true,
row_homogeneous: true }); row_homogeneous: true });
this._box = new St.Widget({ layout_manager: gridLayout, x_expand: true, y_expand: true }); this._box = new St.Widget({ layout_manager: gridLayout, x_expand: true, y_expand: true });
this.actor.add_child(this._box); this.add_child(this._box);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
let cur = keys[i]; let cur = keys[i];
@ -1032,86 +1065,32 @@ var Keypad = class Keypad {
let w, h; let w, h;
w = cur.width || 1; w = cur.width || 1;
h = cur.height || 1; h = cur.height || 1;
gridLayout.attach(key.actor, cur.left, cur.top, w, h); gridLayout.attach(key, cur.left, cur.top, w, h);
key.connect('released', () => { key.connect('released', () => {
this.emit('keyval', cur.keyval); this.emit('keyval', cur.keyval);
}); });
} }
} }
}; });
Signals.addSignalMethods(Keypad.prototype);
var Keyboard = class Keyboard { var KeyboardManager = class KeyBoardManager {
constructor() { constructor() {
this.actor = null; this._keyboard = null;
this._focusInExtendedKeys = false;
this._emojiActive = false;
this._languagePopup = null;
this._currentFocusWindow = null;
this._animFocusedWindow = null;
this._delayedAnimFocusWindow = null;
this._enableKeyboard = false; // a11y settings value
this._enabled = false; // enabled state (by setting or device type)
this._latched = false; // current level is latched
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA }); this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this)); this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
this._lastDeviceId = null; this._lastDeviceId = null;
this._suggestions = null; Meta.get_backend().connect('last-device-changed', (backend, deviceId) => {
this._emojiKeyVisible = Meta.is_wayland_compositor();
this._focusTracker = new FocusTracker();
this._focusTracker.connect('position-changed', this._onFocusPositionChanged.bind(this));
this._focusTracker.connect('reset', () => {
this._delayedAnimFocusWindow = null;
this._animFocusedWindow = null;
this._oskFocusWindow = null;
});
this._focusTracker.connect('focus-changed', (tracker, focused) => {
// Valid only for X11
if (Meta.is_wayland_compositor())
return;
if (focused)
this.show(Main.layoutManager.focusIndex);
else
this.hide();
});
Meta.get_backend().connect('last-device-changed',
(backend, deviceId) => {
let manager = Clutter.DeviceManager.get_default(); let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId); let device = manager.get_device(deviceId);
if (!device.get_device_name().includes('XTEST')) { if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDeviceId = deviceId; this._lastDeviceId = deviceId;
this._syncEnabled(); this._syncEnabled();
} }
}); });
this._syncEnabled(); this._syncEnabled();
this._showIdleId = 0;
this._keyboardVisible = false;
Main.layoutManager.connect('keyboard-visible-changed', (o, visible) => {
this._keyboardVisible = visible;
});
this._keyboardRequested = false;
this._keyboardRestingId = 0;
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
}
get visible() {
return this._keyboardVisible;
}
_onFocusPositionChanged(focusTracker) {
let rect = focusTracker.getCurrentRect();
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
} }
_lastDeviceIsTouchscreen() { _lastDeviceIsTouchscreen() {
@ -1128,38 +1107,143 @@ var Keyboard = class Keyboard {
} }
_syncEnabled() { _syncEnabled() {
let wasEnabled = this._enabled; let enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD); let enabled = enableKeyboard || this._lastDeviceIsTouchscreen();
this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen(); if (!enabled && !this._keyboard)
if (!this._enabled && !this._keyboardController)
return; return;
if (this._enabled && !this._keyboardController) if (enabled && !this._keyboard) {
this._setupKeyboard(); this._keyboard = new Keyboard();
else if (!this._enabled) } else if (!enabled && this._keyboard) {
this.setCursorLocation(null); this._keyboard.setCursorLocation(null);
if (!this._enabled && wasEnabled)
Main.layoutManager.hideKeyboard(true); Main.layoutManager.hideKeyboard(true);
this._keyboard.destroy();
this._keyboard = null;
}
} }
_destroyKeyboard() { get keyboardActor() {
if (this._keyboardNotifyId) return this._keyboard;
this._keyboardController.disconnect(this._keyboardNotifyId); }
if (this._keyboardGroupsChangedId)
this._keyboardController.disconnect(this._keyboardGroupsChangedId); get visible() {
if (this._keyboardStateId) return this._keyboard && this._keyboard.visible;
this._keyboardController.disconnect(this._keyboardStateId); }
if (this._emojiKeyVisibleId)
this._keyboardController.disconnect(this._emojiKeyVisibleId); open(monitor) {
if (this._keypadVisibleId) if (this._keyboard)
this._keyboardController.disconnect(this._keypadVisibleId); this._keyboard.open(monitor);
if (this._focusNotifyId) }
global.stage.disconnect(this._focusNotifyId);
close() {
if (this._keyboard)
this._keyboard.close();
}
addSuggestion(text, callback) {
if (this._keyboard)
this._keyboard.addSuggestion(text, callback);
}
resetSuggestions() {
if (this._keyboard)
this._keyboard.resetSuggestions();
}
shouldTakeEvent(event) {
if (!this._keyboard)
return false;
let actor = event.get_source();
return Main.layoutManager.keyboardBox.contains(actor) ||
!!actor._extended_keys || !!actor.extended_key;
}
};
var Keyboard = GObject.registerClass(
class Keyboard extends St.BoxLayout {
_init() {
super._init({ name: 'keyboard', vertical: true });
this._focusInExtendedKeys = false;
this._emojiActive = false;
this._languagePopup = null;
this._currentFocusWindow = null;
this._animFocusedWindow = null;
this._delayedAnimFocusWindow = null;
this._latched = false; // current level is latched
this._suggestions = null;
this._emojiKeyVisible = Meta.is_wayland_compositor();
this._focusTracker = new FocusTracker();
this._connectSignal(this._focusTracker, 'position-changed',
this._onFocusPositionChanged.bind(this));
this._connectSignal(this._focusTracker, 'reset', () => {
this._delayedAnimFocusWindow = null;
this._animFocusedWindow = null;
this._oskFocusWindow = null;
});
// Valid only for X11
if (!Meta.is_wayland_compositor()) {
this._connectSignal(this._focusTracker, 'focus-changed', (_tracker, focused) => {
if (focused)
this.open(Main.layoutManager.focusIndex);
else
this.close();
});
}
this._showIdleId = 0;
this._keyboardVisible = false;
this._connectSignal(Main.layoutManager, 'keyboard-visible-changed', (_lm, visible) => {
this._keyboardVisible = visible;
});
this._keyboardRequested = false;
this._keyboardRestingId = 0;
this._connectSignal(Main.layoutManager, 'monitors-changed', this._relayout.bind(this));
this._setupKeyboard();
this.connect('destroy', this._onDestroy.bind(this));
}
_connectSignal(obj, signal, callback) {
if (!this._connectionsIDs)
this._connectionsIDs = [];
let id = obj.connect(signal, callback);
this._connectionsIDs.push([obj, id]);
return id;
}
get visible() {
return this._keyboardVisible && super.visible;
}
_onFocusPositionChanged(focusTracker) {
let rect = focusTracker.getCurrentRect();
this.setCursorLocation(focusTracker.currentWindow, rect.x, rect.y, rect.width, rect.height);
}
_onDestroy() {
for (let [obj, id] of this._connectionsIDs)
obj.disconnect(id);
delete this._connectionsIDs;
this._clearShowIdle(); this._clearShowIdle();
this._keyboard = null;
this.actor.destroy(); this._keyboardController = null;
this.actor = null; this._suggestions = null;
this._aspectContainer = null;
this._emojiSelection = null;
this._keypad = null;
Main.layoutManager.untrackChrome(this);
Main.layoutManager.keyboardBox.remove_actor(this);
if (this._languagePopup) { if (this._languagePopup) {
this._languagePopup.destroy(); this._languagePopup.destroy();
@ -1168,9 +1252,8 @@ var Keyboard = class Keyboard {
} }
_setupKeyboard() { _setupKeyboard() {
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true }); Main.layoutManager.keyboardBox.add_actor(this);
Main.layoutManager.keyboardBox.add_actor(this.actor); Main.layoutManager.trackChrome(this);
Main.layoutManager.trackChrome(this.actor);
this._keyboardController = new KeyboardController(); this._keyboardController = new KeyboardController();
@ -1178,30 +1261,28 @@ var Keyboard = class Keyboard {
this._currentPage = null; this._currentPage = null;
this._suggestions = new Suggestions(); this._suggestions = new Suggestions();
this.actor.add(this._suggestions.actor, this.add(this._suggestions, { x_align: St.Align.MIDDLE, x_fill: false });
{ x_align: St.Align.MIDDLE,
x_fill: false });
this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() }); this._aspectContainer = new AspectContainer({ layout_manager: new Clutter.BinLayout() });
this.actor.add(this._aspectContainer, { expand: true }); this.add(this._aspectContainer, { expand: true });
this._emojiSelection = new EmojiSelection(); this._emojiSelection = new EmojiSelection();
this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this)); this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
this._emojiSelection.connect('hide', () => this.hide()); this._emojiSelection.connect('close-request', () => this.close());
this._emojiSelection.connect('emoji-selected', (selection, emoji) => { this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
this._keyboardController.commitString(emoji); this._keyboardController.commitString(emoji);
}); });
this._aspectContainer.add_child(this._emojiSelection.actor); this._aspectContainer.add_child(this._emojiSelection);
this._emojiSelection.actor.hide(); this._emojiSelection.hide();
this._keypad = new Keypad(); this._keypad = new Keypad();
this._keypad.connect('keyval', (keypad, keyval) => { this._connectSignal(this._keypad, 'keyval', (_keypad, keyval) => {
this._keyboardController.keyvalPress(keyval); this._keyboardController.keyvalPress(keyval);
this._keyboardController.keyvalRelease(keyval); this._keyboardController.keyvalRelease(keyval);
}); });
this._aspectContainer.add_child(this._keypad.actor); this._aspectContainer.add_child(this._keypad);
this._keypad.actor.hide(); this._keypad.hide();
this._keypadVisible = false; this._keypadVisible = false;
this._ensureKeysForGroup(this._keyboardController.getCurrentGroup()); this._ensureKeysForGroup(this._keyboardController.getCurrentGroup());
@ -1210,16 +1291,22 @@ var Keyboard = class Keyboard {
// Keyboard models are defined in LTR, we must override // Keyboard models are defined in LTR, we must override
// the locale setting in order to avoid flipping the // the locale setting in order to avoid flipping the
// keyboard on RTL locales. // keyboard on RTL locales.
this.actor.text_direction = Clutter.TextDirection.LTR; this.text_direction = Clutter.TextDirection.LTR;
this._keyboardNotifyId = this._keyboardController.connect('active-group', this._onGroupChanged.bind(this)); this._connectSignal(this._keyboardController, 'active-group',
this._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed', this._onKeyboardGroupsChanged.bind(this)); this._onGroupChanged.bind(this));
this._keyboardStateId = this._keyboardController.connect('panel-state', this._onKeyboardStateChanged.bind(this)); this._connectSignal(this._keyboardController, 'groups-changed',
this._keypadVisibleId = this._keyboardController.connect('keypad-visible', this._onKeypadVisible.bind(this)); this._onKeyboardGroupsChanged.bind(this));
this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this)); this._connectSignal(this._keyboardController, 'panel-state',
this._onKeyboardStateChanged.bind(this));
this._connectSignal(this._keyboardController, 'keypad-visible',
this._onKeypadVisible.bind(this));
this._connectSignal(global.stage, 'notify::key-focus',
this._onKeyFocusChanged.bind(this));
if (Meta.is_wayland_compositor()) if (Meta.is_wayland_compositor())
this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this)); this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
this._relayout(); this._relayout();
} }
@ -1235,17 +1322,17 @@ var Keyboard = class Keyboard {
return; return;
if (!(focus instanceof Clutter.Text)) { if (!(focus instanceof Clutter.Text)) {
this.hide(); this.close();
return; return;
} }
if (!this._showIdleId) { if (!this._showIdleId) {
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex); this.open(Main.layoutManager.focusIndex);
this._showIdleId = 0; this._showIdleId = 0;
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show'); GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.open');
} }
} }
@ -1309,7 +1396,7 @@ var Keyboard = class Keyboard {
this._setActiveLayer(0); this._setActiveLayer(0);
}); });
layout.appendKey(button.actor, button.keyButton.keyWidth); layout.appendKey(button, button.keyButton.keyWidth);
} }
} }
@ -1357,7 +1444,7 @@ var Keyboard = class Keyboard {
if (keyval != null) if (keyval != null)
this._keyboardController.keyvalRelease(keyval); this._keyboardController.keyvalRelease(keyval);
else if (action == 'hide') else if (action == 'hide')
this.hide(); this.close();
else if (action == 'languageMenu') else if (action == 'languageMenu')
this._popupLanguageMenu(actor); this._popupLanguageMenu(actor);
else if (action == 'emoji') else if (action == 'emoji')
@ -1380,7 +1467,7 @@ var Keyboard = class Keyboard {
/* Only hide the key actor, so the container still takes space */ /* Only hide the key actor, so the container still takes space */
extraButton.keyButton.hide(); extraButton.keyButton.hide();
} else { } else {
extraButton.actor.hide(); extraButton.hide();
} }
extraButton.setWidth(1.5); extraButton.setWidth(1.5);
} else if (key.right && numKeys > 8) { } else if (key.right && numKeys > 8) {
@ -1391,7 +1478,7 @@ var Keyboard = class Keyboard {
extraButton.setWidth(1.5); extraButton.setWidth(1.5);
} }
layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth); layout.appendKey(extraButton, extraButton.keyButton.keyWidth);
} }
} }
@ -1402,7 +1489,7 @@ var Keyboard = class Keyboard {
_setEmojiActive(active) { _setEmojiActive(active) {
this._emojiActive = active; this._emojiActive = active;
this._emojiSelection.actor.visible = this._emojiActive; this._emojiSelection.visible = this._emojiActive;
this._updateCurrentPageVisible(); this._updateCurrentPageVisible();
} }
@ -1470,12 +1557,12 @@ var Keyboard = class Keyboard {
_relayout() { _relayout() {
let monitor = Main.layoutManager.keyboardMonitor; let monitor = Main.layoutManager.keyboardMonitor;
if (this.actor == null || monitor == null) if (!monitor)
return; return;
let maxHeight = monitor.height / 3; let maxHeight = monitor.height / 3;
this.actor.width = monitor.width; this.width = monitor.width;
this.actor.height = maxHeight; this.height = maxHeight;
} }
_onGroupChanged() { _onGroupChanged() {
@ -1484,7 +1571,7 @@ var Keyboard = class Keyboard {
} }
_onKeyboardGroupsChanged() { _onKeyboardGroupsChanged() {
let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor]; let nonGroupActors = [this._emojiSelection, this._keypad];
this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => { this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
c.destroy(); c.destroy();
}); });
@ -1498,7 +1585,7 @@ var Keyboard = class Keyboard {
return; return;
this._keypadVisible = visible; this._keypadVisible = visible;
this._keypad.actor.visible = this._keypadVisible; this._keypad.visible = this._keypadVisible;
this._updateCurrentPageVisible(); this._updateCurrentPageVisible();
} }
@ -1523,9 +1610,9 @@ var Keyboard = class Keyboard {
return; return;
if (enabled) if (enabled)
this.show(Main.layoutManager.focusIndex); this.open(Main.layoutManager.focusIndex);
else else
this.hide(); this.close();
} }
_setActiveLayer(activeLevel) { _setActiveLayer(activeLevel) {
@ -1552,12 +1639,6 @@ var Keyboard = class Keyboard {
this._updateCurrentPageVisible(); this._updateCurrentPageVisible();
} }
shouldTakeEvent(event) {
let actor = event.get_source();
return Main.layoutManager.keyboardBox.contains(actor) ||
!!actor._extended_keys || !!actor.extended_key;
}
_clearKeyboardRestTimer() { _clearKeyboardRestTimer() {
if (!this._keyboardRestingId) if (!this._keyboardRestingId)
return; return;
@ -1565,10 +1646,7 @@ var Keyboard = class Keyboard {
this._keyboardRestingId = 0; this._keyboardRestingId = 0;
} }
show(monitor) { open(monitor) {
if (!this._enabled)
return;
this._clearShowIdle(); this._clearShowIdle();
this._keyboardRequested = true; this._keyboardRequested = true;
@ -1585,13 +1663,13 @@ var Keyboard = class Keyboard {
KEYBOARD_REST_TIME, KEYBOARD_REST_TIME,
() => { () => {
this._clearKeyboardRestTimer(); this._clearKeyboardRestTimer();
this._show(monitor); this._open(monitor);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
} }
_show(monitor) { _open(monitor) {
if (!this._keyboardRequested) if (!this._keyboardRequested)
return; return;
@ -1607,10 +1685,7 @@ var Keyboard = class Keyboard {
} }
} }
hide() { close() {
if (!this._enabled)
return;
this._clearShowIdle(); this._clearShowIdle();
this._keyboardRequested = false; this._keyboardRequested = false;
@ -1622,13 +1697,13 @@ var Keyboard = class Keyboard {
KEYBOARD_REST_TIME, KEYBOARD_REST_TIME,
() => { () => {
this._clearKeyboardRestTimer(); this._clearKeyboardRestTimer();
this._hide(); this._close();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer'); GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
} }
_hide() { _close() {
if (this._keyboardRequested) if (this._keyboardRequested)
return; return;
@ -1645,7 +1720,7 @@ var Keyboard = class Keyboard {
if (!this._suggestions) if (!this._suggestions)
return; return;
this._suggestions.add(text, callback); this._suggestions.add(text, callback);
this._suggestions.actor.show(); this._suggestions.show();
} }
_clearShowIdle() { _clearShowIdle() {
@ -1722,7 +1797,7 @@ var Keyboard = class Keyboard {
this._oskFocusWindow = window; this._oskFocusWindow = window;
} }
}; });
var KeyboardController = class { var KeyboardController = class {
constructor() { constructor() {

View File

@ -606,17 +606,17 @@ var LayoutManager = GObject.registerClass({
return; return;
} }
this._systemBackground = new Background.SystemBackground(); this._systemBackground = new Background.SystemBackground();
this._systemBackground.actor.hide(); this._systemBackground.hide();
global.stage.insert_child_below(this._systemBackground.actor, null); global.stage.insert_child_below(this._systemBackground, null);
let constraint = new Clutter.BindConstraint({ source: global.stage, let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL }); coordinate: Clutter.BindCoordinate.ALL });
this._systemBackground.actor.add_constraint(constraint); this._systemBackground.add_constraint(constraint);
let signalId = this._systemBackground.connect('loaded', () => { let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId); this._systemBackground.disconnect(signalId);
this._systemBackground.actor.show(); this._systemBackground.show();
global.stage.show(); global.stage.show();
this._prepareStartupAnimation(); this._prepareStartupAnimation();
@ -722,7 +722,7 @@ var LayoutManager = GObject.registerClass({
this._coverPane.destroy(); this._coverPane.destroy();
this._coverPane = null; this._coverPane = null;
this._systemBackground.actor.destroy(); this._systemBackground.destroy();
this._systemBackground = null; this._systemBackground = null;
this._startingUp = false; this._startingUp = false;
@ -1112,8 +1112,11 @@ var LayoutManager = GObject.registerClass({
// //
// This class manages a "hot corner" that can toggle switching to // This class manages a "hot corner" that can toggle switching to
// overview. // overview.
var HotCorner = class HotCorner { var HotCorner = GObject.registerClass(
constructor(layoutManager, monitor, x, y) { class HotCorner extends Clutter.Actor {
_init(layoutManager, monitor, x, y) {
super._init();
// We use this flag to mark the case where the user has entered the // 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 // hot corner and has not left both the hot corner and a surrounding
// guard area (the "environs"). This avoids triggering the hot corner // guard area (the "environs"). This avoids triggering the hot corner
@ -1142,6 +1145,8 @@ var HotCorner = class HotCorner {
this._ripples = new Ripples.Ripples(px, py, 'ripple-box'); this._ripples = new Ripples.Ripples(px, py, 'ripple-box');
this._ripples.addTo(layoutManager.uiGroup); this._ripples.addTo(layoutManager.uiGroup);
this.connect('destroy', this._onDestroy.bind(this));
} }
setBarrierSize(size) { setBarrierSize(size) {
@ -1181,11 +1186,14 @@ var HotCorner = class HotCorner {
_setupFallbackCornerIfNeeded(layoutManager) { _setupFallbackCornerIfNeeded(layoutManager) {
if (!global.display.supports_extended_barriers()) { if (!global.display.supports_extended_barriers()) {
this.actor = new Clutter.Actor({ name: 'hot-corner-environs', this.set({
x: this._x, y: this._y, name: 'hot-corner-environs',
x: this._x,
y: this._y,
width: 3, width: 3,
height: 3, height: 3,
reactive: true }); reactive: true
});
this._corner = new Clutter.Actor({ name: 'hot-corner', this._corner = new Clutter.Actor({ name: 'hot-corner',
width: 1, width: 1,
@ -1194,19 +1202,16 @@ var HotCorner = class HotCorner {
reactive: true }); reactive: true });
this._corner._delegate = this; this._corner._delegate = this;
this.actor.add_child(this._corner); this.add_child(this._corner);
layoutManager.addChrome(this.actor); layoutManager.addChrome(this);
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) { if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
this._corner.set_position(this.actor.width - this._corner.width, 0); this._corner.set_position(this.width - this._corner.width, 0);
this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST); this.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
} else { } else {
this._corner.set_position(0, 0); this._corner.set_position(0, 0);
} }
this.actor.connect('leave-event',
this._onEnvironsLeft.bind(this));
this._corner.connect('enter-event', this._corner.connect('enter-event',
this._onCornerEntered.bind(this)); this._onCornerEntered.bind(this));
this._corner.connect('leave-event', this._corner.connect('leave-event',
@ -1214,14 +1219,11 @@ var HotCorner = class HotCorner {
} }
} }
destroy() { _onDestroy() {
this.setBarrierSize(0); this.setBarrierSize(0);
this._pressureBarrier.destroy(); this._pressureBarrier.destroy();
this._pressureBarrier = null; this._pressureBarrier = null;
if (this.actor)
this.actor.destroy();
this._ripples.destroy(); this._ripples.destroy();
} }
@ -1253,18 +1255,18 @@ var HotCorner = class HotCorner {
} }
_onCornerLeft(actor, event) { _onCornerLeft(actor, event) {
if (event.get_related() != this.actor) if (event.get_related() != this)
this._entered = false; this._entered = false;
// Consume event, otherwise this will confuse onEnvironsLeft // Consume event, otherwise this will confuse onEnvironsLeft
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_onEnvironsLeft(actor, event) { vfunc_leave_event(crossingEvent) {
if (event.get_related() != this._corner) if (crossingEvent.related != this._corner)
this._entered = false; this._entered = false;
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
}; });
var PressureBarrier = class PressureBarrier { var PressureBarrier = class PressureBarrier {
constructor(threshold, timeout, actionMode) { constructor(threshold, timeout, actionMode) {

View File

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

View File

@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */ /* exported LookingGlass */
const { Clutter, Cogl, Gio, GLib, const { Clutter, Cogl, Gio, GLib, GObject,
GObject, Meta, Pango, Shell, St } = imports.gi; Graphene, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const System = imports.system; const System = imports.system;
@ -110,9 +110,11 @@ var AutoComplete = class AutoComplete {
Signals.addSignalMethods(AutoComplete.prototype); Signals.addSignalMethods(AutoComplete.prototype);
var Notebook = class Notebook { var Notebook = GObject.registerClass({
constructor() { Signals: { 'selection': { param_types: [Clutter.Actor.$gtype] } },
this.actor = new St.BoxLayout({ vertical: true }); }, class Notebook extends St.BoxLayout {
_init() {
super._init({ vertical: true });
this.tabControls = new St.BoxLayout({ style_class: 'labels' }); this.tabControls = new St.BoxLayout({ style_class: 'labels' });
@ -143,7 +145,7 @@ var Notebook = class Notebook {
_scrollToBottom: false }; _scrollToBottom: false };
this._tabs.push(tabData); this._tabs.push(tabData);
scrollview.hide(); scrollview.hide();
this.actor.add(scrollview, { expand: true }); this.add(scrollview, { expand: true });
let vAdjust = scrollview.vscroll.adjustment; let vAdjust = scrollview.vscroll.adjustment;
vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData)); vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData));
@ -174,7 +176,7 @@ var Notebook = class Notebook {
// Focus the new tab before unmapping the old one // Focus the new tab before unmapping the old one
let tabData = this._tabs[index]; let tabData = this._tabs[index];
if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false)) if (!tabData.scrollView.navigate_focus(null, St.DirectionType.TAB_FORWARD, false))
this.actor.grab_key_focus(); this.grab_key_focus();
this._unselect(); this._unselect();
@ -234,8 +236,7 @@ var Notebook = class Notebook {
this.selectIndex(prevIndex); this.selectIndex(prevIndex);
} }
}; });
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) { function objectToString(o) {
if (typeof o == typeof objectToString) { if (typeof o == typeof objectToString) {
@ -246,57 +247,64 @@ function objectToString(o) {
} }
} }
var ObjLink = class ObjLink { var ObjLink = GObject.registerClass(
constructor(lookingGlass, o, title) { class ObjLink extends St.Button {
_init(lookingGlass, o, title) {
let text; let text;
if (title) if (title)
text = title; text = title;
else else
text = objectToString(o); text = objectToString(o);
text = GLib.markup_escape_text(text, -1); text = GLib.markup_escape_text(text, -1);
this._obj = o;
this.actor = new St.Button({ reactive: true, super._init({
reactive: true,
track_hover: true, track_hover: true,
style_class: 'shell-link', style_class: 'shell-link',
label: text }); label: text
this.actor.get_child().single_line_mode = true; });
this.actor.connect('clicked', this._onClicked.bind(this)); this.get_child().single_line_mode = true;
this._obj = o;
this._lookingGlass = lookingGlass; this._lookingGlass = lookingGlass;
} }
_onClicked() { vfunc_clicked() {
this._lookingGlass.inspectObject(this._obj, this.actor); this._lookingGlass.inspectObject(this._obj, this);
} }
}; });
var Result = GObject.registerClass({
GTypeName: 'LookingClass_Result'
}, 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.index = index;
this.o = o; this.o = o;
this.actor = new St.BoxLayout({ vertical: true });
this._lookingGlass = lookingGlass; this._lookingGlass = lookingGlass;
let cmdTxt = new St.Label({ text: command }); let cmdTxt = new St.Label({ text: command });
cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END; cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
this.actor.add(cmdTxt); this.add(cmdTxt);
let box = new St.BoxLayout({}); let box = new St.BoxLayout({});
this.actor.add(box); this.add(box);
let resultTxt = new St.Label({ text: `r(${index}) = ` }); let resultTxt = new St.Label({ text: `r(${index}) = ` });
resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END; resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
box.add(resultTxt); box.add(resultTxt);
let objLink = new ObjLink(this._lookingGlass, o); let objLink = new ObjLink(this._lookingGlass, o);
box.add(objLink.actor); box.add(objLink);
} }
}; });
var WindowList = class WindowList { var WindowList = GObject.registerClass({
constructor(lookingGlass) { GTypeName: 'LookingClass_WindowList'
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' }); }, class WindowList extends St.BoxLayout {
_init(lookingGlass) {
super._init({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
this._updateId = Main.initializeDeferredWork(this.actor, this._updateWindowList.bind(this)); this._updateId = Main.initializeDeferredWork(this, this._updateWindowList.bind(this));
global.display.connect('window-created', this._updateWindowList.bind(this)); global.display.connect('window-created', this._updateWindowList.bind(this));
tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this)); tracker.connect('tracked-windows-changed', this._updateWindowList.bind(this));
@ -307,7 +315,7 @@ var WindowList = class WindowList {
if (!this._lookingGlass.isOpen) if (!this._lookingGlass.isOpen)
return; return;
this.actor.destroy_all_children(); this.destroy_all_children();
let windows = global.get_window_actors(); let windows = global.get_window_actors();
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
@ -318,9 +326,9 @@ var WindowList = class WindowList {
metaWindow._lookingGlassManaged = true; metaWindow._lookingGlassManaged = true;
} }
let box = new St.BoxLayout({ vertical: true }); let box = new St.BoxLayout({ vertical: true });
this.actor.add(box); this.add(box);
let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title); let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title);
box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false }); box.add(windowLink, { x_align: St.Align.START, x_fill: false });
let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' }); let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
box.add(propsBox); box.add(propsBox);
propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` })); propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` }));
@ -331,7 +339,7 @@ var WindowList = class WindowList {
propsBox.add(propBox); propsBox.add(propBox);
propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false }); propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false });
let appLink = new ObjLink(this._lookingGlass, app, app.get_id()); let appLink = new ObjLink(this._lookingGlass, app, app.get_id());
propBox.add(appLink.actor, { y_fill: false }); propBox.add(appLink, { y_fill: false });
propBox.add(icon, { y_fill: false }); propBox.add(icon, { y_fill: false });
} else { } else {
propsBox.add(new St.Label({ text: '<untracked>' })); propsBox.add(new St.Label({ text: '<untracked>' }));
@ -342,23 +350,27 @@ var WindowList = class WindowList {
update() { update() {
this._updateWindowList(); this._updateWindowList();
} }
}; });
Signals.addSignalMethods(WindowList.prototype);
var ObjInspector = GObject.registerClass(
class ObjInspector extends St.ScrollView {
_init(lookingGlass) {
super._init({
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
x_fill: true,
y_fill: true
});
var ObjInspector = class ObjInspector {
constructor(lookingGlass) {
this._obj = null; this._obj = null;
this._previousObj = null; this._previousObj = null;
this._parentList = []; this._parentList = [];
this.actor = new St.ScrollView({ pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), this.get_hscroll_bar().hide();
x_fill: true, y_fill: true });
this.actor.get_hscroll_bar().hide();
this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector', this._container = new St.BoxLayout({ name: 'LookingGlassPropertyInspector',
style_class: 'lg-dialog', style_class: 'lg-dialog',
vertical: true }); vertical: true });
this.actor.add_actor(this._container); this.add_actor(this._container);
this._lookingGlass = lookingGlass; this._lookingGlass = lookingGlass;
} }
@ -404,7 +416,7 @@ var ObjInspector = class ObjInspector {
let link; let link;
try { try {
let prop = obj[propName]; let prop = obj[propName];
link = new ObjLink(this._lookingGlass, prop).actor; link = new ObjLink(this._lookingGlass, prop);
} catch (e) { } catch (e) {
link = new St.Label({ text: '<error>' }); link = new St.Label({ text: '<error>' });
} }
@ -421,17 +433,17 @@ var ObjInspector = class ObjInspector {
return; return;
this._previousObj = null; this._previousObj = null;
this._open = true; this._open = true;
this.actor.show(); this.show();
if (sourceActor) { if (sourceActor) {
this.actor.set_scale(0, 0); this.set_scale(0, 0);
this.actor.ease({ this.ease({
scale_x: 1, scale_x: 1,
scale_y: 1, scale_y: 1,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: 200 duration: 200
}); });
} else { } else {
this.actor.set_scale(1, 1); this.set_scale(1, 1);
} }
} }
@ -439,7 +451,7 @@ var ObjInspector = class ObjInspector {
if (!this._open) if (!this._open)
return; return;
this._open = false; this._open = false;
this.actor.hide(); this.hide();
this._previousObj = null; this._previousObj = null;
this._obj = null; this._obj = null;
} }
@ -453,7 +465,7 @@ var ObjInspector = class ObjInspector {
_onBack() { _onBack() {
this.selectObject(this._previousObj, true); this.selectObject(this._previousObj, true);
} }
}; });
var RedBorderEffect = GObject.registerClass( var RedBorderEffect = GObject.registerClass(
class RedBorderEffect extends Clutter.Effect { class RedBorderEffect extends Clutter.Effect {
@ -465,16 +477,16 @@ class RedBorderEffect extends Clutter.Effect {
color.init_from_4ub(0xff, 0, 0, 0xc4); color.init_from_4ub(0xff, 0, 0, 0xc4);
Cogl.set_source_color(color); Cogl.set_source_color(color);
let geom = actor.get_allocation_geometry(); let alloc = actor.get_allocation_box();
let width = 2; let width = 2;
// clockwise order // clockwise order
Cogl.rectangle(0, 0, geom.width, width); Cogl.rectangle(0, 0, alloc.get_width(), width);
Cogl.rectangle(geom.width - width, width, Cogl.rectangle(alloc.get_width() - width, width,
geom.width, geom.height); alloc.get_width(), alloc.get_height());
Cogl.rectangle(0, geom.height, Cogl.rectangle(0, alloc.get_height(),
geom.width - width, geom.height - width); alloc.get_width() - width, alloc.get_height() - width);
Cogl.rectangle(0, geom.height - width, Cogl.rectangle(0, alloc.get_height() - width,
width, width); width, width);
} }
}); });
@ -484,8 +496,7 @@ var Inspector = GObject.registerClass({
'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } }, 'target': { param_types: [Clutter.Actor.$gtype, GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] } },
}, class Inspector extends Clutter.Actor { }, class Inspector extends Clutter.Actor {
_init(lookingGlass) { _init(lookingGlass) {
super._init({ width: 0, super._init({ width: 0, height: 0 });
height: 0 });
Main.uiGroup.add_actor(this); Main.uiGroup.add_actor(this);
@ -620,18 +631,20 @@ var Inspector = GObject.registerClass({
} }
}); });
var Extensions = class Extensions { var Extensions = GObject.registerClass({
constructor(lookingGlass) { GTypeName: 'LookingClass_Extensions'
}, class Extensions extends St.BoxLayout {
_init(lookingGlass) {
super._init({ vertical: true, name: 'lookingGlassExtensions' });
this._lookingGlass = lookingGlass; this._lookingGlass = lookingGlass;
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none', this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
text: _("No extensions installed") }); text: _("No extensions installed") });
this._numExtensions = 0; this._numExtensions = 0;
this._extensionsList = new St.BoxLayout({ vertical: true, this._extensionsList = new St.BoxLayout({ vertical: true,
style_class: 'lg-extensions-list' }); style_class: 'lg-extensions-list' });
this._extensionsList.add(this._noExtensions); this._extensionsList.add(this._noExtensions);
this.actor.add(this._extensionsList); this.add(this._extensionsList);
Main.extensionManager.getUuids().forEach(uuid => { Main.extensionManager.getUuids().forEach(uuid => {
this._loadExtension(null, uuid); this._loadExtension(null, uuid);
@ -759,10 +772,19 @@ var Extensions = class Extensions {
return box; 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._borderPaintTarget = null;
this._redBorderEffect = new RedBorderEffect(); this._redBorderEffect = new RedBorderEffect();
@ -770,26 +792,18 @@ var LookingGlass = class LookingGlass {
this._it = null; this._it = null;
this._offset = 0; this._offset = 0;
this._results = [];
// Sort of magic, but...eh. // Sort of magic, but...eh.
this._maxItems = 150; 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 = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._interfaceSettings.connect('changed::monospace-font-name', this._interfaceSettings.connect('changed::monospace-font-name',
this._updateFont.bind(this)); this._updateFont.bind(this));
this._updateFont(); this._updateFont();
// We want it to appear to slide out from underneath the panel // We want it to appear to slide out from underneath the panel
Main.uiGroup.add_actor(this.actor); Main.uiGroup.add_actor(this);
Main.uiGroup.set_child_below_sibling(this.actor, Main.uiGroup.set_child_below_sibling(this,
Main.layoutManager.panelBox); Main.layoutManager.panelBox);
Main.layoutManager.panelBox.connect('allocation-changed', Main.layoutManager.panelBox.connect('allocation-changed',
this._queueResize.bind(this)); this._queueResize.bind(this));
@ -797,11 +811,11 @@ var LookingGlass = class LookingGlass {
this._queueResize.bind(this)); this._queueResize.bind(this));
this._objInspector = new ObjInspector(this); this._objInspector = new ObjInspector(this);
Main.uiGroup.add_actor(this._objInspector.actor); Main.uiGroup.add_actor(this._objInspector);
this._objInspector.actor.hide(); this._objInspector.hide();
let toolbar = new St.BoxLayout({ name: 'Toolbar' }); let toolbar = new St.BoxLayout({ name: 'Toolbar' });
this.actor.add_actor(toolbar); this.add_actor(toolbar);
let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker', let inspectIcon = new St.Icon({ icon_name: 'gtk-color-picker',
icon_size: 24 }); icon_size: 24 });
toolbar.add_actor(inspectIcon); toolbar.add_actor(inspectIcon);
@ -812,10 +826,10 @@ var LookingGlass = class LookingGlass {
this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target); this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
}); });
inspector.connect('closed', () => { inspector.connect('closed', () => {
this.actor.show(); this.show();
global.stage.set_key_focus(this._entry); global.stage.set_key_focus(this._entry);
}); });
this.actor.hide(); this.hide();
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
}); });
@ -837,7 +851,7 @@ var LookingGlass = class LookingGlass {
let notebook = new Notebook(); let notebook = new Notebook();
this._notebook = notebook; this._notebook = notebook;
this.actor.add(notebook.actor, { expand: true }); this.add(notebook, { expand: true });
let emptyBox = new St.Bin(); let emptyBox = new St.Bin();
toolbar.add(emptyBox, { expand: true }); toolbar.add(emptyBox, { expand: true });
@ -860,10 +874,10 @@ var LookingGlass = class LookingGlass {
this._entryArea.add(this._entry, { expand: true }); this._entryArea.add(this._entry, { expand: true });
this._windowList = new WindowList(this); this._windowList = new WindowList(this);
notebook.appendPage('Windows', this._windowList.actor); notebook.appendPage('Windows', this._windowList);
this._extensions = new Extensions(this); this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor); notebook.appendPage('Extensions', this._extensions);
this._entry.clutter_text.connect('activate', (o, _e) => { this._entry.clutter_text.connect('activate', (o, _e) => {
// Hide any completions we are currently showing // Hide any completions we are currently showing
@ -905,7 +919,7 @@ var LookingGlass = class LookingGlass {
// monospace font to be bold/oblique/etc. Could easily be added here. // monospace font to be bold/oblique/etc. Could easily be added here.
let size = fontDesc.get_size() / 1024.; let size = fontDesc.get_size() / 1024.;
let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt'; let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt';
this.actor.style = ` this.style = `
font-size: ${size}${unit}; font-size: ${size}${unit};
font-family: "${fontDesc.get_family()}";`; font-family: "${fontDesc.get_family()}";`;
} }
@ -919,17 +933,14 @@ var LookingGlass = class LookingGlass {
} }
_pushResult(command, obj) { _pushResult(command, obj) {
let index = this._results.length + this._offset; let index = this._resultsArea.get_n_children() + this._offset;
let result = new Result(this, CHEVRON + command, obj, index); let result = new Result(this, CHEVRON + command, obj, index);
this._results.push(result); this._resultsArea.add(result);
this._resultsArea.add(result.actor);
if (obj instanceof Clutter.Actor) if (obj instanceof Clutter.Actor)
this.setBorderPaintTarget(obj); this.setBorderPaintTarget(obj);
let children = this._resultsArea.get_children(); if (this._resultsArea.get_n_children() > this._maxItems) {
if (children.length > this._maxItems) { this._resultsArea.get_first_child().destroy();
this._results.shift();
children[0].destroy();
this._offset++; this._offset++;
} }
this._it = obj; this._it = obj;
@ -1016,7 +1027,7 @@ var LookingGlass = class LookingGlass {
getResult(idx) { getResult(idx) {
try { try {
return this._results[idx - this._offset].o; return this._resultsArea.get_child_at_index(idx - this._offset).o;
} catch (e) { } catch (e) {
throw new Error(`Unknown result at index ${idx}`); throw new Error(`Unknown result at index ${idx}`);
} }
@ -1041,14 +1052,14 @@ var LookingGlass = class LookingGlass {
let myWidth = primary.width * 0.7; let myWidth = primary.width * 0.7;
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height; let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9); let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.actor.x = primary.x + (primary.width - myWidth) / 2; this.x = primary.x + (primary.width - myWidth) / 2;
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight; this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight;
this._targetY = this._hiddenY + myHeight; this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY; this.y = this._hiddenY;
this.actor.width = myWidth; this.width = myWidth;
this.actor.height = myHeight; this.height = myHeight;
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8)); this._objInspector.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._objInspector.set_position(this.x + Math.floor(myWidth * 0.1),
this._targetY + Math.floor(myHeight * 0.1)); this._targetY + Math.floor(myHeight * 0.1));
} }
@ -1062,11 +1073,10 @@ var LookingGlass = class LookingGlass {
} }
// Handle key events which are relevant for all tabs of the LookingGlass // Handle key events which are relevant for all tabs of the LookingGlass
_globalKeyPressEvent(actor, event) { vfunc_key_press_event(keyPressEvent) {
let symbol = event.get_key_symbol(); let symbol = keyPressEvent.keyval;
let modifierState = event.get_state();
if (symbol == Clutter.Escape) { if (symbol == Clutter.Escape) {
if (this._objInspector.actor.visible) { if (this._objInspector.visible) {
this._objInspector.close(); this._objInspector.close();
} else { } else {
this.close(); this.close();
@ -1074,7 +1084,7 @@ var LookingGlass = class LookingGlass {
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
// Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view // Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
if (modifierState & Clutter.ModifierType.CONTROL_MASK) { if (keyPressEvent.modifier_state & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.KEY_Page_Up) { if (symbol == Clutter.KEY_Page_Up) {
this._notebook.prevTab(); this._notebook.prevTab();
} else if (symbol == Clutter.KEY_Page_Down) { } else if (symbol == Clutter.KEY_Page_Down) {
@ -1092,16 +1102,16 @@ var LookingGlass = class LookingGlass {
return; return;
this._notebook.selectIndex(0); this._notebook.selectIndex(0);
this.actor.show(); this.show();
this._open = true; this._open = true;
this._history.lastItem(); this._history.lastItem();
this.actor.remove_all_transitions(); this.remove_all_transitions();
// We inverse compensate for the slow-down so you can change the factor // We inverse compensate for the slow-down so you can change the factor
// through LookingGlass without long waits. // through LookingGlass without long waits.
let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor; let duration = LG_ANIMATION_TIME / St.Settings.get().slow_down_factor;
this.actor.ease({ this.ease({
y: this._targetY, y: this._targetY,
duration, duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
@ -1114,10 +1124,10 @@ var LookingGlass = class LookingGlass {
if (!this._open) if (!this._open)
return; return;
this._objInspector.actor.hide(); this._objInspector.hide();
this._open = false; this._open = false;
this.actor.remove_all_transitions(); this.remove_all_transitions();
this.setBorderPaintTarget(null); this.setBorderPaintTarget(null);
@ -1126,16 +1136,15 @@ var LookingGlass = class LookingGlass {
let settings = St.Settings.get(); let settings = St.Settings.get();
let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor, let duration = Math.min(LG_ANIMATION_TIME / settings.slow_down_factor,
LG_ANIMATION_TIME); LG_ANIMATION_TIME);
this.actor.ease({ this.ease({
y: this._hiddenY, y: this._hiddenY,
duration, duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.actor.hide() onComplete: () => this.hide()
}); });
} }
get isOpen() { get isOpen() {
return this._open; return this._open;
} }
}; });
Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -1290,7 +1290,7 @@ var ZoomRegion = class ZoomRegion {
// Add a background for when the magnified uiGroup is scrolled // Add a background for when the magnified uiGroup is scrolled
// out of view (don't want to see desktop showing through). // out of view (don't want to see desktop showing through).
this._background = (new Background.SystemBackground()).actor; this._background = new Background.SystemBackground();
mainGroup.add_actor(this._background); mainGroup.add_actor(this._background);
// Clone the group that contains all of UI on the screen. This is the // Clone the group that contains all of UI on the screen. This is the
@ -1587,8 +1587,9 @@ var ZoomRegion = class ZoomRegion {
} }
}; };
var Crosshairs = class Crosshairs { var Crosshairs = GObject.registerClass(
constructor() { class Crosshairs extends Clutter.Actor {
_init() {
// Set the group containing the crosshairs to three times the desktop // Set the group containing the crosshairs to three times the desktop
// size in case the crosshairs need to appear to be infinite in // size in case the crosshairs need to appear to be infinite in
@ -1596,7 +1597,7 @@ var Crosshairs = class Crosshairs {
let groupWidth = global.screen_width * 3; let groupWidth = global.screen_width * 3;
let groupHeight = global.screen_height * 3; let groupHeight = global.screen_height * 3;
this._actor = new Clutter.Actor({ super._init({
clip_to_allocation: false, clip_to_allocation: false,
width: groupWidth, width: groupWidth,
height: groupHeight height: groupHeight
@ -1605,10 +1606,10 @@ var Crosshairs = class Crosshairs {
this._horizRightHair = new Clutter.Actor(); this._horizRightHair = new Clutter.Actor();
this._vertTopHair = new Clutter.Actor(); this._vertTopHair = new Clutter.Actor();
this._vertBottomHair = new Clutter.Actor(); this._vertBottomHair = new Clutter.Actor();
this._actor.add_actor(this._horizLeftHair); this.add_actor(this._horizLeftHair);
this._actor.add_actor(this._horizRightHair); this.add_actor(this._horizRightHair);
this._actor.add_actor(this._vertTopHair); this.add_actor(this._vertTopHair);
this._actor.add_actor(this._vertBottomHair); this.add_actor(this._vertBottomHair);
this._clipSize = [0, 0]; this._clipSize = [0, 0];
this._clones = []; this._clones = [];
this.reCenter(); this.reCenter();
@ -1618,7 +1619,7 @@ var Crosshairs = class Crosshairs {
} }
_monitorsChanged() { _monitorsChanged() {
this._actor.set_size(global.screen_width * 3, global.screen_height * 3); this.set_size(global.screen_width * 3, global.screen_height * 3);
this.reCenter(); this.reCenter();
} }
@ -1639,12 +1640,15 @@ var Crosshairs = class Crosshairs {
if (zoomRegion && magnifiedMouse) { if (zoomRegion && magnifiedMouse) {
let container = magnifiedMouse.get_parent(); let container = magnifiedMouse.get_parent();
if (container) { if (container) {
crosshairsActor = this._actor; crosshairsActor = this;
if (this._actor.get_parent() != null) { if (this.get_parent() != null) {
crosshairsActor = new Clutter.Clone({ source: this._actor }); crosshairsActor = new Clutter.Clone({ source: this });
this._clones.push(crosshairsActor); 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.add_actor(crosshairsActor);
container.raise_child(magnifiedMouse, crosshairsActor); container.raise_child(magnifiedMouse, crosshairsActor);
@ -1663,7 +1667,7 @@ var Crosshairs = class Crosshairs {
* child actor if it was just a clone of the crosshairs actor. * child actor if it was just a clone of the crosshairs actor.
*/ */
removeFromParent(childActor) { removeFromParent(childActor) {
if (childActor == this._actor) if (childActor == this)
childActor.get_parent().remove_actor(childActor); childActor.get_parent().remove_actor(childActor);
else else
childActor.destroy(); childActor.destroy();
@ -1773,28 +1777,6 @@ var Crosshairs = class Crosshairs {
} }
} }
/**
* 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: * reCenter:
* Reposition the horizontal and vertical hairs such that they cross at * Reposition the horizontal and vertical hairs such that they cross at
@ -1803,7 +1785,7 @@ var Crosshairs = class Crosshairs {
* @clipSize: Optional. If present, an array of the form [width, height]. * @clipSize: Optional. If present, an array of the form [width, height].
*/ */
reCenter(clipSize) { reCenter(clipSize) {
let [groupWidth, groupHeight] = this._actor.get_size(); let [groupWidth, groupHeight] = this.get_size();
let leftLength = this._horizLeftHair.get_width(); let leftLength = this._horizLeftHair.get_width();
let topLength = this._vertTopHair.get_height(); let topLength = this._vertTopHair.get_height();
let thickness = this._horizLeftHair.get_height(); let thickness = this._horizLeftHair.get_height();
@ -1825,7 +1807,7 @@ var Crosshairs = class Crosshairs {
this._vertTopHair.set_position((groupWidth - thickness) / 2, top); this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom); this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
} }
}; });
var MagShaderEffects = class MagShaderEffects { var MagShaderEffects = class MagShaderEffects {
constructor(uiGroupClone) { constructor(uiGroupClone) {

View File

@ -189,7 +189,7 @@ function _initializeUI() {
messageTray = new MessageTray.MessageTray(); messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel(); panel = new Panel.Panel();
keyboard = new Keyboard.Keyboard(); keyboard = new Keyboard.KeyboardManager();
notificationDaemon = new NotificationDaemon.NotificationDaemon(); notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler(); windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager(); componentManager = new Components.ComponentManager();
@ -403,7 +403,7 @@ function notify(msg, details) {
messageTray.add(source); messageTray.add(source);
let notification = new MessageTray.Notification(source, msg, details); let notification = new MessageTray.Notification(source, msg, details);
notification.setTransient(true); notification.setTransient(true);
source.notify(notification); source.showNotification(notification);
} }
/** /**

View File

@ -1,7 +1,8 @@
const { Atk, Clutter, Gio, GLib, GObject, Meta, Pango, St } = imports.gi; /* exported MessageListSection */
const { Atk, Clutter, Gio, GLib,
GObject, Graphene, Meta, Pango, St } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
const Util = imports.misc.util; const Util = imports.misc.util;
@ -31,13 +32,18 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1); return GLib.markup_escape_text(text, -1);
} }
var URLHighlighter = class URLHighlighter { var URLHighlighter = GObject.registerClass(
constructor(text = '', lineWrap, allowMarkup) { class URLHighlighter extends St.Label {
this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter', _init(text = '', lineWrap, allowMarkup) {
x_expand: true, x_align: Clutter.ActorAlign.START }); super._init({
reactive: true,
style_class: 'url-highlighter',
x_expand: true,
x_align: Clutter.ActorAlign.START
});
this._linkColor = '#ccccff'; this._linkColor = '#ccccff';
this.actor.connect('style-changed', () => { this.connect('style-changed', () => {
let [hasColor, color] = this.actor.get_theme_node().lookup_color('link-color', false); let [hasColor, color] = this.get_theme_node().lookup_color('link-color', false);
if (hasColor) { if (hasColor) {
let linkColor = color.to_string().substr(0, 7); let linkColor = color.to_string().substr(0, 7);
if (linkColor != this._linkColor) { if (linkColor != this._linkColor) {
@ -46,42 +52,47 @@ var URLHighlighter = class URLHighlighter {
} }
} }
}); });
this.actor.clutter_text.line_wrap = lineWrap; this.clutter_text.line_wrap = lineWrap;
this.actor.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR; this.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
this.setMarkup(text, allowMarkup); this.setMarkup(text, allowMarkup);
this.actor.connect('button-press-event', (actor, event) => { }
vfunc_button_press_event(buttonEvent) {
// Don't try to URL highlight when invisible. // Don't try to URL highlight when invisible.
// The MessageTray doesn't actually hide us, so // The MessageTray doesn't actually hide us, so
// we need to check for paint opacities as well. // we need to check for paint opacities as well.
if (!actor.visible || actor.get_paint_opacity() == 0) if (!this.visible || this.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
// Keep Notification.actor from seeing this and taking // Keep Notification from seeing this and taking
// a pointer grab, which would block our button-release-event // a pointer grab, which would block our button-release-event
// handler, if an URL is clicked // handler, if an URL is clicked
return this._findUrlAtPos(event) != -1; return this._findUrlAtPos(buttonEvent) != -1;
}); }
this.actor.connect('button-release-event', (actor, event) => {
if (!actor.visible || actor.get_paint_opacity() == 0) vfunc_button_release_event(buttonEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let urlId = this._findUrlAtPos(event); let urlId = this._findUrlAtPos(buttonEvent);
if (urlId != -1) { if (urlId != -1) {
let url = this._urls[urlId].url; let url = this._urls[urlId].url;
if (!url.includes(':')) if (!url.includes(':'))
url = 'http://' + url; url = 'http://' + url;
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1)); Gio.app_info_launch_default_for_uri(
url, global.create_app_launch_context(0, -1));
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}); }
this.actor.connect('motion-event', (actor, event) => {
if (!actor.visible || actor.get_paint_opacity() == 0) vfunc_motion_event(motionEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let urlId = this._findUrlAtPos(event); let urlId = this._findUrlAtPos(motionEvent);
if (urlId != -1 && !this._cursorChanged) { if (urlId != -1 && !this._cursorChanged) {
global.display.set_cursor(Meta.Cursor.POINTING_HAND); global.display.set_cursor(Meta.Cursor.POINTING_HAND);
this._cursorChanged = true; this._cursorChanged = true;
@ -90,26 +101,26 @@ var URLHighlighter = class URLHighlighter {
this._cursorChanged = false; this._cursorChanged = false;
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
}); }
this.actor.connect('leave-event', () => {
if (!this.actor.visible || this.actor.get_paint_opacity() == 0) vfunc_leave_event(crossingEvent) {
if (!this.visible || this.get_paint_opacity() == 0)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (this._cursorChanged) { if (this._cursorChanged) {
this._cursorChanged = false; this._cursorChanged = false;
global.display.set_cursor(Meta.Cursor.DEFAULT); global.display.set_cursor(Meta.Cursor.DEFAULT);
} }
return Clutter.EVENT_PROPAGATE; return super.vfunc_leave_event(crossingEvent);
});
} }
setMarkup(text, allowMarkup) { setMarkup(text, allowMarkup) {
text = text ? _fixMarkup(text, allowMarkup) : ''; text = text ? _fixMarkup(text, allowMarkup) : '';
this._text = text; this._text = text;
this.actor.clutter_text.set_markup(text); this.clutter_text.set_markup(text);
/* clutter_text.text contain text without markup */ /* clutter_text.text contain text without markup */
this._urls = Util.findUrls(this.actor.clutter_text.text); this._urls = Util.findUrls(this.clutter_text.text);
this._highlightUrls(); this._highlightUrls();
} }
@ -125,16 +136,15 @@ var URLHighlighter = class URLHighlighter {
pos = url.pos + url.url.length; pos = url.pos + url.url.length;
} }
markup += this._text.substr(pos); markup += this._text.substr(pos);
this.actor.clutter_text.set_markup(markup); this.clutter_text.set_markup(markup);
} }
_findUrlAtPos(event) { _findUrlAtPos(event) {
let success_; let { x, y } = event;
let [x, y] = event.get_coords(); [, x, y] = this.transform_stage_point(x, y);
[success_, x, y] = this.actor.transform_stage_point(x, y);
let findPos = -1; let findPos = -1;
for (let i = 0; i < this.actor.clutter_text.text.length; i++) { for (let i = 0; i < this.clutter_text.text.length; i++) {
let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i); let [, px, py, lineHeight] = this.clutter_text.position_to_coords(i);
if (py > y || py + lineHeight < y || x < px) if (py > y || py + lineHeight < y || x < px)
continue; continue;
findPos = i; findPos = i;
@ -147,7 +157,7 @@ var URLHighlighter = class URLHighlighter {
} }
return -1; return -1;
} }
}; });
var ScaleLayout = GObject.registerClass( var ScaleLayout = GObject.registerClass(
class ScaleLayout extends Clutter.BinLayout { class ScaleLayout extends Clutter.BinLayout {
@ -283,21 +293,29 @@ var LabelExpanderLayout = GObject.registerClass({
} }
}); });
var Message = class Message {
constructor(title, body) {
this.expanded = false;
this._useBodyMarkup = false; var Message = GObject.registerClass({
GTypeName: 'MessageList_Message',
this.actor = new St.Button({ style_class: 'message', Signals: {
'close': {},
'expanded': {},
'unexpanded': {},
}
}, class Message extends St.Button {
_init(title, body) {
super._init({
style_class: 'message',
accessible_role: Atk.Role.NOTIFICATION, accessible_role: Atk.Role.NOTIFICATION,
can_focus: true, can_focus: true,
x_expand: true, x_fill: true }); x_expand: true,
this.actor.connect('key-press-event', x_fill: true
this._onKeyPressed.bind(this)); });
this.expanded = false;
this._useBodyMarkup = false;
let vbox = new St.BoxLayout({ vertical: true }); let vbox = new St.BoxLayout({ vertical: true });
this.actor.set_child(vbox); this.set_child(vbox);
let hbox = new St.BoxLayout(); let hbox = new St.BoxLayout();
vbox.add_actor(hbox); vbox.add_actor(hbox);
@ -341,15 +359,14 @@ var Message = class Message {
contentBox.add_actor(this._bodyStack); contentBox.add_actor(this._bodyStack);
this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup); this.bodyLabel = new URLHighlighter('', false, this._useBodyMarkup);
this.bodyLabel.actor.add_style_class_name('message-body'); this.bodyLabel.add_style_class_name('message-body');
this._bodyStack.add_actor(this.bodyLabel.actor); this._bodyStack.add_actor(this.bodyLabel);
this.setBody(body); this.setBody(body);
this._closeButton.connect('clicked', this.close.bind(this)); this._closeButton.connect('clicked', this.close.bind(this));
let actorHoverId = this.actor.connect('notify::hover', this._sync.bind(this)); let actorHoverId = this.connect('notify::hover', this._sync.bind(this));
this._closeButton.connect('destroy', this.actor.disconnect.bind(this.actor, actorHoverId)); this._closeButton.connect('destroy', this.disconnect.bind(this, actorHoverId));
this.actor.connect('clicked', this._onClicked.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._sync(); this._sync();
} }
@ -435,7 +452,7 @@ var Message = class Message {
if (this._bodyStack.get_n_children() < 2) { if (this._bodyStack.get_n_children() < 2) {
this._expandedLabel = new URLHighlighter(this._bodyText, this._expandedLabel = new URLHighlighter(this._bodyText,
true, this._useBodyMarkup); true, this._useBodyMarkup);
this.setExpandedBody(this._expandedLabel.actor); this.setExpandedBody(this._expandedLabel);
} }
if (animate) { if (animate) {
@ -488,19 +505,16 @@ var Message = class Message {
} }
_sync() { _sync() {
let visible = this.actor.hover && this.canClose(); let visible = this.hover && this.canClose();
this._closeButton.opacity = visible ? 255 : 0; this._closeButton.opacity = visible ? 255 : 0;
this._closeButton.reactive = visible; this._closeButton.reactive = visible;
} }
_onClicked() {
}
_onDestroy() { _onDestroy() {
} }
_onKeyPressed(a, event) { vfunc_key_press_event(keyEvent) {
let keysym = event.get_key_symbol(); let keysym = keyEvent.keyval;
if (keysym == Clutter.KEY_Delete || if (keysym == Clutter.KEY_Delete ||
keysym == Clutter.KEY_KP_Delete) { keysym == Clutter.KEY_KP_Delete) {
@ -509,37 +523,66 @@ var Message = class Message {
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
}; });
Signals.addSignalMethods(Message.prototype);
var MessageListSection = class MessageListSection { var MessageListSection = GObject.registerClass({
constructor() { Properties: {
this.actor = new St.BoxLayout({ style_class: 'message-list-section', '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, clip_to_allocation: true,
x_expand: true, vertical: true }); vertical: true,
x_expand: true
});
this._list = new St.BoxLayout({ style_class: 'message-list-section-list', this._list = new St.BoxLayout({ style_class: 'message-list-section-list',
vertical: true }); vertical: true });
this.actor.add_actor(this._list); this.add_actor(this._list);
this._list.connect('actor-added', this._sync.bind(this)); this._list.connect('actor-added', this._sync.bind(this));
this._list.connect('actor-removed', this._sync.bind(this)); this._list.connect('actor-removed', this._sync.bind(this));
let id = Main.sessionMode.connect('updated', let id = Main.sessionMode.connect('updated',
this._sync.bind(this)); this._sync.bind(this));
this.actor.connect('destroy', () => { this.connect('destroy', () => {
Main.sessionMode.disconnect(id); Main.sessionMode.disconnect(id);
}); });
this._messages = new Map();
this._date = new Date(); this._date = new Date();
this.empty = true; this._empty = true;
this.canClear = false; this._canClear = false;
this._sync(); this._sync();
} }
_onKeyFocusIn(actor) { get empty() {
this.emit('key-focus-in', actor); 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);
} }
get allowed() { get allowed() {
@ -558,58 +601,62 @@ var MessageListSection = class MessageListSection {
} }
addMessageAtIndex(message, index, animate) { addMessageAtIndex(message, index, animate) {
let obj = { if (this._messages.includes(message))
container: null, throw new Error('Message was already added previously');
destroyId: 0,
keyFocusId: 0, let listItem = new St.Bin({
closeId: 0 child: message,
}; x_fill: true,
let pivot = new Clutter.Point({ x: .5, y: .5 }); y_fill: true,
let scale = animate ? 0 : 1; layout_manager: new ScaleLayout(),
obj.container = new St.Widget({ layout_manager: new ScaleLayout(), pivot_point: new Graphene.Point({ x: .5, y: .5 }),
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);
}); });
obj.closeId = message.connect('close', () => { listItem._connectionsIds = [];
listItem._connectionsIds.push(message.connect('key-focus-in',
this._onKeyFocusIn.bind(this)));
listItem._connectionsIds.push(message.connect('close', () => {
this.removeMessage(message, true); this.removeMessage(message, true);
}); }));
listItem._connectionsIds.push(message.connect('destroy', () => {
listItem._connectionsIds.forEach(id => message.disconnect(id));
listItem.destroy();
}));
this._messages.set(message, obj); this._list.insert_child_at_index(listItem, index);
obj.container.add_actor(message.actor);
this._list.insert_child_at_index(obj.container, index); if (animate) {
listItem.set({ scale_x: 0, scale_y: 0 });
if (animate) listItem.ease({
obj.container.ease({
scale_x: 1, scale_x: 1,
scale_y: 1, scale_y: 1,
duration: MESSAGE_ANIMATION_TIME, duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
}); });
} }
}
moveMessage(message, index, animate) { moveMessage(message, index, animate) {
let obj = this._messages.get(message); if (!this._messages.includes(message))
throw new Error(`Impossible to move the untracked message ${message}`);
let listItem = message.get_parent();
if (!animate) { if (!animate) {
this._list.set_child_at_index(obj.container, index); this._list.set_child_at_index(listItem, index);
return; return;
} }
let onComplete = () => { let onComplete = () => {
this._list.set_child_at_index(obj.container, index); this._list.set_child_at_index(listItem, index);
obj.container.ease({ listItem.ease({
scale_x: 1, scale_x: 1,
scale_y: 1, scale_y: 1,
duration: MESSAGE_ANIMATION_TIME, duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
}); });
}; };
obj.container.ease({ listItem.ease({
scale_x: 0, scale_x: 0,
scale_y: 0, scale_y: 0,
duration: MESSAGE_ANIMATION_TIME, duration: MESSAGE_ANIMATION_TIME,
@ -619,33 +666,31 @@ var MessageListSection = class MessageListSection {
} }
removeMessage(message, animate) { removeMessage(message, animate) {
let obj = this._messages.get(message); if (!this._messages.includes(message))
throw new Error(`Impossible to remove the untracked message ${message}`);
message.actor.disconnect(obj.destroyId); let listItem = message.get_parent();
message.actor.disconnect(obj.keyFocusId); listItem._connectionsIds.forEach(id => message.disconnect(id));
message.disconnect(obj.closeId);
this._messages.delete(message);
if (animate) { if (animate) {
obj.container.ease({ listItem.ease({
scale_x: 0, scale_x: 0,
scale_y: 0, scale_y: 0,
duration: MESSAGE_ANIMATION_TIME, duration: MESSAGE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => { onComplete: () => {
obj.container.destroy(); listItem.destroy();
global.sync_pointer(); global.sync_pointer();
} }
}); });
} else { } else {
obj.container.destroy(); listItem.destroy();
global.sync_pointer(); global.sync_pointer();
} }
} }
clear() { clear() {
let messages = [...this._messages.keys()].filter(msg => msg.canClose()); let messages = this._messages.filter(msg => msg.canClose());
// If there are few messages, letting them all zoom out looks OK // If there are few messages, letting them all zoom out looks OK
if (messages.length < 2) { if (messages.length < 2) {
@ -658,9 +703,8 @@ var MessageListSection = class MessageListSection {
let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5); let delay = MESSAGE_ANIMATION_TIME / Math.max(messages.length, 5);
for (let i = 0; i < messages.length; i++) { for (let i = 0; i < messages.length; i++) {
let message = messages[i]; let message = messages[i];
let obj = this._messages.get(message); message.get_parent().ease({
obj.container.ease({ translation_x: this._list.width,
anchor_x: this._list.width,
opacity: 0, opacity: 0,
duration: MESSAGE_ANIMATION_TIME, duration: MESSAGE_ANIMATION_TIME,
delay: i * delay, delay: i * delay,
@ -671,33 +715,25 @@ var MessageListSection = class MessageListSection {
} }
} }
_canClear() {
for (let message of this._messages.keys())
if (message.canClose())
return true;
return false;
}
_shouldShow() { _shouldShow() {
return !this.empty; return !this.empty;
} }
_sync() { _sync() {
let empty = this._list.get_n_children() == 0; let messages = this._messages;
let changed = this.empty !== empty; let empty = messages.length == 0;
this.empty = empty;
if (changed) if (this._empty != empty) {
this.emit('empty-changed'); this._empty = empty;
this.notify('empty');
let canClear = this._canClear();
changed = this.canClear !== canClear;
this.canClear = canClear;
if (changed)
this.emit('can-clear-changed');
this.actor.visible = this.allowed && this._shouldShow();
} }
};
Signals.addSignalMethods(MessageListSection.prototype); let canClear = messages.some(m => m.canClose());
if (this._canClear != canClear) {
this._canClear = canClear;
this.notify('can-clear');
}
this.visible = this.allowed && this._shouldShow();
}
});

View File

@ -4,7 +4,6 @@
SystemNotificationSource, MessageTray */ SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
const GnomeSession = imports.misc.gnomeSession; const GnomeSession = imports.misc.gnomeSession;
@ -134,72 +133,84 @@ var FocusGrabber = class FocusGrabber {
// source, such as whether to play sound or honour the critical bit. // source, such as whether to play sound or honour the critical bit.
// //
// A notification without a policy object will inherit the default one. // A notification without a policy object will inherit the default one.
var NotificationPolicy = class NotificationPolicy { var NotificationPolicy = GObject.registerClass({
constructor(params) { GTypeName: 'MessageTray_NotificationPolicy',
params = Params.parse(params, { Properties: {
enable: true, 'enable': GObject.ParamSpec.boolean(
enableSound: true, 'enable', 'enable', 'enable',
showBanners: true, GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
forceExpanded: false, true),
showInLockScreen: true, 'enable-sound': GObject.ParamSpec.boolean(
detailsInLockScreen: false, 'enable-sound', 'enable-sound', 'enable-sound',
}); GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY,
Object.getOwnPropertyNames(params).forEach(key => { true),
let desc = Object.getOwnPropertyDescriptor(params, key); 'show-banners': GObject.ParamSpec.boolean(
Object.defineProperty(this, `_${key}`, desc); '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 {
// Do nothing for the default policy. These methods are only useful for the // Do nothing for the default policy. These methods are only useful for the
// GSettings policy. // GSettings policy.
store() { } store() { }
destroy() { } destroy() {
this.run_dispose();
get enable() {
return this._enable;
} }
get enableSound() { get enableSound() {
return this._enableSound; return this.enable_sound;
} }
get showBanners() { get showBanners() {
return this._showBanners; return this.show_banners;
} }
get forceExpanded() { get forceExpanded() {
return this._forceExpanded; return this.force_expanded;
} }
get showInLockScreen() { get showInLockScreen() {
return this._showInLockScreen; return this.show_in_lock_screen;
} }
get detailsInLockScreen() { get detailsInLockScreen() {
return this._detailsInLockScreen; return this.details_in_lock_screen;
} }
}; });
Signals.addSignalMethods(NotificationPolicy.prototype);
var NotificationGenericPolicy = var NotificationGenericPolicy = GObject.registerClass({
class NotificationGenericPolicy extends NotificationPolicy { GTypeName: 'MessageTray_NotificationGenericPolicy'
constructor() { }, class NotificationGenericPolicy extends NotificationPolicy {
super(); _init() {
super._init();
this.id = 'generic'; this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' }); this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', this._changed.bind(this)); this._masterSettings.connect('changed', this._changed.bind(this));
} }
store() { }
destroy() { destroy() {
this._masterSettings.run_dispose(); this._masterSettings.run_dispose();
super.destroy();
} }
_changed(settings, key) { _changed(settings, key) {
this.emit('policy-changed', key); if (this.constructor.find_property(key))
this.notify(key);
} }
get showBanners() { get showBanners() {
@ -209,12 +220,13 @@ class NotificationGenericPolicy extends NotificationPolicy {
get showInLockScreen() { get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen'); return this._masterSettings.get_boolean('show-in-lock-screen');
} }
}; });
var NotificationApplicationPolicy = var NotificationApplicationPolicy = GObject.registerClass({
class NotificationApplicationPolicy extends NotificationPolicy { GTypeName: 'MessageTray_NotificationApplicationPolicy'
constructor(id) { }, class NotificationApplicationPolicy extends NotificationPolicy {
super(); _init(id) {
super._init();
this.id = id; this.id = id;
this._canonicalId = this._canonicalizeId(id); this._canonicalId = this._canonicalizeId(id);
@ -240,12 +252,13 @@ class NotificationApplicationPolicy extends NotificationPolicy {
destroy() { destroy() {
this._masterSettings.run_dispose(); this._masterSettings.run_dispose();
this._settings.run_dispose(); this._settings.run_dispose();
super.destroy();
} }
_changed(settings, key) { _changed(settings, key) {
this.emit('policy-changed', key); if (this.constructor.find_property(key))
if (key == 'enable') this.notify(key);
this.emit('enable-changed');
} }
_canonicalizeId(id) { _canonicalizeId(id) {
@ -279,7 +292,7 @@ class NotificationApplicationPolicy extends NotificationPolicy {
get detailsInLockScreen() { get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen'); return this._settings.get_boolean('details-in-lock-screen');
} }
}; });
// Notification: // Notification:
// @source: the notification's Source // @source: the notification's Source
@ -336,12 +349,26 @@ class NotificationApplicationPolicy extends NotificationPolicy {
// @source allows playing sounds). // @source allows playing sounds).
// //
// [1] https://developer.gnome.org/notification-spec/#markup // [1] https://developer.gnome.org/notification-spec/#markup
var Notification = class Notification { var Notification = GObject.registerClass({
constructor(source, title, banner, params) { GTypeName: 'MessageTray_Notification',
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();
this.source = source; this.source = source;
this.title = title; this.title = title;
this.urgency = Urgency.NORMAL; this.urgency = Urgency.NORMAL;
this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
this.isTransient = false; this.isTransient = false;
this.privacyScope = PrivacyScope.USER; this.privacyScope = PrivacyScope.USER;
@ -353,6 +380,7 @@ var Notification = class Notification {
this._soundFile = null; this._soundFile = null;
this._soundPlayed = false; this._soundPlayed = false;
this.actions = []; this.actions = [];
this.setResident(false);
// If called with only one argument we assume the caller // If called with only one argument we assume the caller
// will call .update() later on. This is the case of // will call .update() later on. This is the case of
@ -422,7 +450,7 @@ var Notification = class Notification {
if (this._acknowledged == v) if (this._acknowledged == v)
return; return;
this._acknowledged = v; this._acknowledged = v;
this.emit('acknowledged-changed'); this.notify('acknowledged');
} }
setUrgency(urgency) { setUrgency(urgency) {
@ -431,6 +459,15 @@ var Notification = class Notification {
setResident(resident) { setResident(resident) {
this.resident = 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) { setTransient(isTransient) {
@ -472,23 +509,30 @@ var Notification = class Notification {
activate() { activate() {
this.emit('activated'); this.emit('activated');
if (!this.resident)
this.destroy();
} }
destroy(reason = NotificationDestroyedReason.DISMISSED) { destroy(reason = NotificationDestroyedReason.DISMISSED) {
this.emit('destroy', reason); if (this._activatedId) {
this.disconnect(this._activatedId);
delete this._activatedId;
} }
};
Signals.addSignalMethods(Notification.prototype);
var NotificationBanner = this.emit('destroy', reason);
class NotificationBanner extends Calendar.NotificationMessage { this.run_dispose();
constructor(notification) { }
super(notification); });
this.actor.can_focus = false; var NotificationBanner = GObject.registerClass({
this.actor.add_style_class_name('notification-banner'); Signals: {
'done-displaying': {},
'unfocused': {},
}
}, class NotificationBanner extends Calendar.NotificationMessage {
_init(notification) {
super._init(notification);
this.can_focus = false;
this.add_style_class_name('notification-banner');
this._buttonBox = null; this._buttonBox = null;
@ -575,7 +619,7 @@ class NotificationBanner extends Calendar.NotificationMessage {
return this.addButton(button, callback); return this.addButton(button, callback);
} }
}; });
var SourceActor = GObject.registerClass( var SourceActor = GObject.registerClass(
class SourceActor extends St.Widget { class SourceActor extends St.Widget {
@ -640,7 +684,7 @@ class SourceActorWithLabel extends SourceActor {
this.add_actor(this._counterBin); this.add_actor(this._counterBin);
this._countUpdatedId = this._source.connect('count-updated', this._updateCount.bind(this)); this._countUpdatedId = this._source.connect('notify::count', this._updateCount.bind(this));
this._updateCount(); this._updateCount();
this.connect('destroy', () => { this.connect('destroy', () => {
@ -688,11 +732,34 @@ class SourceActorWithLabel extends SourceActor {
} }
}); });
var Source = class Source { var Source = GObject.registerClass({
constructor(title, iconName) { GTypeName: 'MessageTray_Source',
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: title });
this.SOURCE_ICON_SIZE = 48; this.SOURCE_ICON_SIZE = 48;
this.title = title;
this.iconName = iconName; this.iconName = iconName;
this.isChat = false; this.isChat = false;
@ -727,7 +794,7 @@ var Source = class Source {
} }
countUpdated() { countUpdated() {
this.emit('count-updated'); super.notify('count');
} }
_createPolicy() { _createPolicy() {
@ -741,8 +808,11 @@ var Source = class Source {
} }
setTitle(newTitle) { setTitle(newTitle) {
if (this.title == newTitle)
return;
this.title = newTitle; this.title = newTitle;
this.emit('title-changed'); this.notify('title');
} }
createBanner(notification) { createBanner(notification) {
@ -767,10 +837,10 @@ var Source = class Source {
return; return;
this.notifications.splice(index, 1); this.notifications.splice(index, 1);
this.countUpdated();
if (this.notifications.length == 0) if (this.notifications.length == 0)
this.destroy(); this.destroy();
this.countUpdated();
} }
pushNotification(notification) { pushNotification(notification) {
@ -781,24 +851,39 @@ var Source = class Source {
this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED); this.notifications.shift().destroy(NotificationDestroyedReason.EXPIRED);
notification.connect('destroy', this._onNotificationDestroy.bind(this)); notification.connect('destroy', this._onNotificationDestroy.bind(this));
notification.connect('acknowledged-changed', this.countUpdated.bind(this)); notification.connect('notify::acknowledged', this.countUpdated.bind(this));
this.notifications.push(notification); this.notifications.push(notification);
this.emit('notification-added', notification); this.emit('notification-added', notification);
this.countUpdated(); this.countUpdated();
} }
notify(notification) { showNotification(notification) {
notification.acknowledged = false; notification.acknowledged = false;
this.pushNotification(notification); this.pushNotification(notification);
if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) { if (this.policy.showBanners || notification.urgency == Urgency.CRITICAL) {
this.emit('notify', notification); this.emit('notification-show', notification);
} else { } else {
notification.playSound(); 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) { destroy(reason) {
this.policy.destroy(); this.policy.destroy();
@ -809,6 +894,8 @@ var Source = class Source {
notifications[i].destroy(reason); notifications[i].destroy(reason);
this.emit('destroy', reason); this.emit('destroy', reason);
this.run_dispose();
} }
iconUpdated() { iconUpdated() {
@ -823,14 +910,23 @@ var Source = class Source {
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) if (!this.notifications[i].resident)
this.notifications[i].destroy(); this.notifications[i].destroy();
this.countUpdated();
} }
}; });
Signals.addSignalMethods(Source.prototype);
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()
});
var MessageTray = class MessageTray {
constructor() {
this._presence = new GnomeSession.Presence((proxy, _error) => { this._presence = new GnomeSession.Presence((proxy, _error) => {
this._onStatusChanged(proxy.status); this._onStatusChanged(proxy.status);
}); });
@ -847,18 +943,15 @@ var MessageTray = class MessageTray {
// so fix up Clutter's view of the pointer position in // so fix up Clutter's view of the pointer position in
// that case. // that case.
let related = ev.get_related(); let related = ev.get_related();
if (!related || this.actor.contains(related)) if (!related || this.contains(related))
global.sync_pointer(); 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 }); let constraint = new Layout.MonitorConstraint({ primary: true });
Main.layoutManager.panelBox.bind_property('visible', Main.layoutManager.panelBox.bind_property('visible',
constraint, 'work-area', constraint, 'work-area',
GObject.BindingFlags.SYNC_CREATE); GObject.BindingFlags.SYNC_CREATE);
this.actor.add_constraint(constraint); this.add_constraint(constraint);
this._bannerBin = new St.Widget({ name: 'notification-container', this._bannerBin = new St.Widget({ name: 'notification-container',
reactive: true, reactive: true,
@ -872,7 +965,7 @@ var MessageTray = class MessageTray {
this._onNotificationKeyRelease.bind(this)); this._onNotificationKeyRelease.bind(this));
this._bannerBin.connect('notify::hover', this._bannerBin.connect('notify::hover',
this._onNotificationHoverChanged.bind(this)); this._onNotificationHoverChanged.bind(this));
this.actor.add_actor(this._bannerBin); this.add_actor(this._bannerBin);
this._notificationFocusGrabber = new FocusGrabber(this._bannerBin); this._notificationFocusGrabber = new FocusGrabber(this._bannerBin);
this._notificationQueue = []; this._notificationQueue = [];
@ -901,7 +994,7 @@ var MessageTray = class MessageTray {
this._notificationTimeoutId = 0; this._notificationTimeoutId = 0;
this._notificationRemoved = false; this._notificationRemoved = false;
Main.layoutManager.addChrome(this.actor, { affectsInputRegion: false }); Main.layoutManager.addChrome(this, { affectsInputRegion: false });
Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true }); Main.layoutManager.trackChrome(this._bannerBin, { affectsInputRegion: true });
global.display.connect('in-fullscreen-changed', this._updateState.bind(this)); global.display.connect('in-fullscreen-changed', this._updateState.bind(this));
@ -944,11 +1037,11 @@ var MessageTray = class MessageTray {
} }
_onDragBegin() { _onDragBegin() {
Shell.util_set_hidden_from_pick(this.actor, true); Shell.util_set_hidden_from_pick(this, true);
} }
_onDragEnd() { _onDragEnd() {
Shell.util_set_hidden_from_pick(this.actor, false); Shell.util_set_hidden_from_pick(this, false);
} }
get bannerAlignment() { get bannerAlignment() {
@ -997,22 +1090,22 @@ var MessageTray = class MessageTray {
// Register that we got a notification for this source // Register that we got a notification for this source
source.policy.store(); source.policy.store();
source.policy.connect('enable-changed', () => { source.policy.connect('notify::enable', () => {
this._onSourceEnableChanged(source.policy, source); this._onSourceEnableChanged(source.policy, source);
}); });
source.policy.connect('policy-changed', this._updateState.bind(this)); source.policy.connect('notify', this._updateState.bind(this));
this._onSourceEnableChanged(source.policy, source); this._onSourceEnableChanged(source.policy, source);
} }
_addSource(source) { _addSource(source) {
let obj = { let obj = {
notifyId: 0, showId: 0,
destroyId: 0, destroyId: 0,
}; };
this._sources.set(source, obj); this._sources.set(source, obj);
obj.notifyId = source.connect('notify', this._onNotify.bind(this)); obj.showId = source.connect('notification-show', this._onNotificationShow.bind(this));
obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this)); obj.destroyId = source.connect('destroy', this._onSourceDestroy.bind(this));
this.emit('source-added', source); this.emit('source-added', source);
@ -1022,7 +1115,7 @@ var MessageTray = class MessageTray {
let obj = this._sources.get(source); let obj = this._sources.get(source);
this._sources.delete(source); this._sources.delete(source);
source.disconnect(obj.notifyId); source.disconnect(obj.showId);
source.disconnect(obj.destroyId); source.disconnect(obj.destroyId);
this.emit('source-removed', source); this.emit('source-removed', source);
@ -1063,7 +1156,7 @@ var MessageTray = class MessageTray {
} }
} }
_onNotify(source, notification) { _onNotificationShow(_source, notification) {
if (this._notification == notification) { if (this._notification == notification) {
// If a notification that is being shown is updated, we update // If a notification that is being shown is updated, we update
// how it is shown and extend the time until it auto-hides. // how it is shown and extend the time until it auto-hides.
@ -1195,7 +1288,7 @@ var MessageTray = class MessageTray {
// at the present time. // at the present time.
_updateState() { _updateState() {
let hasMonitor = Main.layoutManager.primaryMonitor != null; let hasMonitor = Main.layoutManager.primaryMonitor != null;
this.actor.visible = !this._bannerBlocked && hasMonitor && this._banner != null; this.visible = !this._bannerBlocked && hasMonitor && this._banner != null;
if (this._bannerBlocked || !hasMonitor) if (this._bannerBlocked || !hasMonitor)
return; return;
@ -1275,11 +1368,11 @@ var MessageTray = class MessageTray {
this._updateState(); this._updateState();
}); });
this._bannerBin.add_actor(this._banner.actor); this._bannerBin.add_actor(this._banner);
this._bannerBin.opacity = 0; this._bannerBin.opacity = 0;
this._bannerBin.y = -this._banner.actor.height; this._bannerBin.y = -this._banner.height;
this.actor.show(); this.show();
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
this._updateShowingNotification(); this._updateShowingNotification();
@ -1426,16 +1519,16 @@ var MessageTray = class MessageTray {
_hideNotificationCompleted() { _hideNotificationCompleted() {
let notification = this._notification; let notification = this._notification;
this._notification = null; this._notification = null;
if (notification.isTransient) if (!this._notificationRemoved && notification.isTransient)
notification.destroy(NotificationDestroyedReason.EXPIRED); notification.destroy(NotificationDestroyedReason.EXPIRED);
this._pointerInNotification = false; this._pointerInNotification = false;
this._notificationRemoved = false; this._notificationRemoved = false;
Meta.enable_unredirect_for_display(global.display); Meta.enable_unredirect_for_display(global.display);
this._banner.actor.destroy(); this._banner.destroy();
this._banner = null; this._banner = null;
this.actor.hide(); this.hide();
} }
_expandActiveNotification() { _expandActiveNotification() {
@ -1457,15 +1550,15 @@ var MessageTray = class MessageTray {
_ensureBannerFocused() { _ensureBannerFocused() {
this._notificationFocusGrabber.grabFocus(); this._notificationFocusGrabber.grabFocus();
} }
}; });
Signals.addSignalMethods(MessageTray.prototype);
var SystemNotificationSource = class SystemNotificationSource extends Source { var SystemNotificationSource = GObject.registerClass(
constructor() { class SystemNotificationSource extends Source {
super(_("System Information"), 'dialog-information-symbolic'); _init() {
super._init(_("System Information"), 'dialog-information-symbolic');
} }
open() { open() {
this.destroy(); this.destroy();
} }
}; });

View File

@ -121,7 +121,7 @@ var ModalDialog = GObject.registerClass({
this.dialogLayout.opacity = 255; this.dialogLayout.opacity = 255;
if (this._lightbox) if (this._lightbox)
this._lightbox.show(); this._lightbox.lightOn();
this.opacity = 0; this.opacity = 0;
this.show(); this.show();
this.ease({ this.ease({

View File

@ -1,5 +1,5 @@
/* exported MediaSection */ /* exported MediaSection */
const { Gio, Shell, St } = imports.gi; const { Gio, GObject, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
@ -19,9 +19,10 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.'; const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
var MediaMessage = class MediaMessage extends MessageList.Message { var MediaMessage = GObject.registerClass(
constructor(player) { class MediaMessage extends MessageList.Message {
super('', ''); _init(player) {
super._init('', '');
this._player = player; this._player = player;
@ -48,7 +49,7 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
this._update(); this._update();
} }
_onClicked() { vfunc_clicked() {
this._player.raise(); this._player.raise();
Main.panel.closeCalendar(); Main.panel.closeCalendar();
} }
@ -79,7 +80,7 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
this._updateNavButton(this._prevButton, this._player.canGoPrevious); this._updateNavButton(this._prevButton, this._player.canGoPrevious);
this._updateNavButton(this._nextButton, this._player.canGoNext); this._updateNavButton(this._nextButton, this._player.canGoNext);
} }
}; });
var MprisPlayer = class MprisPlayer { var MprisPlayer = class MprisPlayer {
constructor(busName) { constructor(busName) {
@ -194,9 +195,10 @@ var MprisPlayer = class MprisPlayer {
}; };
Signals.addSignalMethods(MprisPlayer.prototype); Signals.addSignalMethods(MprisPlayer.prototype);
var MediaSection = class MediaSection extends MessageList.MessageListSection { var MediaSection = GObject.registerClass(
constructor() { class MediaSection extends MessageList.MessageListSection {
super(); _init() {
super._init();
this._players = new Map(); this._players = new Map();
@ -247,4 +249,4 @@ var MediaSection = class MediaSection extends MessageList.MessageListSection {
if (newOwner && !oldOwner) if (newOwner && !oldOwner)
this._addPlayer(name); this._addPlayer(name);
} }
}; });

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */ /* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi; const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
const Config = imports.misc.config; const Config = imports.misc.config;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -412,10 +412,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
} }
}; };
var FdoNotificationDaemonSource = var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source { class FdoNotificationDaemonSource extends MessageTray.Source {
constructor(title, pid, sender, appId) { _init(title, pid, sender, appId) {
super(title); super._init(title);
this.pid = pid; this.pid = pid;
this.app = this._getApp(appId); this.app = this._getApp(appId);
@ -464,7 +464,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
if (notification.resident && this.app && tracker.focus_app == this.app) if (notification.resident && this.app && tracker.focus_app == this.app)
this.pushNotification(notification); this.pushNotification(notification);
else else
this.notify(notification); this.showNotification(notification);
} }
_getApp(appId) { _getApp(appId) {
@ -526,7 +526,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
return null; return null;
} }
} }
}; });
const PRIORITY_URGENCY_MAP = { const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW, low: MessageTray.Urgency.LOW,
@ -535,10 +535,10 @@ const PRIORITY_URGENCY_MAP = {
urgent: MessageTray.Urgency.CRITICAL urgent: MessageTray.Urgency.CRITICAL
}; };
var GtkNotificationDaemonNotification = var GtkNotificationDaemonNotification = GObject.registerClass(
class GtkNotificationDaemonNotification extends MessageTray.Notification { class GtkNotificationDaemonNotification extends MessageTray.Notification {
constructor(source, notification) { _init(source, notification) {
super(source); super._init(source);
this._serialized = GLib.Variant.new('a{sv}', notification); this._serialized = GLib.Variant.new('a{sv}', notification);
let { title, let { title,
@ -602,7 +602,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
serialize() { serialize() {
return this._serialized; return this._serialized;
} }
}; });
const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application'); const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application');
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface); const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
@ -618,9 +618,9 @@ function getPlatformData() {
function InvalidAppError() {} function InvalidAppError() {}
var GtkNotificationDaemonAppSource = var GtkNotificationDaemonAppSource = GObject.registerClass(
class GtkNotificationDaemonAppSource extends MessageTray.Source { class GtkNotificationDaemonAppSource extends MessageTray.Source {
constructor(appId) { _init(appId) {
let objectPath = objectPathFromAppId(appId); let objectPath = objectPathFromAppId(appId);
if (!GLib.Variant.is_object_path(objectPath)) if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError(); throw new InvalidAppError();
@ -629,7 +629,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!app) if (!app)
throw new InvalidAppError(); throw new InvalidAppError();
super(app.get_name()); super._init(app.get_name());
this._appId = appId; this._appId = appId;
this._app = app; this._app = app;
@ -690,7 +690,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
this._notifications[notificationId] = notification; this._notifications[notificationId] = notification;
if (showBanner) if (showBanner)
this.notify(notification); this.showNotification(notification);
else else
this.pushNotification(notification); this.pushNotification(notification);
@ -716,7 +716,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
} }
return [this._appId, notifications]; return [this._appId, notifications];
} }
}; });
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications'); const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
@ -742,7 +742,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
delete this._sources[appId]; delete this._sources[appId];
this._saveNotifications(); this._saveNotifications();
}); });
source.connect('count-updated', this._saveNotifications.bind(this)); source.connect('notify::count', this._saveNotifications.bind(this));
Main.messageTray.add(source); Main.messageTray.add(source);
this._sources[appId] = source; this._sources[appId] = source;
return source; return source;

View File

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

View File

@ -41,22 +41,25 @@ class OsdWindowConstraint extends Clutter.Constraint {
} }
}); });
var OsdWindow = class { var OsdWindow = GObject.registerClass(
constructor(monitorIndex) { class OsdWindow extends St.Widget {
this.actor = new St.Widget({ x_expand: true, _init(monitorIndex) {
super._init({
x_expand: true,
y_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER
});
this._monitorIndex = monitorIndex; this._monitorIndex = monitorIndex;
let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
this.actor.add_constraint(constraint); this.add_constraint(constraint);
this._boxConstraint = new OsdWindowConstraint(); this._boxConstraint = new OsdWindowConstraint();
this._box = new St.BoxLayout({ style_class: 'osd-window', this._box = new St.BoxLayout({ style_class: 'osd-window',
vertical: true }); vertical: true });
this._box.add_constraint(this._boxConstraint); this._box.add_constraint(this._boxConstraint);
this.actor.add_actor(this._box); this.add_actor(this._box);
this._icon = new St.Icon(); this._icon = new St.Icon();
this._box.add(this._icon, { expand: true }); this._box.add(this._icon, { expand: true });
@ -73,7 +76,7 @@ var OsdWindow = class {
this._hideTimeoutId = 0; this._hideTimeoutId = 0;
this._reset(); this._reset();
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this._monitorsChangedId = this._monitorsChangedId =
Main.layoutManager.connect('monitors-changed', Main.layoutManager.connect('monitors-changed',
@ -83,7 +86,7 @@ var OsdWindow = class {
themeContext.connect('notify::scale-factor', themeContext.connect('notify::scale-factor',
this._relayout.bind(this)); this._relayout.bind(this));
this._relayout(); this._relayout();
Main.uiGroup.add_child(this.actor); Main.uiGroup.add_child(this);
} }
_onDestroy() { _onDestroy() {
@ -110,7 +113,7 @@ var OsdWindow = class {
setLevel(value) { setLevel(value) {
this._level.visible = (value != undefined); this._level.visible = (value != undefined);
if (value != undefined) { if (value != undefined) {
if (this.actor.visible) if (this.visible)
this._level.ease_property('value', value, { this._level.ease_property('value', value, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: LEVEL_ANIMATION_TIME duration: LEVEL_ANIMATION_TIME
@ -128,13 +131,13 @@ var OsdWindow = class {
if (!this._icon.gicon) if (!this._icon.gicon)
return; return;
if (!this.actor.visible) { if (!this.visible) {
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
this.actor.show(); super.show();
this.actor.opacity = 0; this.opacity = 0;
this.actor.get_parent().set_child_above_sibling(this.actor, null); this.get_parent().set_child_above_sibling(this, null);
this.actor.ease({ this.ease({
opacity: 255, opacity: 255,
duration: FADE_TIME, duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
@ -158,7 +161,7 @@ var OsdWindow = class {
_hide() { _hide() {
this._hideTimeoutId = 0; this._hideTimeoutId = 0;
this.actor.ease({ this.ease({
opacity: 0, opacity: 0,
duration: FADE_TIME, duration: FADE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -171,7 +174,7 @@ var OsdWindow = class {
} }
_reset() { _reset() {
this.actor.hide(); super.hide();
this.setLabel(null); this.setLabel(null);
this.setMaxLevel(null); this.setMaxLevel(null);
this.setLevel(null); this.setLevel(null);
@ -193,7 +196,7 @@ var OsdWindow = class {
this._box.translation_y = Math.round(monitor.height / 4); this._box.translation_y = Math.round(monitor.height / 4);
this._boxConstraint.minSize = popupSize; this._boxConstraint.minSize = popupSize;
} }
}; });
var OsdWindowManager = class { var OsdWindowManager = class {
constructor() { constructor() {
@ -210,7 +213,7 @@ var OsdWindowManager = class {
} }
for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) { for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) {
this._osdWindows[i].actor.destroy(); this._osdWindows[i].destroy();
this._osdWindows[i] = null; this._osdWindows[i] = null;
} }

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */ /* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi; const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Background = imports.ui.background; const Background = imports.ui.background;
@ -72,36 +72,108 @@ var ShellInfo = class {
if (undoCallback) if (undoCallback)
notification.addAction(_("Undo"), this._onUndoClicked.bind(this)); notification.addAction(_("Undo"), this._onUndoClicked.bind(this));
this._source.notify(notification); this._source.showNotification(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
});
let searchEntryBin = new St.Bin({
child: this._searchEntry,
x_align: St.Align.MIDDLE
});
this.add_actor(searchEntryBin);
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
// Add our same-line elements after the search entry
this.add(this._controls, { y_fill: true, expand: true });
}
get dash() {
return this._controls.dash;
}
get searchEntry() {
return this._searchEntry;
}
get viewSelector() {
return this._controls.viewSelector;
}
});
var Overview = class { var Overview = class {
constructor() { constructor() {
this._overviewCreated = false;
this._initCalled = false; this._initCalled = false;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this)); Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated(); 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() { _createOverview() {
if (this._overviewCreated) if (this._overview)
return; return;
if (this.isDummy) if (this.isDummy)
return; 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 // The main Background actors are inside global.window_group which are
// hidden when displaying the overview, so we create a new // hidden when displaying the overview, so we create a new
// one. Instances of this class share a single CoglTexture behind the // one. Instances of this class share a single CoglTexture behind the
@ -116,11 +188,11 @@ var Overview = class {
this._activationTime = 0; 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._shown = false; // show() and not hide()
this._modal = false; // have a modal grab this._modal = false; // have a modal grab
this.animationInProgress = false; this._animationInProgress = false;
this.visibleTarget = false; this._visibleTarget = false;
// During transitions, we raise this to the top to avoid having the overview // 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 // area be reactive; it causes too many issues such as double clicks on
@ -129,9 +201,6 @@ var Overview = class {
reactive: true }); reactive: true });
Main.layoutManager.overviewGroup.add_child(this._coverPane); Main.layoutManager.overviewGroup.add_child(this._coverPane);
this._coverPane.connect('event', () => Clutter.EVENT_STOP); this._coverPane.connect('event', () => Clutter.EVENT_STOP);
Main.layoutManager.overviewGroup.add_child(this._overview);
this._coverPane.hide(); this._coverPane.hide();
// XDND // XDND
@ -213,41 +282,12 @@ var Overview = class {
if (this.isDummy) if (this.isDummy)
return; return;
this._overview = new OverviewActor();
this._overview._delegate = this;
Main.layoutManager.overviewGroup.add_child(this._overview);
this._shellInfo = new ShellInfo(); 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)); Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
this._relayout(); this._relayout();
} }
@ -426,7 +466,7 @@ var Overview = class {
focusSearch() { focusSearch() {
this.show(); this.show();
this._searchEntry.grab_key_focus(); this._overview.searchEntry.grab_key_focus();
} }
fadeInDesktop() { fadeInDesktop() {
@ -464,11 +504,11 @@ var Overview = class {
// the overview if the user both triggered the hot corner and // the overview if the user both triggered the hot corner and
// clicked the Activities button. // clicked the Activities button.
shouldToggleByCornerOrButton() { shouldToggleByCornerOrButton() {
if (this.animationInProgress) if (this._animationInProgress)
return false; return false;
if (this._inItemDrag || this._inWindowDrag) if (this._inItemDrag || this._inWindowDrag)
return false; return false;
if (this._activationTime == 0 || if (!this._activationTime ||
GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT) GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
return true; return true;
return false; return false;
@ -478,7 +518,7 @@ var Overview = class {
// We delay grab changes during animation so that when removing the // 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 // overview we don't have a problem with the release of a press/release
// going to an application. // going to an application.
if (this.animationInProgress) if (this._animationInProgress)
return true; return true;
if (this._shown) { if (this._shown) {
@ -520,12 +560,12 @@ var Overview = class {
_animateVisible() { _animateVisible() {
if (this.visible || this.animationInProgress) if (this._visible || this._animationInProgress)
return; return;
this.visible = true; this._visible = true;
this.animationInProgress = true; this._animationInProgress = true;
this.visibleTarget = true; this._visibleTarget = true;
this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC; this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
@ -546,7 +586,7 @@ var Overview = class {
} }
_showDone() { _showDone() {
this.animationInProgress = false; this._animationInProgress = false;
this._desktopFade.hide(); this._desktopFade.hide();
this._coverPane.hide(); this._coverPane.hide();
@ -586,11 +626,11 @@ var Overview = class {
} }
_animateNotVisible() { _animateNotVisible() {
if (!this.visible || this.animationInProgress) if (!this._visible || this._animationInProgress)
return; return;
this.animationInProgress = true; this._animationInProgress = true;
this.visibleTarget = false; this._visibleTarget = false;
this.viewSelector.animateFromOverview(); this.viewSelector.animateFromOverview();
@ -616,8 +656,8 @@ var Overview = class {
this._desktopFade.hide(); this._desktopFade.hide();
this._coverPane.hide(); this._coverPane.hide();
this.visible = false; this._visible = false;
this.animationInProgress = false; this._animationInProgress = false;
this.emit('hidden'); this.emit('hidden');
// Handle any calls to show* while we were hiding // Handle any calls to show* while we were hiding
@ -633,14 +673,17 @@ var Overview = class {
if (this.isDummy) if (this.isDummy)
return; return;
if (this.visible) if (this._visible)
this.hide(); this.hide();
else else
this.show(); this.show();
} }
getShowAppsButton() { getShowAppsButton() {
return this._dash.showAppsButton; logError(new Error('Usage of Overview.\'getShowAppsButton\' is deprecated, ' +
'use \'dash.showAppsButton\' property instead'));
return this.dash.showAppsButton;
} }
}; };
Signals.addSignalMethods(Overview.prototype); Signals.addSignalMethods(Overview.prototype);

View File

@ -118,18 +118,21 @@ var SlideLayout = GObject.registerClass({
} }
}); });
var SlidingControl = class { var SlidingControl = GObject.registerClass(
constructor(params) { class SlidingControl extends St.Widget {
_init(params) {
params = Params.parse(params, { slideDirection: SlideDirection.LEFT }); params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
this._visible = true;
this._inDrag = false;
this.layout = new SlideLayout(); this.layout = new SlideLayout();
this.layout.slideDirection = params.slideDirection; this.layout.slideDirection = params.slideDirection;
this.actor = new St.Widget({ layout_manager: this.layout, super._init({
layout_manager: this.layout,
style_class: 'overview-controls', style_class: 'overview-controls',
clip_to_allocation: true }); clip_to_allocation: true
});
this._visible = true;
this._inDrag = false;
Main.overview.connect('hiding', this._onOverviewHiding.bind(this)); Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
@ -147,20 +150,20 @@ var SlidingControl = class {
} }
_updateSlide() { _updateSlide() {
this.actor.ease_property('@layout.slide-x', this._getSlide(), { this.ease_property('@layout.slide-x', this._getSlide(), {
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME, duration: SIDE_CONTROLS_ANIMATION_TIME,
}); });
} }
getVisibleWidth() { getVisibleWidth() {
let child = this.actor.get_first_child(); let child = this.get_first_child();
let [, , natWidth] = child.get_preferred_size(); let [, , natWidth] = child.get_preferred_size();
return natWidth; return natWidth;
} }
_getTranslation() { _getTranslation() {
let child = this.actor.get_first_child(); let child = this.get_first_child();
let direction = getRtlSlideDirection(this.layout.slideDirection, child); let direction = getRtlSlideDirection(this.layout.slideDirection, child);
let visibleWidth = this.getVisibleWidth(); let visibleWidth = this.getVisibleWidth();
@ -186,7 +189,7 @@ var SlidingControl = class {
return; return;
this.layout.translation_x = translationStart; this.layout.translation_x = translationStart;
this.actor.ease_property('@layout.translation-x', translationEnd, { this.ease_property('@layout.translation-x', translationEnd, {
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: SIDE_CONTROLS_ANIMATION_TIME, duration: SIDE_CONTROLS_ANIMATION_TIME,
}); });
@ -218,7 +221,7 @@ var SlidingControl = class {
} }
fadeIn() { fadeIn() {
this.actor.ease({ this.ease({
opacity: 255, opacity: 255,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2, duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_IN_QUAD mode: Clutter.AnimationMode.EASE_IN_QUAD
@ -226,7 +229,7 @@ var SlidingControl = class {
} }
fadeHalf() { fadeHalf() {
this.actor.ease({ this.ease({
opacity: 128, opacity: 128,
duration: SIDE_CONTROLS_ANIMATION_TIME / 2, duration: SIDE_CONTROLS_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_OUT_QUAD mode: Clutter.AnimationMode.EASE_OUT_QUAD
@ -249,37 +252,38 @@ var SlidingControl = class {
// selector; this means we can now safely set the full slide for // selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called, // the next page, since slideIn or slideOut might have been called,
// changing the visiblity // changing the visiblity
this.actor.remove_transition('@layout.slide-x'); this.remove_transition('@layout.slide-x');
this.layout.slide_x = this._getSlide(); this.layout.slide_x = this._getSlide();
this._updateTranslation(); this._updateTranslation();
} }
}; });
var ThumbnailsSlider = class extends SlidingControl { var ThumbnailsSlider = GObject.registerClass(
constructor(thumbnailsBox) { class ThumbnailsSlider extends SlidingControl {
super({ slideDirection: SlideDirection.RIGHT }); _init(thumbnailsBox) {
super._init({ slideDirection: SlideDirection.RIGHT });
this._thumbnailsBox = thumbnailsBox; this._thumbnailsBox = thumbnailsBox;
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT; this.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
this.actor.reactive = true; this.reactive = true;
this.actor.track_hover = true; this.track_hover = true;
this.actor.add_actor(this._thumbnailsBox); this.add_actor(this._thumbnailsBox);
Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this)); Main.layoutManager.connect('monitors-changed', this._updateSlide.bind(this));
global.workspace_manager.connect('active-workspace-changed', global.workspace_manager.connect('active-workspace-changed',
this._updateSlide.bind(this)); this._updateSlide.bind(this));
global.workspace_manager.connect('notify::n-workspaces', global.workspace_manager.connect('notify::n-workspaces',
this._updateSlide.bind(this)); this._updateSlide.bind(this));
this.actor.connect('notify::hover', this._updateSlide.bind(this)); this.connect('notify::hover', this._updateSlide.bind(this));
this._thumbnailsBox.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); this._thumbnailsBox.bind_property('visible', this, 'visible', GObject.BindingFlags.SYNC_CREATE);
} }
_getAlwaysZoomOut() { _getAlwaysZoomOut() {
// Always show the pager on hover, during a drag, or if workspaces are // 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 // actually used, e.g. there are windows on any non-active workspace
let workspaceManager = global.workspace_manager; let workspaceManager = global.workspace_manager;
let alwaysZoomOut = this.actor.hover || let alwaysZoomOut = this.hover ||
this._inDrag || this._inDrag ||
!Meta.prefs_get_dynamic_workspaces() || !Meta.prefs_get_dynamic_workspaces() ||
workspaceManager.n_workspaces > 2 || workspaceManager.n_workspaces > 2 ||
@ -304,12 +308,12 @@ var ThumbnailsSlider = class extends SlidingControl {
} }
getNonExpandedWidth() { getNonExpandedWidth() {
let child = this.actor.get_first_child(); let child = this.get_first_child();
return child.get_theme_node().get_length('visible-width'); return child.get_theme_node().get_length('visible-width');
} }
_onDragEnd() { _onDragEnd() {
this.actor.sync_hover(); this.sync_hover();
super._onDragEnd(); super._onDragEnd();
} }
@ -321,7 +325,7 @@ var ThumbnailsSlider = class extends SlidingControl {
if (alwaysZoomOut) if (alwaysZoomOut)
return 1; return 1;
let child = this.actor.get_first_child(); let child = this.get_first_child();
let preferredHeight = child.get_preferred_height(-1)[1]; let preferredHeight = child.get_preferred_height(-1)[1];
let expandedWidth = child.get_preferred_width(preferredHeight)[1]; let expandedWidth = child.get_preferred_width(preferredHeight)[1];
@ -335,24 +339,25 @@ var ThumbnailsSlider = class extends SlidingControl {
else else
return this.getNonExpandedWidth(); return this.getNonExpandedWidth();
} }
}; });
var DashSlider = class extends SlidingControl { var DashSlider = GObject.registerClass(
constructor(dash) { class DashSlider extends SlidingControl {
super({ slideDirection: SlideDirection.LEFT }); _init(dash) {
super._init({ slideDirection: SlideDirection.LEFT });
this._dash = dash; this._dash = dash;
// SlideLayout reads the actor's expand flags to decide // SlideLayout reads the actor's expand flags to decide
// whether to allocate the natural size to its child, or the whole // whether to allocate the natural size to its child, or the whole
// available allocation // available allocation
this._dash.actor.x_expand = true; this._dash.x_expand = true;
this.actor.x_expand = true; this.x_expand = true;
this.actor.x_align = Clutter.ActorAlign.START; this.x_align = Clutter.ActorAlign.START;
this.actor.y_expand = true; this.y_expand = true;
this.actor.add_actor(this._dash.actor); this.add_actor(this._dash);
this._dash.connect('icon-size-changed', this._updateSlide.bind(this)); this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
} }
@ -371,7 +376,7 @@ var DashSlider = class extends SlidingControl {
_onWindowDragEnd() { _onWindowDragEnd() {
this.fadeIn(); this.fadeIn();
} }
}; });
var DashSpacer = GObject.registerClass( var DashSpacer = GObject.registerClass(
class DashSpacer extends St.Widget { class DashSpacer extends St.Widget {
@ -416,12 +421,21 @@ var ControlsLayout = GObject.registerClass({
} }
}); });
var ControlsManager = class { var ControlsManager = GObject.registerClass(
constructor(searchEntry) { 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
});
this.dash = new Dash.Dash(); this.dash = new Dash.Dash();
this._dashSlider = new DashSlider(this.dash); this._dashSlider = new DashSlider(this.dash);
this._dashSpacer = new DashSpacer(); this._dashSpacer = new DashSpacer();
this._dashSpacer.setDashActor(this._dashSlider.actor); this._dashSpacer.setDashActor(this._dashSlider);
this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox(); this._thumbnailsBox = new WorkspaceThumbnail.ThumbnailsBox();
this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox); this._thumbnailsSlider = new ThumbnailsSlider(this._thumbnailsBox);
@ -431,20 +445,15 @@ var ControlsManager = class {
this.viewSelector.connect('page-changed', this._setVisibility.bind(this)); this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
this.viewSelector.connect('page-empty', this._onPageEmpty.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', this._group = new St.BoxLayout({ name: 'overview-group',
x_expand: true, y_expand: true }); x_expand: true, y_expand: true });
this.actor.add_actor(this._group); this.add_actor(this._group);
this.actor.add_actor(this._dashSlider.actor); this.add_actor(this._dashSlider);
this._group.add_actor(this._dashSpacer); this._group.add_actor(this._dashSpacer);
this._group.add(this.viewSelector.actor, { x_fill: true, this._group.add(this.viewSelector, { x_fill: true, expand: true });
expand: true }); this._group.add_actor(this._thumbnailsSlider);
this._group.add_actor(this._thumbnailsSlider.actor);
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this)); layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
@ -452,18 +461,18 @@ var ControlsManager = class {
} }
_updateWorkspacesGeometry() { _updateWorkspacesGeometry() {
let [x, y] = this.actor.get_transformed_position(); let [x, y] = this.get_transformed_position();
let [width, height] = this.actor.get_transformed_size(); let [width, height] = this.get_transformed_size();
let geometry = { x: x, y: y, width: width, height: height }; let geometry = { x: x, y: y, width: width, height: height };
let spacing = this.actor.get_theme_node().get_length('spacing'); let spacing = this.get_theme_node().get_length('spacing');
let dashWidth = this._dashSlider.getVisibleWidth() + spacing; let dashWidth = this._dashSlider.getVisibleWidth() + spacing;
let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing; let thumbnailsWidth = this._thumbnailsSlider.getNonExpandedWidth() + spacing;
geometry.width -= dashWidth; geometry.width -= dashWidth;
geometry.width -= thumbnailsWidth; geometry.width -= thumbnailsWidth;
if (this.actor.get_text_direction() == Clutter.TextDirection.LTR) if (this.get_text_direction() == Clutter.TextDirection.LTR)
geometry.x += dashWidth; geometry.x += dashWidth;
else else
geometry.x += thumbnailsWidth; geometry.x += thumbnailsWidth;
@ -510,4 +519,4 @@ var ControlsManager = class {
this._updateSpacerVisibility(); this._updateSpacerVisibility();
} }
}; });

View File

@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PadOsdService */ /* exported PadOsd, PadOsdService */
const { Atk, Clutter, GDesktopEnums, Gio, const { Atk, Clutter, GDesktopEnums, Gio,
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi; GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
@ -22,26 +22,32 @@ const CCW = 1;
const UP = 0; const UP = 0;
const DOWN = 1; const DOWN = 1;
var PadChooser = class { var PadChooser = GObject.registerClass({
constructor(device, groupDevices) { Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } }
this.actor = new St.Button({ style_class: 'pad-chooser-button', }, class PadChooser extends St.Button {
_init(device, groupDevices) {
super._init({
style_class: 'pad-chooser-button',
toggle_mode: true, toggle_mode: true,
x_fill: false, x_fill: false,
y_fill: false, y_fill: false,
x_align: St.Align.MIDDLE, x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE
});
this.currentDevice = device; this.currentDevice = device;
this._padChooserMenu = null; this._padChooserMenu = null;
let arrow = new St.Icon({ style_class: 'popup-menu-arrow', let arrow = new St.Icon({ style_class: 'popup-menu-arrow',
icon_name: 'pan-down-symbolic', icon_name: 'pan-down-symbolic',
accessible_role: Atk.Role.ARROW }); accessible_role: Atk.Role.ARROW });
this.actor.set_child(arrow); this.set_child(arrow);
this._ensureMenu(groupDevices); this._ensureMenu(groupDevices);
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('clicked', actor => { }
if (actor.get_checked()) {
vfunc_clicked() {
if (this.get_checked()) {
if (this._padChooserMenu != null) if (this._padChooserMenu != null)
this._padChooserMenu.open(true); this._padChooserMenu.open(true);
else else
@ -49,13 +55,12 @@ var PadChooser = class {
} else { } else {
this._padChooserMenu.close(true); this._padChooserMenu.close(true);
} }
});
} }
_ensureMenu(devices) { _ensureMenu(devices) {
this._padChooserMenu = new PopupMenu.PopupMenu(this.actor, 0.5, St.Side.TOP); this._padChooserMenu = new PopupMenu.PopupMenu(this, 0.5, St.Side.TOP);
this._padChooserMenu.connect('menu-closed', () => { this._padChooserMenu.connect('menu-closed', () => {
this.actor.set_checked(false); this.set_checked(false);
}); });
this._padChooserMenu.actor.hide(); this._padChooserMenu.actor.hide();
Main.uiGroup.add_actor(this._padChooserMenu.actor); Main.uiGroup.add_actor(this._padChooserMenu.actor);
@ -78,24 +83,20 @@ var PadChooser = class {
update(devices) { update(devices) {
if (this._padChooserMenu) if (this._padChooserMenu)
this._padChooserMenu.actor.destroy(); this._padChooserMenu.actor.destroy();
this.actor.set_checked(false); this.set_checked(false);
this._ensureMenu(devices); this._ensureMenu(devices);
} }
});
destroy() { var KeybindingEntry = GObject.registerClass({
this.actor.destroy(); GTypeName: 'PadOsd_KeybindingEntry',
} Signals: { 'keybinding-edited': {} }
}; }, class KeybindingEntry extends St.Entry {
Signals.addSignalMethods(PadChooser.prototype); _init() {
super._init({ hint_text: _("New shortcut…"), style: 'width: 10em' });
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));
} }
_onCapturedEvent(actor, event) { vfunc_captured_event(event) {
if (event.type() != Clutter.EventType.KEY_PRESS) if (event.type() != Clutter.EventType.KEY_PRESS)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@ -103,23 +104,24 @@ var KeybindingEntry = class {
event.get_key_symbol(), event.get_key_symbol(),
event.get_key_code(), event.get_key_code(),
event.get_state()); event.get_state());
this.actor.set_text(str); this.set_text(str);
this.emit('keybinding-edited', str); this.emit('keybinding-edited', str);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
}; });
Signals.addSignalMethods(KeybindingEntry.prototype);
var ActionComboBox = class { var ActionComboBox = GObject.registerClass({
constructor() { GTypeName: 'PadOsd_ActionComboBox',
this.actor = new St.Button({ style_class: 'button' }); Signals: { 'action-selected': { param_types: [GObject.TYPE_INT] } }
this.actor.connect('clicked', this._onButtonClicked.bind(this)); }, class ActionComboBox extends St.Button {
this.actor.set_toggle_mode(true); _init() {
super._init({ style_class: 'button' });
this.set_toggle_mode(true);
let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL, let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
spacing: 6 }); spacing: 6 });
let box = new St.Widget({ layout_manager: boxLayout }); let box = new St.Widget({ layout_manager: boxLayout });
this.actor.set_child(box); this.set_child(box);
this._label = new St.Label({ style_class: 'combo-box-label' }); this._label = new St.Label({ style_class: 'combo-box-label' });
box.add_child(this._label); box.add_child(this._label);
@ -131,9 +133,9 @@ var ActionComboBox = class {
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
box.add_child(arrow); box.add_child(arrow);
this._editMenu = new PopupMenu.PopupMenu(this.actor, 0, St.Side.TOP); this._editMenu = new PopupMenu.PopupMenu(this, 0, St.Side.TOP);
this._editMenu.connect('menu-closed', () => { this._editMenu.connect('menu-closed', () => {
this.actor.set_checked(false); this.set_checked(false);
}); });
this._editMenu.actor.hide(); this._editMenu.actor.hide();
Main.uiGroup.add_actor(this._editMenu.actor); Main.uiGroup.add_actor(this._editMenu.actor);
@ -179,8 +181,8 @@ var ActionComboBox = class {
this._editMenu.close(true); this._editMenu.close(true);
} }
_onButtonClicked() { vfunc_clicked() {
if (this.actor.get_checked()) if (this.get_checked())
this.popup(); this.popup();
else else
this.popdown(); this.popdown();
@ -189,38 +191,40 @@ var ActionComboBox = class {
setButtonActionsActive(active) { setButtonActionsActive(active) {
this._buttonItems.forEach(item => item.setSensitive(active)); this._buttonItems.forEach(item => item.setSensitive(active));
} }
}; });
Signals.addSignalMethods(ActionComboBox.prototype);
var ActionEditor = class { var ActionEditor = GObject.registerClass({
constructor() { GTypeName: 'PadOsd_ActionEditor',
Signals: { 'done': {} }
}, class ActionEditor extends St.Widget {
_init() {
let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL, let boxLayout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL,
spacing: 12 }); spacing: 12 });
this.actor = new St.Widget({ layout_manager: boxLayout }); super._init({ layout_manager: boxLayout });
this._actionComboBox = new ActionComboBox(); this._actionComboBox = new ActionComboBox();
this._actionComboBox.connect('action-selected', this._onActionSelected.bind(this)); this._actionComboBox.connect('action-selected', this._onActionSelected.bind(this));
this.actor.add_actor(this._actionComboBox.actor); this.add_actor(this._actionComboBox);
this._keybindingEdit = new KeybindingEntry(); this._keybindingEdit = new KeybindingEntry();
this._keybindingEdit.connect('keybinding-edited', this._onKeybindingEdited.bind(this)); this._keybindingEdit.connect('keybinding-edited', this._onKeybindingEdited.bind(this));
this.actor.add_actor(this._keybindingEdit.actor); this.add_actor(this._keybindingEdit);
this._doneButton = new St.Button({ label: _("Done"), this._doneButton = new St.Button({ label: _("Done"),
style_class: 'button', style_class: 'button',
x_expand: false }); x_expand: false });
this._doneButton.connect('clicked', this._onEditingDone.bind(this)); this._doneButton.connect('clicked', this._onEditingDone.bind(this));
this.actor.add_actor(this._doneButton); this.add_actor(this._doneButton);
} }
_updateKeybindingEntryState() { _updateKeybindingEntryState() {
if (this._currentAction == GDesktopEnums.PadButtonAction.KEYBINDING) { if (this._currentAction == GDesktopEnums.PadButtonAction.KEYBINDING) {
this._keybindingEdit.actor.set_text(this._currentKeybinding); this._keybindingEdit.set_text(this._currentKeybinding);
this._keybindingEdit.actor.show(); this._keybindingEdit.show();
this._keybindingEdit.actor.grab_key_focus(); this._keybindingEdit.grab_key_focus();
} else { } else {
this._keybindingEdit.actor.hide(); this._keybindingEdit.hide();
} }
} }
@ -238,7 +242,7 @@ var ActionEditor = class {
close() { close() {
this._actionComboBox.popdown(); this._actionComboBox.popdown();
this.actor.hide(); this.hide();
} }
_onKeybindingEdited(entry, keybinding) { _onKeybindingEdited(entry, keybinding) {
@ -272,8 +276,7 @@ var ActionEditor = class {
this.close(); this.close();
this.emit('done'); this.emit('done');
} }
}; });
Signals.addSignalMethods(ActionEditor.prototype);
var PadDiagram = GObject.registerClass({ var PadDiagram = GObject.registerClass({
Properties: { Properties: {
@ -615,8 +618,18 @@ var PadDiagram = GObject.registerClass({
} }
}); });
var PadOsd = class { var PadOsd = GObject.registerClass({
constructor(padDevice, settings, imagePath, editionMode, monitorIndex) { Signals: { 'pad-selected': { param_types: [Clutter.InputDevice.$gtype] } }
}, 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
});
this.padDevice = padDevice; this.padDevice = padDevice;
this._groupPads = [padDevice]; this._groupPads = [padDevice];
this._settings = settings; this._settings = settings;
@ -653,23 +666,18 @@ var PadOsd = class {
this._groupPads.push(device); this._groupPads.push(device);
}); });
this.actor = new St.BoxLayout({ style_class: 'pad-osd-window', this.connect('destroy', this._onDestroy.bind(this));
x_expand: true, Main.uiGroup.add_actor(this);
y_expand: true,
vertical: true,
reactive: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
Main.uiGroup.add_actor(this.actor);
this._monitorIndex = monitorIndex; this._monitorIndex = monitorIndex;
let constraint = new Layout.MonitorConstraint({ index: monitorIndex }); let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
this.actor.add_constraint(constraint); this.add_constraint(constraint);
this._titleBox = new St.BoxLayout({ style_class: 'pad-osd-title-box', this._titleBox = new St.BoxLayout({ style_class: 'pad-osd-title-box',
vertical: false, vertical: false,
x_expand: false, x_expand: false,
x_align: Clutter.ActorAlign.CENTER }); x_align: Clutter.ActorAlign.CENTER });
this.actor.add_actor(this._titleBox); this.add_actor(this._titleBox);
let labelBox = new St.BoxLayout({ style_class: 'pad-osd-title-menu-box', let labelBox = new St.BoxLayout({ style_class: 'pad-osd-title-menu-box',
vertical: true }); vertical: true });
@ -690,10 +698,10 @@ var PadOsd = class {
this._padDiagram = new PadDiagram({ image: this._imagePath, this._padDiagram = new PadDiagram({ image: this._imagePath,
left_handed: settings.get_boolean('left-handed'), left_handed: settings.get_boolean('left-handed'),
editor_actor: this._actionEditor.actor, editor_actor: this._actionEditor,
x_expand: true, x_expand: true,
y_expand: true }); y_expand: true });
this.actor.add_actor(this._padDiagram); this.add_actor(this._padDiagram);
// FIXME: Fix num buttons. // FIXME: Fix num buttons.
let i = 0; let i = 0;
@ -724,7 +732,7 @@ var PadOsd = class {
x_expand: true, x_expand: true,
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
this.actor.add_actor(buttonBox); this.add_actor(buttonBox);
this._editButton = new St.Button({ label: _("Edit…"), this._editButton = new St.Button({ label: _("Edit…"),
style_class: 'button', style_class: 'button',
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
@ -735,7 +743,7 @@ var PadOsd = class {
buttonBox.add_actor(this._editButton); buttonBox.add_actor(this._editButton);
this._syncEditionMode(); this._syncEditionMode();
Main.pushModal(this.actor); Main.pushModal(this);
} }
_updatePadChooser() { _updatePadChooser() {
@ -745,7 +753,7 @@ var PadOsd = class {
this._padChooser.connect('pad-selected', (chooser, pad) => { this._padChooser.connect('pad-selected', (chooser, pad) => {
this._requestForOtherPad(pad); this._requestForOtherPad(pad);
}); });
this._titleBox.add_child(this._padChooser.actor); this._titleBox.add_child(this._padChooser);
} else { } else {
this._padChooser.update(this._groupPads); this._padChooser.update(this._groupPads);
} }
@ -918,12 +926,8 @@ var PadOsd = class {
this._syncEditionMode(); this._syncEditionMode();
} }
destroy() {
this.actor.destroy();
}
_onDestroy() { _onDestroy() {
Main.popModal(this.actor); Main.popModal(this);
this._actionEditor.close(); this._actionEditor.close();
let deviceManager = Clutter.DeviceManager.get_default(); let deviceManager = Clutter.DeviceManager.get_default();
@ -941,11 +945,9 @@ var PadOsd = class {
this._capturedEventId = 0; this._capturedEventId = 0;
} }
this.actor = null;
this.emit('closed'); this.emit('closed');
} }
}; });
Signals.addSignalMethods(PadOsd.prototype);
const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd'); const PadOsdIface = loadInterfaceXML('org.gnome.Shell.Wacom.PadOsd');

View File

@ -20,14 +20,17 @@ var ANIMATION_DELAY = 100;
var PageIndicators = GObject.registerClass({ 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 { }, class PageIndicators extends St.BoxLayout {
_init(vertical = true) { _init(orientation = Clutter.Orientation.VERTICAL) {
super._init({ style_class: 'page-indicators', let vertical = orientation == Clutter.Orientation.VERTICAL;
super._init({
style_class: 'page-indicators',
vertical, vertical,
x_expand: true, y_expand: true, x_expand: true, y_expand: true,
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER, x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END, y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
reactive: true, reactive: true,
clip_to_allocation: true }); clip_to_allocation: true
});
this._nPages = 0; this._nPages = 0;
this._currentPage = undefined; this._currentPage = undefined;
this._reactive = true; this._reactive = true;
@ -93,19 +96,27 @@ var PageIndicators = GObject.registerClass({
var AnimatedPageIndicators = GObject.registerClass( var AnimatedPageIndicators = GObject.registerClass(
class AnimatedPageIndicators extends PageIndicators { class AnimatedPageIndicators extends PageIndicators {
_init() { _init() {
super._init(true); super._init();
this.connect('destroy', this._onDestroy.bind(this));
}
this.connect('notify::mapped', () => { _onDestroy() {
if (!this.mapped) if (this.animateLater) {
return; Meta.later_remove(this.animateLater);
this.animateLater = 0;
}
}
vfunc_map() {
super.vfunc_map();
// Implicit animations are skipped for unmapped actors, and our // Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler // children aren't mapped yet, so defer to a later handler
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this.animateLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateLater = 0;
this.animateIndicators(AnimationDirection.IN); this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
});
} }
animateIndicators(animationDirection) { animateIndicators(animationDirection) {

View File

@ -235,7 +235,7 @@ var AppMenuButton = GObject.registerClass({
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this)); this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true); this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
this._container.add_actor(this._spinner.actor); this._container.add_actor(this._spinner);
let menu = new AppMenu(this); let menu = new AppMenu(this);
this.setMenu(menu); this.setMenu(menu);
@ -430,9 +430,6 @@ class ActivitiesButton extends PanelMenu.Button {
this.label_actor = this._label; 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', () => { Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview'); this.add_style_pseudo_class('overview');
this.add_accessible_state (Atk.StateType.CHECKED); this.add_accessible_state (Atk.StateType.CHECKED);
@ -459,7 +456,7 @@ class ActivitiesButton extends PanelMenu.Button {
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
} }
_onCapturedEvent(actor, event) { vfunc_captured_event(event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS || if (event.type() == Clutter.EventType.BUTTON_PRESS ||
event.type() == Clutter.EventType.TOUCH_BEGIN) { event.type() == Clutter.EventType.TOUCH_BEGIN) {
if (!Main.overview.shouldToggleByCornerOrButton()) if (!Main.overview.shouldToggleByCornerOrButton())
@ -468,9 +465,7 @@ class ActivitiesButton extends PanelMenu.Button {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onEvent(actor, event) { vfunc_event(event) {
super._onEvent(actor, event);
if (event.type() == Clutter.EventType.TOUCH_END || if (event.type() == Clutter.EventType.TOUCH_END ||
event.type() == Clutter.EventType.BUTTON_RELEASE) event.type() == Clutter.EventType.BUTTON_RELEASE)
if (Main.overview.shouldToggleByCornerOrButton()) if (Main.overview.shouldToggleByCornerOrButton())
@ -479,13 +474,16 @@ class ActivitiesButton extends PanelMenu.Button {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onKeyRelease(actor, event) { vfunc_key_release_event(keyEvent) {
let symbol = event.get_key_symbol(); let ret = super.vfunc_key_release_event(keyEvent);
if (ret == Clutter.EVENT_PROPAGATE) {
let symbol = keyEvent.keyval;
if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) { if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
if (Main.overview.shouldToggleByCornerOrButton()) if (Main.overview.shouldToggleByCornerOrButton())
Main.overview.toggle(); Main.overview.toggle();
} }
return Clutter.EVENT_PROPAGATE; }
return ret;
} }
_xdndToggleOverview() { _xdndToggleOverview() {
@ -501,13 +499,12 @@ class ActivitiesButton extends PanelMenu.Button {
} }
}); });
var PanelCorner = class { var PanelCorner = GObject.registerClass(
constructor(side) { class PanelCorner extends St.DrawingArea {
_init(side) {
this._side = side; this._side = side;
this.actor = new St.DrawingArea({ style_class: 'panel-corner' }); super._init({ style_class: 'panel-corner' });
this.actor.connect('style-changed', this._styleChanged.bind(this));
this.actor.connect('repaint', this._repaint.bind(this));
} }
_findRightmostButton(container) { _findRightmostButton(container) {
@ -597,7 +594,7 @@ var PanelCorner = class {
this._buttonStyleChangedSignalId = button.connect('style-changed', this._buttonStyleChangedSignalId = button.connect('style-changed',
() => { () => {
let pseudoClass = button.get_style_pseudo_class(); let pseudoClass = button.get_style_pseudo_class();
this.actor.set_style_pseudo_class(pseudoClass); this.set_style_pseudo_class(pseudoClass);
}); });
// The corner doesn't support theme transitions, so override // The corner doesn't support theme transitions, so override
@ -606,8 +603,8 @@ var PanelCorner = class {
} }
} }
_repaint() { vfunc_repaint() {
let node = this.actor.get_theme_node(); let node = this.get_theme_node();
let cornerRadius = node.get_length("-panel-corner-radius"); let cornerRadius = node.get_length("-panel-corner-radius");
let borderWidth = node.get_length('-panel-corner-border-width'); let borderWidth = node.get_length('-panel-corner-border-width');
@ -618,7 +615,7 @@ var PanelCorner = class {
let overlap = borderColor.alpha != 0; let overlap = borderColor.alpha != 0;
let offsetY = overlap ? 0 : borderWidth; let offsetY = overlap ? 0 : borderWidth;
let cr = this.actor.get_context(); let cr = this.get_context();
cr.setOperator(Cairo.Operator.SOURCE); cr.setOperator(Cairo.Operator.SOURCE);
cr.moveTo(0, offsetY); cr.moveTo(0, offsetY);
@ -654,16 +651,17 @@ var PanelCorner = class {
cr.$dispose(); cr.$dispose();
} }
_styleChanged() { vfunc_style_changed() {
let node = this.actor.get_theme_node(); super.vfunc_style_changed();
let node = this.get_theme_node();
let cornerRadius = node.get_length("-panel-corner-radius"); let cornerRadius = node.get_length("-panel-corner-radius");
let borderWidth = node.get_length('-panel-corner-border-width'); let borderWidth = node.get_length('-panel-corner-border-width');
this.actor.set_size(cornerRadius, borderWidth + cornerRadius); this.set_size(cornerRadius, borderWidth + cornerRadius);
this.actor.set_anchor_point(0, borderWidth); this.set_anchor_point(0, borderWidth);
} }
}; });
var AggregateLayout = GObject.registerClass( var AggregateLayout = GObject.registerClass(
class AggregateLayout extends Clutter.BoxLayout { class AggregateLayout extends Clutter.BoxLayout {
@ -728,20 +726,20 @@ class AggregateMenu extends PanelMenu.Button {
this._nightLight = new imports.ui.status.nightLight.Indicator(); this._nightLight = new imports.ui.status.nightLight.Indicator();
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator(); this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
this._indicators.add_child(this._thunderbolt.indicators); this._indicators.add_child(this._thunderbolt);
this._indicators.add_child(this._screencast.indicators); this._indicators.add_child(this._screencast);
this._indicators.add_child(this._location.indicators); this._indicators.add_child(this._location);
this._indicators.add_child(this._nightLight.indicators); this._indicators.add_child(this._nightLight);
if (this._network) { if (this._network) {
this._indicators.add_child(this._network.indicators); this._indicators.add_child(this._network);
} }
if (this._bluetooth) { if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators); this._indicators.add_child(this._bluetooth);
} }
this._indicators.add_child(this._remoteAccess.indicators); this._indicators.add_child(this._remoteAccess);
this._indicators.add_child(this._rfkill.indicators); this._indicators.add_child(this._rfkill);
this._indicators.add_child(this._volume.indicators); this._indicators.add_child(this._volume);
this._indicators.add_child(this._power.indicators); this._indicators.add_child(this._power);
this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM)); this._indicators.add_child(PopupMenu.arrowIcon(St.Side.BOTTOM));
this.menu.addMenuItem(this._volume.menu); this.menu.addMenuItem(this._volume.menu);
@ -799,14 +797,10 @@ class Panel extends St.Widget {
this.add_child(this._rightBox); this.add_child(this._rightBox);
this._leftCorner = new PanelCorner(St.Side.LEFT); this._leftCorner = new PanelCorner(St.Side.LEFT);
this.add_child(this._leftCorner.actor); this.add_child(this._leftCorner);
this._rightCorner = new PanelCorner(St.Side.RIGHT); this._rightCorner = new PanelCorner(St.Side.RIGHT);
this.add_child(this._rightCorner.actor); this.add_child(this._rightCorner);
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', () => { Main.overview.connect('showing', () => {
this.add_style_pseudo_class('overview'); this.add_style_pseudo_class('overview');
@ -895,62 +889,65 @@ class Panel extends St.Widget {
let cornerWidth, cornerHeight; let cornerWidth, cornerHeight;
[, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1); [, cornerWidth] = this._leftCorner.get_preferred_width(-1);
[, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1); [, cornerHeight] = this._leftCorner.get_preferred_height(-1);
childBox.x1 = 0; childBox.x1 = 0;
childBox.x2 = cornerWidth; childBox.x2 = cornerWidth;
childBox.y1 = allocHeight; childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight; childBox.y2 = allocHeight + cornerHeight;
this._leftCorner.actor.allocate(childBox, flags); this._leftCorner.allocate(childBox, flags);
[, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1); [, cornerWidth] = this._rightCorner.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1); [, cornerHeight] = this._rightCorner.get_preferred_height(-1);
childBox.x1 = allocWidth - cornerWidth; childBox.x1 = allocWidth - cornerWidth;
childBox.x2 = allocWidth; childBox.x2 = allocWidth;
childBox.y1 = allocHeight; childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight; childBox.y2 = allocHeight + cornerHeight;
this._rightCorner.actor.allocate(childBox, flags); this._rightCorner.allocate(childBox, flags);
} }
_onButtonPress(actor, event) { _tryDragWindow(event) {
if (Main.modalCount > 0) if (Main.modalCount > 0)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (event.get_source() != actor) if (event.source != this)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let type = event.type(); let { x, y } = event;
let isPress = type == Clutter.EventType.BUTTON_PRESS; let dragWindow = this._getDraggableWindowForPosition(x);
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) if (!dragWindow)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
global.display.begin_grab_op(dragWindow, return global.display.begin_grab_op(
dragWindow,
Meta.GrabOp.MOVING, Meta.GrabOp.MOVING,
false, /* pointer grab */ false, /* pointer grab */
true, /* frame action */ true, /* frame action */
button, event.button || -1,
event.get_state(), event.modifier_state,
event.get_time(), event.time,
stageX, stageY); x, y) ? Clutter.EVENT_STOP : Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
} }
_onKeyPress(actor, event) { vfunc_button_press_event(buttonEvent) {
let symbol = event.get_key_symbol(); 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;
if (symbol == Clutter.KEY_Escape) { if (symbol == Clutter.KEY_Escape) {
global.display.focus_default_window(event.get_time()); global.display.focus_default_window(keyEvent.time);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -1114,14 +1111,14 @@ class Panel extends St.Widget {
_addStyleClassName(className) { _addStyleClassName(className) {
this.add_style_class_name(className); this.add_style_class_name(className);
this._rightCorner.actor.add_style_class_name(className); this._rightCorner.add_style_class_name(className);
this._leftCorner.actor.add_style_class_name(className); this._leftCorner.add_style_class_name(className);
} }
_removeStyleClassName(className) { _removeStyleClassName(className) {
this.remove_style_class_name(className); this.remove_style_class_name(className);
this._rightCorner.actor.remove_style_class_name(className); this._rightCorner.remove_style_class_name(className);
this._leftCorner.actor.remove_style_class_name(className); this._leftCorner.remove_style_class_name(className);
} }
_onMenuSet(indicator) { _onMenuSet(indicator) {

View File

@ -2,7 +2,6 @@
/* exported Button, SystemIndicator */ /* exported Button, SystemIndicator */
const { Atk, Clutter, GObject, St } = imports.gi; const { Atk, Clutter, GObject, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
@ -101,9 +100,6 @@ var Button = GObject.registerClass({
accessible_name: nameText ? nameText : "", accessible_name: nameText ? nameText : "",
accessible_role: Atk.Role.MENU }); accessible_role: Atk.Role.MENU });
this.connect('event', this._onEvent.bind(this));
this.connect('notify::visible', this._onVisibilityChanged.bind(this));
if (dontCreateMenu) if (dontCreateMenu)
this.menu = new PopupMenu.PopupDummyMenu(this); this.menu = new PopupMenu.PopupDummyMenu(this);
else else
@ -132,7 +128,7 @@ var Button = GObject.registerClass({
this.emit('menu-set'); this.emit('menu-set');
} }
_onEvent(actor, event) { vfunc_event(event) {
if (this.menu && if (this.menu &&
(event.type() == Clutter.EventType.TOUCH_BEGIN || (event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS)) event.type() == Clutter.EventType.BUTTON_PRESS))
@ -141,11 +137,10 @@ var Button = GObject.registerClass({
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onVisibilityChanged() { vfunc_hide() {
if (!this.menu) super.vfunc_hide();
return;
if (!this.visible) if (this.menu)
this.menu.close(); this.menu.close();
} }
@ -200,24 +195,34 @@ var Button = GObject.registerClass({
* of an icon and a menu section, which will be composed into the * of an icon and a menu section, which will be composed into the
* aggregate menu. * aggregate menu.
*/ */
var SystemIndicator = class { var SystemIndicator = GObject.registerClass({
constructor() { GTypeName: 'PanelMenu_SystemIndicator',
this.indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box', }, class SystemIndicator extends St.BoxLayout {
reactive: true }); _init() {
this.indicators.hide(); super._init({
style_class: 'panel-status-indicators-box',
reactive: true,
visible: false
});
this.menu = new PopupMenu.PopupMenuSection(); 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() { _syncIndicatorsVisible() {
this.indicators.visible = this.indicators.get_children().some(a => a.visible); this.visible = this.get_children().some(a => a.visible);
} }
_addIndicator() { _addIndicator() {
let icon = new St.Icon({ style_class: 'system-status-icon' }); let icon = new St.Icon({ style_class: 'system-status-icon' });
this.indicators.add_actor(icon); this.add_actor(icon);
icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this)); icon.connect('notify::visible', this._syncIndicatorsVisible.bind(this));
this._syncIndicatorsVisible(); this._syncIndicatorsVisible();
return icon; return icon;
} }
}; });
Signals.addSignalMethods(SystemIndicator.prototype);

View File

@ -3,7 +3,7 @@
PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu, PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */ PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */
const { Atk, Clutter, Gio, GObject, Shell, St } = imports.gi; const { Atk, Clutter, Gio, GObject, Graphene, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
@ -97,12 +97,6 @@ var PopupBaseMenuItem = GObject.registerClass({
if (params.style_class) if (params.style_class)
this.add_style_class_name(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) if (params.reactive && params.hover)
this.bind_property('hover', this, 'active', GObject.BindingFlags.SYNC_CREATE); this.bind_property('hover', this, 'active', GObject.BindingFlags.SYNC_CREATE);
} }
@ -124,32 +118,44 @@ var PopupBaseMenuItem = GObject.registerClass({
this._parent = parent; this._parent = parent;
} }
_onButtonPressEvent() { vfunc_button_press_event(buttonEvent) {
if (!this._activatable)
return super.vfunc_button_press_event(buttonEvent);
// This is the CSS active state // This is the CSS active state
this.add_style_pseudo_class('active'); this.add_style_pseudo_class('active');
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onButtonReleaseEvent(actor, event) { vfunc_button_release_event(buttonEvent) {
if (!this._activatable)
return super.vfunc_button_release_event(buttonEvent);
this.remove_style_pseudo_class('active'); this.remove_style_pseudo_class('active');
this.activate(event); this.activate(Clutter.get_current_event());
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_onTouchEvent(actor, event) { vfunc_touch_event(touchEvent) {
if (event.type() == Clutter.EventType.TOUCH_END) { if (!this._activatable)
return super.vfunc_touch_event(touchEvent);
if (touchEvent.type == Clutter.EventType.TOUCH_END) {
this.remove_style_pseudo_class('active'); this.remove_style_pseudo_class('active');
this.activate(event); this.activate(Clutter.get_current_event());
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (event.type() == Clutter.EventType.TOUCH_BEGIN) { } else if (touchEvent.type == Clutter.EventType.TOUCH_BEGIN) {
// This is the CSS active state // This is the CSS active state
this.add_style_pseudo_class('active'); this.add_style_pseudo_class('active');
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onKeyPressEvent(actor, event) { vfunc_key_press_event(keyEvent) {
let state = event.get_state(); if (!this._activatable)
return super.vfunc_key_press_event(keyEvent);
let state = keyEvent.modifier_state;
// if user has a modifier down (except capslock and numlock) // if user has a modifier down (except capslock and numlock)
// then don't handle the key press here // then don't handle the key press here
@ -160,9 +166,9 @@ var PopupBaseMenuItem = GObject.registerClass({
if (state) if (state)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let symbol = event.get_key_symbol(); let symbol = keyEvent.keyval;
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) { if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.activate(event); this.activate(Clutter.get_current_event());
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@ -1130,7 +1136,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
this.add(expander, { expand: true }); this.add(expander, { expand: true });
this._triangle = arrowIcon(St.Side.RIGHT); this._triangle = arrowIcon(St.Side.RIGHT);
this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 }); this._triangle.pivot_point = new Graphene.Point({ x: 0.5, y: 0.6 });
this._triangleBin = new St.Widget({ y_expand: true, this._triangleBin = new St.Widget({ y_expand: true,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
@ -1185,8 +1191,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return this.menu.isOpen; return this.menu.isOpen;
} }
_onKeyPressEvent(actor, event) { vfunc_key_press_event(keyPressEvent) {
let symbol = event.get_key_symbol(); let symbol = keyPressEvent.keyval;
if (symbol == Clutter.KEY_Right) { if (symbol == Clutter.KEY_Right) {
this._setOpenState(true); this._setOpenState(true);
@ -1197,14 +1203,14 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
return super._onKeyPressEvent(actor, event); return super.vfunc_key_press_event(keyPressEvent);
} }
activate(_event) { activate(_event) {
this._setOpenState(true); this._setOpenState(true);
} }
_onButtonReleaseEvent() { vfunc_button_release_event() {
// Since we override the parent, we need to manage what the parent does // Since we override the parent, we need to manage what the parent does
// with the active style class // with the active style class
this.remove_style_pseudo_class('active'); this.remove_style_pseudo_class('active');
@ -1212,8 +1218,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onTouchEvent(actor, event) { vfunc_touch_event(touchEvent) {
if (event.type() == Clutter.EventType.TOUCH_END) { if (touchEvent.type == Clutter.EventType.TOUCH_END) {
// Since we override the parent, we need to manage what the parent does // Since we override the parent, we need to manage what the parent does
// with the active style class // with the active style class
this.remove_style_pseudo_class('active'); this.remove_style_pseudo_class('active');

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { AccountsService, Clutter, Cogl, Gio, GLib, const { AccountsService, Clutter, Cogl, Gio, GLib,
GnomeDesktop, GObject, Meta, Shell, St } = imports.gi; GnomeDesktop, GObject, Graphene, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo; const Cairo = imports.cairo;
const Signals = imports.signals; const Signals = imports.signals;
@ -17,6 +17,8 @@ const MessageTray = imports.ui.messageTray;
const ShellDBus = imports.ui.shellDBus; const ShellDBus = imports.ui.shellDBus;
const SmartcardManager = imports.misc.smartcardManager; const SmartcardManager = imports.misc.smartcardManager;
const { adjustAnimationTime } = imports.ui.environment;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled'; const LOCK_ENABLED_KEY = 'lock-enabled';
const LOCK_DELAY_KEY = 'lock-delay'; const LOCK_DELAY_KEY = 'lock-delay';
@ -46,21 +48,23 @@ var STANDARD_FADE_TIME = 10000;
var MANUAL_FADE_TIME = 300; var MANUAL_FADE_TIME = 300;
var CURTAIN_SLIDE_TIME = 300; var CURTAIN_SLIDE_TIME = 300;
var Clock = class { var Clock = GObject.registerClass(
constructor() { class ScreenShieldClock extends St.BoxLayout {
this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock', _init() {
vertical: true }); super._init({ style_class: 'screen-shield-clock', vertical: true });
this._time = new St.Label({ style_class: 'screen-shield-clock-time' }); this._time = new St.Label({ style_class: 'screen-shield-clock-time' });
this._date = new St.Label({ style_class: 'screen-shield-clock-date' }); this._date = new St.Label({ style_class: 'screen-shield-clock-date' });
this.actor.add(this._time, { x_align: St.Align.MIDDLE }); this.add(this._time, { x_align: St.Align.MIDDLE });
this.actor.add(this._date, { x_align: St.Align.MIDDLE }); this.add(this._date, { x_align: St.Align.MIDDLE });
this._wallClock = new GnomeDesktop.WallClock({ time_only: true }); this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
this._wallClock.connect('notify::clock', this._updateClock.bind(this)); this._wallClock.connect('notify::clock', this._updateClock.bind(this));
this._updateClock(); this._updateClock();
this.connect('destroy', this._onDestroy.bind(this));
} }
_updateClock() { _updateClock() {
@ -73,17 +77,20 @@ var Clock = class {
this._date.text = date.toLocaleFormat(dateFormat); this._date.text = date.toLocaleFormat(dateFormat);
} }
destroy() { _onDestroy() {
this.actor.destroy();
this._wallClock.run_dispose(); this._wallClock.run_dispose();
} }
}; });
var NotificationsBox = class { var NotificationsBox = GObject.registerClass({
constructor() { Signals: { 'wake-up-screen': {} }
this.actor = new St.BoxLayout({ vertical: true, }, class NotificationsBox extends St.BoxLayout {
_init() {
super._init({
vertical: true,
name: 'screenShieldNotifications', name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-container' }); style_class: 'screen-shield-notifications-container'
});
this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START, this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
hscrollbar_policy: St.PolicyType.NEVER }); hscrollbar_policy: St.PolicyType.NEVER });
@ -91,7 +98,7 @@ var NotificationsBox = class {
style_class: 'screen-shield-notifications-container' }); style_class: 'screen-shield-notifications-container' });
this._scrollView.add_actor(this._notificationBox); this._scrollView.add_actor(this._notificationBox);
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START }); this.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
this._sources = new Map(); this._sources = new Map();
Main.messageTray.getSources().forEach(source => { Main.messageTray.getSources().forEach(source => {
@ -100,9 +107,11 @@ var NotificationsBox = class {
this._updateVisibility(); this._updateVisibility();
this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this)); this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
} }
destroy() { _onDestroy() {
if (this._sourceAddedId) { if (this._sourceAddedId) {
Main.messageTray.disconnect(this._sourceAddedId); Main.messageTray.disconnect(this._sourceAddedId);
this._sourceAddedId = 0; this._sourceAddedId = 0;
@ -112,15 +121,13 @@ var NotificationsBox = class {
for (let [source, obj] of items) { for (let [source, obj] of items) {
this._removeSource(source, obj); this._removeSource(source, obj);
} }
this.actor.destroy();
} }
_updateVisibility() { _updateVisibility() {
this._notificationBox.visible = this._notificationBox.visible =
this._notificationBox.get_children().some(a => a.visible); this._notificationBox.get_children().some(a => a.visible);
this.actor.visible = this._notificationBox.visible; this.visible = this._notificationBox.visible;
} }
_makeNotificationCountText(count, isChat) { _makeNotificationCountText(count, isChat) {
@ -222,14 +229,14 @@ var NotificationsBox = class {
this._showSource(source, obj, obj.sourceBox); this._showSource(source, obj, obj.sourceBox);
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START }); this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
obj.sourceCountChangedId = source.connect('count-updated', source => { obj.sourceCountChangedId = source.connect('notify::count', source => {
this._countChanged(source, obj); this._countChanged(source, obj);
}); });
obj.sourceTitleChangedId = source.connect('title-changed', source => { obj.sourceTitleChangedId = source.connect('notify::title', source => {
this._titleChanged(source, obj); this._titleChanged(source, obj);
}); });
obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => { obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => {
if (key == 'show-in-lock-screen') if (pspec.name == 'show-in-lock-screen')
this._visibleChanged(source, obj); this._visibleChanged(source, obj);
else else
this._detailedChanged(source, obj); this._detailedChanged(source, obj);
@ -336,8 +343,7 @@ var NotificationsBox = class {
this._sources.delete(source); this._sources.delete(source);
} }
}; });
Signals.addSignalMethods(NotificationsBox.prototype);
var Arrow = GObject.registerClass( var Arrow = GObject.registerClass(
class ScreenShieldArrow extends St.Bin { class ScreenShieldArrow extends St.Bin {
@ -486,7 +492,7 @@ var ScreenShield = class {
this._lockDialogGroup = new St.Widget({ x_expand: true, this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true, y_expand: true,
reactive: true, reactive: true,
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }), pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }),
name: 'lockDialogGroup' }); name: 'lockDialogGroup' });
this.actor.add_actor(this._lockDialogGroup); this.actor.add_actor(this._lockDialogGroup);
@ -557,11 +563,11 @@ var ScreenShield = class {
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup, this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true, { inhibitEvents: true,
fadeFactor: 1 }); fadeFactor: 1 });
this._longLightbox.connect('shown', this._onLongLightboxShown.bind(this)); this._longLightbox.connect('notify::active', this._onLongLightbox.bind(this));
this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup, this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true, { inhibitEvents: true,
fadeFactor: 1 }); fadeFactor: 1 });
this._shortLightbox.connect('shown', this._onShortLightboxShown.bind(this)); this._shortLightbox.connect('notify::active', this._onShortLightbox.bind(this));
this.idleMonitor = Meta.IdleMonitor.get_core(); this.idleMonitor = Meta.IdleMonitor.get_core();
this._cursorTracker = Meta.CursorTracker.get_for_display(global.display); this._cursorTracker = Meta.CursorTracker.get_for_display(global.display);
@ -807,7 +813,7 @@ var ScreenShield = class {
this._maybeCancelDialog(); this._maybeCancelDialog();
if (this._longLightbox.actor.visible) { if (this._longLightbox.visible) {
// We're in the process of showing. // We're in the process of showing.
return; return;
} }
@ -832,7 +838,7 @@ var ScreenShield = class {
if (shouldLock) { if (shouldLock) {
let lockTimeout = Math.max( let lockTimeout = Math.max(
STANDARD_FADE_TIME, adjustAnimationTime(STANDARD_FADE_TIME),
this._settings.get_uint(LOCK_DELAY_KEY) * 1000); this._settings.get_uint(LOCK_DELAY_KEY) * 1000);
this._lockTimeoutId = GLib.timeout_add( this._lockTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, GLib.PRIORITY_DEFAULT,
@ -849,8 +855,8 @@ var ScreenShield = class {
} }
_activateFade(lightbox, time) { _activateFade(lightbox, time) {
Main.uiGroup.set_child_above_sibling(lightbox.actor, null); Main.uiGroup.set_child_above_sibling(lightbox, null);
lightbox.show(time); lightbox.lightOn(time);
if (this._becameActiveId == 0) if (this._becameActiveId == 0)
this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this)); this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this));
@ -879,18 +885,20 @@ var ScreenShield = class {
this._becameActiveId = 0; this._becameActiveId = 0;
if (this._isActive || this._isLocked) { if (this._isActive || this._isLocked) {
this._longLightbox.hide(); this._longLightbox.lightOff();
this._shortLightbox.hide(); this._shortLightbox.lightOff();
} else { } else {
this.deactivate(false); this.deactivate(false);
} }
} }
_onLongLightboxShown() { _onLongLightbox(lightBox) {
if (lightBox.active)
this.activate(false); this.activate(false);
} }
_onShortLightboxShown() { _onShortLightbox(lightBox) {
if (lightBox.active)
this._completeLockScreenShown(); this._completeLockScreenShown();
} }
@ -965,7 +973,6 @@ var ScreenShield = class {
this._dialog = new constructor(this._lockDialogGroup); this._dialog = new constructor(this._lockDialogGroup);
let time = global.get_current_time(); let time = global.get_current_time();
if (!this._dialog.open(time, onPrimary)) { if (!this._dialog.open(time, onPrimary)) {
// This is kind of an impossible error: we're already modal // This is kind of an impossible error: we're already modal
@ -1131,16 +1138,20 @@ var ScreenShield = class {
vertical: true, vertical: true,
style_class: 'screen-shield-contents-box' }); style_class: 'screen-shield-contents-box' });
this._clock = new Clock(); this._clock = new Clock();
this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true, this._lockScreenContentsBox.add(this._clock, {
y_fill: true }); x_fill: true,
y_fill: true
});
this._lockScreenContents.add_actor(this._lockScreenContentsBox); this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._notificationsBox = new NotificationsBox(); this._notificationsBox = new NotificationsBox();
this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this)); this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true, this._lockScreenContentsBox.add(this._notificationsBox, {
x_fill: true,
y_fill: true, y_fill: true,
expand: true }); expand: true
});
this._hasLockScreen = true; this._hasLockScreen = true;
} }
@ -1233,8 +1244,8 @@ var ScreenShield = class {
this._dialog = null; this._dialog = null;
} }
this._longLightbox.hide(); this._longLightbox.lightOff();
this._shortLightbox.hide(); this._shortLightbox.lightOff();
this.actor.hide(); this.actor.hide();
if (this._becameActiveId != 0) { if (this._becameActiveId != 0) {

View File

@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ScreenshotService */ /* exported ScreenshotService */
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi; const { Clutter, Graphene, Gio, GObject, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const GrabHelper = imports.ui.grabHelper; const GrabHelper = imports.ui.grabHelper;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
@ -198,7 +197,7 @@ var ScreenshotService = class {
let screenshot = this._createScreenshot(invocation, false); let screenshot = this._createScreenshot(invocation, false);
if (!screenshot) if (!screenshot)
return; return;
screenshot.pick_color(...coords, (o, res) => { screenshot.pick_color(coords.x, coords.y, (_o, res) => {
let [success_, color] = screenshot.pick_color_finish(res); let [success_, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color; let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{ let retval = GLib.Variant.new('(a{sv})', [{
@ -219,62 +218,62 @@ var ScreenshotService = class {
} }
}; };
var SelectArea = class { var SelectArea = GObject.registerClass({
constructor() { GTypeName: 'Screenshot_SelectArea',
Signals: { 'finished': { param_types: [Meta.Rectangle.$gtype] } }
}, class SelectArea extends St.Widget {
_init() {
this._startX = -1; this._startX = -1;
this._startY = -1; this._startY = -1;
this._lastX = 0; this._lastX = 0;
this._lastY = 0; this._lastY = 0;
this._result = null; this._result = null;
this._group = new St.Widget({ visible: false, super._init({
visible: false,
reactive: true, reactive: true,
x: 0, x: 0,
y: 0 }); y: 0
Main.uiGroup.add_actor(this._group); });
Main.uiGroup.add_actor(this);
this._grabHelper = new GrabHelper.GrabHelper(this._group); this._grabHelper = new GrabHelper.GrabHelper(this);
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, let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL }); coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint); this.add_constraint(constraint);
this._rubberband = new St.Widget({ this._rubberband = new St.Widget({
style_class: 'select-area-rubberband', style_class: 'select-area-rubberband',
visible: false visible: false
}); });
this._group.add_actor(this._rubberband); this.add_actor(this._rubberband);
} }
show() { vfunc_show() {
if (!this._grabHelper.grab({ actor: this._group, if (!this._grabHelper.grab({ actor: this,
onUngrab: this._onUngrab.bind(this) })) onUngrab: this._onUngrab.bind(this) }))
return; return;
global.display.set_cursor(Meta.Cursor.CROSSHAIR); global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this._group, null); Main.uiGroup.set_child_above_sibling(this, null);
this._group.visible = true; super.vfunc_show();
} }
_getGeometry() { _getGeometry() {
return { x: Math.min(this._startX, this._lastX), return new Meta.Rectangle({
x: Math.min(this._startX, this._lastX),
y: Math.min(this._startY, this._lastY), y: Math.min(this._startY, this._lastY),
width: Math.abs(this._startX - this._lastX) + 1, width: Math.abs(this._startX - this._lastX) + 1,
height: Math.abs(this._startY - this._lastY) + 1 }; height: Math.abs(this._startY - this._lastY) + 1
});
} }
_onMotionEvent(actor, event) { vfunc_motion_event(motionEvent) {
if (this._startX == -1 || this._startY == -1 || this._result) if (this._startX == -1 || this._startY == -1 || this._result)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
[this._lastX, this._lastY] = event.get_coords(); [this._lastX, this._lastY] = [motionEvent.x, motionEvent.y];
this._lastX = Math.floor(this._lastX); this._lastX = Math.floor(this._lastX);
this._lastY = Math.floor(this._lastY); this._lastY = Math.floor(this._lastY);
let geometry = this._getGeometry(); let geometry = this._getGeometry();
@ -286,8 +285,8 @@ var SelectArea = class {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onButtonPress(actor, event) { vfunc_button_press_event(buttonEvent) {
[this._startX, this._startY] = event.get_coords(); [this._startX, this._startY] = [buttonEvent.x, buttonEvent.y];
this._startX = Math.floor(this._startX); this._startX = Math.floor(this._startX);
this._startY = Math.floor(this._startY); this._startY = Math.floor(this._startY);
this._rubberband.set_position(this._startX, this._startY); this._rubberband.set_position(this._startX, this._startY);
@ -295,9 +294,9 @@ var SelectArea = class {
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
_onButtonRelease() { vfunc_button_release_event() {
this._result = this._getGeometry(); this._result = this._getGeometry();
this._group.ease({ this.ease({
opacity: 0, opacity: 0,
duration: 200, duration: 200,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -311,43 +310,43 @@ var SelectArea = class {
this.emit('finished', this._result); this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._group.destroy(); this.destroy();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
} }
}; });
Signals.addSignalMethods(SelectArea.prototype);
var PickPixel = GObject.registerClass({
GTypeName: 'Screenshot_PickPixel',
Signals: { 'finished': { param_types: [Graphene.Point.$gtype] } }
}, class PickPixel extends St.Widget {
_init() {
super._init({ visible: false, reactive: true });
var PickPixel = class {
constructor() {
this._result = null; this._result = null;
this._group = new St.Widget({ visible: false, Main.uiGroup.add_actor(this);
reactive: true });
Main.uiGroup.add_actor(this._group);
this._grabHelper = new GrabHelper.GrabHelper(this._group); this._grabHelper = new GrabHelper.GrabHelper(this);
this._group.connect('button-release-event',
this._onButtonRelease.bind(this));
let constraint = new Clutter.BindConstraint({ source: global.stage, let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL }); coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint); this.add_constraint(constraint);
} }
show() { vfunc_show() {
if (!this._grabHelper.grab({ actor: this._group, if (!this._grabHelper.grab({ actor: this,
onUngrab: this._onUngrab.bind(this) })) onUngrab: this._onUngrab.bind(this) }))
return; return;
global.display.set_cursor(Meta.Cursor.CROSSHAIR); global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this._group, null); Main.uiGroup.set_child_above_sibling(this, null);
this._group.visible = true; super.vfunc_show();
} }
_onButtonRelease(actor, event) { vfunc_button_release_event(buttonEvent) {
this._result = event.get_coords(); let { x, y } = buttonEvent;
this._result = new Graphene.Point({ x, y });
this._grabHelper.ungrab(); this._grabHelper.ungrab();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
@ -357,29 +356,29 @@ var PickPixel = class {
this.emit('finished', this._result); this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._group.destroy(); this.destroy();
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
} }
}; });
Signals.addSignalMethods(PickPixel.prototype);
var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds var FLASHSPOT_ANIMATION_OUT_TIME = 500; // milliseconds
var Flashspot = class extends Lightbox.Lightbox { var Flashspot = GObject.registerClass(
constructor(area) { class Flashspot extends Lightbox.Lightbox {
super(Main.uiGroup, { inhibitEvents: true, _init(area) {
super._init(Main.uiGroup, {
inhibitEvents: true,
width: area.width, width: area.width,
height: area.height }); height: area.height
});
this.actor.style_class = 'flashspot'; this.style_class = 'flashspot';
this.actor.set_position(area.x, area.y); this.set_position(area.x, area.y);
} }
fire(doneCallback) { fire(doneCallback) {
this.actor.show(); this.set({ visible: true, opacity: 255 });
this.actor.opacity = 255; this.ease({
this.actor.ease({
opacity: 0, opacity: 0,
duration: FLASHSPOT_ANIMATION_OUT_TIME, duration: FLASHSPOT_ANIMATION_OUT_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -390,4 +389,4 @@ var Flashspot = class extends Lightbox.Lightbox {
} }
}); });
} }
}; });

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported SearchResultsView */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
@ -32,39 +32,47 @@ class MaxWidthBox extends St.BoxLayout {
} }
}); });
var SearchResult = class { var SearchResult = GObject.registerClass(
constructor(provider, metaInfo, resultsView) { class SearchResult extends St.Button {
_init(provider, metaInfo, resultsView) {
this.provider = provider; this.provider = provider;
this.metaInfo = metaInfo; this.metaInfo = metaInfo;
this._resultsView = resultsView; this._resultsView = resultsView;
this.actor = new St.Button({ reactive: true, super._init({
reactive: true,
can_focus: true, can_focus: true,
track_hover: true, track_hover: true,
x_align: St.Align.START, x_align: St.Align.START,
y_fill: true }); y_fill: true
});
}
this.actor._delegate = this; vfunc_clicked() {
this.actor.connect('clicked', this.activate.bind(this)); this.activate();
} }
activate() { activate() {
this.emit('activate', this.metaInfo.id); 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();
} }
}; });
Signals.addSignalMethods(SearchResult.prototype);
var ListSearchResult = class extends SearchResult { var ListSearchResult = GObject.registerClass(
class ListSearchResult extends SearchResult {
_init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
constructor(provider, metaInfo, resultsView) { this.style_class = 'list-search-result';
super(provider, metaInfo, resultsView); this.x_fill = true;
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content', let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false }); vertical: false });
this.actor.set_child(content); this.set_child(content);
this._termsChangedId = 0; this._termsChangedId = 0;
@ -87,7 +95,7 @@ var ListSearchResult = class extends SearchResult {
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE });
this.actor.label_actor = title; this.label_actor = title;
if (this.metaInfo['description']) { if (this.metaInfo['description']) {
this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' }); this._descriptionLabel = new St.Label({ style_class: 'list-search-result-description' });
@ -103,7 +111,7 @@ var ListSearchResult = class extends SearchResult {
this._highlightTerms(); this._highlightTerms();
} }
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} }
get ICON_SIZE() { get ICON_SIZE() {
@ -120,50 +128,53 @@ var ListSearchResult = class extends SearchResult {
this._resultsView.disconnect(this._termsChangedId); this._resultsView.disconnect(this._termsChangedId);
this._termsChangedId = 0; this._termsChangedId = 0;
} }
}; });
var GridSearchResult = class extends SearchResult { var GridSearchResult = GObject.registerClass(
constructor(provider, metaInfo, resultsView) { class GridSearchResult extends SearchResult {
super(provider, metaInfo, resultsView); _init(provider, metaInfo, resultsView) {
super._init(provider, metaInfo, resultsView);
this.actor.style_class = 'grid-search-result'; this.style_class = 'grid-search-result';
this.icon = new IconGrid.BaseIcon(this.metaInfo['name'], this.icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] }); { createIcon: this.metaInfo['createIcon'] });
let content = new St.Bin({ child: this.icon }); let content = new St.Bin({ child: this.icon });
this.actor.set_child(content); this.set_child(content);
this.actor.label_actor = this.icon.label; this.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.provider = provider;
this._resultsView = resultsView; this._resultsView = resultsView;
this._terms = []; this._terms = [];
this._focusChild = null;
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true, this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true }); y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true }); this.add(this._resultDisplayBin, { expand: true });
let separator = new St.Widget({ style_class: 'search-section-separator' }); let separator = new St.Widget({ style_class: 'search-section-separator' });
this.actor.add(separator); this.add(separator);
this._resultDisplays = {}; this._resultDisplays = {};
this._clipboard = St.Clipboard.get_default();
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
this.actor.destroy();
} }
_onDestroy() { _onDestroy() {
@ -180,21 +191,21 @@ var SearchResultsBase = class {
clear() { clear() {
this._cancellable.cancel(); this._cancellable.cancel();
for (let resultId in this._resultDisplays) for (let resultId in this._resultDisplays)
this._resultDisplays[resultId].actor.destroy(); this._resultDisplays[resultId].destroy();
this._resultDisplays = {}; this._resultDisplays = {};
this._clearResultDisplay(); this._clearResultDisplay();
this.actor.hide(); this.hide();
}
get focusChild() {
return this._focusChild;
} }
_keyFocusIn(actor) { _keyFocusIn(actor) {
this.emit('key-focus-in', actor); if (this._focusChild == actor)
} return;
this._focusChild = actor;
_activateResult(result, id) { this.notify('focus-child');
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) { _setMoreCount(_count) {
@ -233,8 +244,7 @@ var SearchResultsBase = class {
metasNeeded.forEach((resultId, i) => { metasNeeded.forEach((resultId, i) => {
let meta = metas[i]; let meta = metas[i];
let display = this._createResultDisplay(meta); let display = this._createResultDisplay(meta);
display.connect('activate', this._activateResult.bind(this)); display.connect('key-focus-in', this._keyFocusIn.bind(this));
display.actor.connect('key-focus-in', this._keyFocusIn.bind(this));
this._resultDisplays[resultId] = display; this._resultDisplays[resultId] = display;
}); });
callback(true); callback(true);
@ -246,7 +256,7 @@ var SearchResultsBase = class {
this._terms = terms; this._terms = terms;
if (providerResults.length == 0) { if (providerResults.length == 0) {
this._clearResultDisplay(); this._clearResultDisplay();
this.actor.hide(); this.hide();
callback(); callback();
} else { } else {
let maxResults = this._getMaxDisplayedResults(); let maxResults = this._getMaxDisplayedResults();
@ -265,22 +275,23 @@ var SearchResultsBase = class {
// To avoid CSS transitions causing flickering when // To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the // the first search result stays the same, we hide the
// content while filling in the results. // content while filling in the results.
this.actor.hide(); this.hide();
this._clearResultDisplay(); this._clearResultDisplay();
results.forEach(resultId => { results.forEach(resultId => {
this._addItem(this._resultDisplays[resultId]); this._addItem(this._resultDisplays[resultId]);
}); });
this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0); this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
this.actor.show(); this.show();
callback(); callback();
}); });
} }
} }
}; });
var ListSearchResults = class extends SearchResultsBase { var ListSearchResults = GObject.registerClass(
constructor(provider, resultsView) { class ListSearchResults extends SearchResultsBase {
super(provider, resultsView); _init(provider, resultsView) {
super._init(provider, resultsView);
this._container = new St.BoxLayout({ style_class: 'search-section-content' }); this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerInfo = new ProviderInfo(provider); this.providerInfo = new ProviderInfo(provider);
@ -321,21 +332,21 @@ var ListSearchResults = class extends SearchResultsBase {
} }
_addItem(display) { _addItem(display) {
this._content.add_actor(display.actor); this._content.add_actor(display);
} }
getFirstResult() { getFirstResult() {
if (this._content.get_n_children() > 0) if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate; return this._content.get_child_at_index(0);
else else
return null; return null;
} }
}; });
Signals.addSignalMethods(ListSearchResults.prototype);
var GridSearchResults = class extends SearchResultsBase { var GridSearchResults = GObject.registerClass(
constructor(provider, resultsView) { class GridSearchResults extends SearchResultsBase {
super(provider, resultsView); _init(provider, resultsView) {
super._init(provider, resultsView);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS, this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START }); xAlign: St.Align.START });
@ -357,7 +368,7 @@ var GridSearchResults = class extends SearchResultsBase {
updateSearch(...args) { updateSearch(...args) {
if (this._notifyAllocationId) if (this._notifyAllocationId)
this.actor.disconnect(this._notifyAllocationId); this.disconnect(this._notifyAllocationId);
if (this._updateSearchLater) { if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater); Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater; delete this._updateSearchLater;
@ -365,7 +376,7 @@ var GridSearchResults = class extends SearchResultsBase {
// Make sure the maximum number of results calculated by // Make sure the maximum number of results calculated by
// _getMaxDisplayedResults() is updated after width changes. // _getMaxDisplayedResults() is updated after width changes.
this._notifyAllocationId = this.actor.connect('notify::allocation', () => { this._notifyAllocationId = this.connect('notify::allocation', () => {
if (this._updateSearchLater) if (this._updateSearchLater)
return; return;
this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
@ -379,7 +390,7 @@ var GridSearchResults = class extends SearchResultsBase {
} }
_getMaxDisplayedResults() { _getMaxDisplayedResults() {
let width = this.actor.allocation.x2 - this.actor.allocation.x1; let width = this.allocation.get_width();
if (width == 0) if (width == 0)
return -1; return -1;
@ -402,17 +413,17 @@ var GridSearchResults = class extends SearchResultsBase {
getFirstResult() { getFirstResult() {
if (this._grid.visibleItemsCount() > 0) if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate; return this._grid.getItemAtIndex(0);
else else
return null; return null;
} }
}; });
Signals.addSignalMethods(GridSearchResults.prototype);
var SearchResults = class { var SearchResultsView = GObject.registerClass({
constructor() { Signals: { 'terms-changed': {} }
this.actor = new St.BoxLayout({ name: 'searchResults', }, class SearchResultsView extends St.BoxLayout {
vertical: true }); _init() {
super._init({ name: 'searchResults', vertical: true });
this._content = new MaxWidthBox({ name: 'searchResultsContent', this._content = new MaxWidthBox({ name: 'searchResultsContent',
vertical: true }); vertical: true });
@ -428,16 +439,18 @@ var SearchResults = class {
action.connect('pan', this._onPan.bind(this)); action.connect('pan', this._onPan.bind(this));
this._scrollView.add_action(action); this._scrollView.add_action(action);
this.actor.add(this._scrollView, { x_fill: true, this.add(this._scrollView, {
x_fill: true,
y_fill: true, y_fill: true,
expand: true, expand: true,
x_align: St.Align.START, x_align: St.Align.START,
y_align: St.Align.START }); y_align: St.Align.STAR
});
this._statusText = new St.Label({ style_class: 'search-statustext' }); this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE, this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE }); y_align: St.Align.MIDDLE });
this.actor.add(this._statusBin, { expand: true }); this.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText); this._statusBin.add_actor(this._statusText);
this._highlightDefault = false; this._highlightDefault = false;
@ -467,6 +480,10 @@ var SearchResults = class {
this._reloadRemoteProviders(); this._reloadRemoteProviders();
} }
get terms() {
return this._terms;
}
_reloadRemoteProviders() { _reloadRemoteProviders() {
let remoteProviders = this._providers.filter(p => p.isRemoteProvider); let remoteProviders = this._providers.filter(p => p.isRemoteProvider);
remoteProviders.forEach(provider => { remoteProviders.forEach(provider => {
@ -591,12 +608,12 @@ var SearchResults = class {
_onPan(action) { _onPan(action) {
let [dist_, dx_, dy] = action.get_motion_delta(0); let [dist_, dx_, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment; let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size; adjustment.value -= (dy / this.height) * adjustment.page_size;
return false; return false;
} }
_keyFocusIn(provider, actor) { _focusChildChanged(provider) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor); Util.ensureActorVisibleInScrollView(this._scrollView, provider.focusChild);
} }
_ensureProviderDisplay(provider) { _ensureProviderDisplay(provider) {
@ -609,9 +626,9 @@ var SearchResults = class {
else else
providerDisplay = new GridSearchResults(provider, this); providerDisplay = new GridSearchResults(provider, this);
providerDisplay.connect('key-focus-in', this._keyFocusIn.bind(this)); providerDisplay.connect('notify::focus-child', this._focusChildChanged.bind(this));
providerDisplay.actor.hide(); providerDisplay.hide();
this._content.add(providerDisplay.actor); this._content.add(providerDisplay);
provider.display = providerDisplay; provider.display = providerDisplay;
} }
@ -629,7 +646,7 @@ var SearchResults = class {
let provider = providers[i]; let provider = providers[i];
let display = provider.display; let display = provider.display;
if (!display.actor.visible) if (!display.visible)
continue; continue;
let firstResult = display.getFirstResult(); let firstResult = display.getFirstResult();
@ -704,22 +721,22 @@ var SearchResults = class {
this._doSearch(); this._doSearch();
if (this._defaultResult) if (this._defaultResult)
this._defaultResult.actor.popup_menu(); this._defaultResult.popup_menu();
} }
navigateFocus(direction) { navigateFocus(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL; let rtl = this.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == St.DirectionType.TAB_BACKWARD || if (direction == St.DirectionType.TAB_BACKWARD ||
direction == (rtl direction == (rtl
? St.DirectionType.RIGHT ? St.DirectionType.RIGHT
: St.DirectionType.LEFT) || : St.DirectionType.LEFT) ||
direction == St.DirectionType.UP) { direction == St.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false); this.navigate_focus(null, direction, false);
return; return;
} }
let from = this._defaultResult ? this._defaultResult.actor : null; let from = this._defaultResult ? this._defaultResult : null;
this.actor.navigate_focus(from, direction, false); this.navigate_focus(from, direction, false);
} }
_setSelected(result, selected) { _setSelected(result, selected) {
@ -727,10 +744,10 @@ var SearchResults = class {
return; return;
if (selected) { if (selected) {
result.actor.add_style_pseudo_class('selected'); result.add_style_pseudo_class('selected');
Util.ensureActorVisibleInScrollView(this._scrollView, result.actor); Util.ensureActorVisibleInScrollView(this._scrollView, result);
} else { } else {
result.actor.remove_style_pseudo_class('selected'); result.remove_style_pseudo_class('selected');
} }
} }
@ -743,8 +760,7 @@ var SearchResults = class {
return description.replace(this._highlightRegex, '<b>$1</b>'); return description.replace(this._highlightRegex, '<b>$1</b>');
} }
}; });
Signals.addSignalMethods(SearchResults.prototype);
var ProviderInfo = GObject.registerClass( var ProviderInfo = GObject.registerClass(
class ProviderInfo extends St.Button { class ProviderInfo extends St.Button {

View File

@ -2,7 +2,6 @@
/* exported ShellMountOperation, GnomeShellMountOpHandler */ /* exported ShellMountOperation, GnomeShellMountOpHandler */
const { Clutter, Gio, GLib, GObject, Pango, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const CheckBox = imports.ui.checkBox; const CheckBox = imports.ui.checkBox;
@ -44,18 +43,22 @@ function _setLabelsForMessage(content, message) {
/* -------------------------------------------------------- */ /* -------------------------------------------------------- */
var ListItem = class { var ListItem = GObject.registerClass({
constructor(app) { GTypeName: 'ShellMountOperation_ListItem',
this._app = app; Signals: { 'activate': {} }
}, class ListItem extends St.Button {
_init(app) {
let layout = new St.BoxLayout({ vertical: false }); let layout = new St.BoxLayout({ vertical: false });
super._init({
this.actor = new St.Button({ style_class: 'mount-dialog-app-list-item', style_class: 'mount-dialog-app-list-item',
can_focus: true, can_focus: true,
child: layout, child: layout,
reactive: true, reactive: true,
x_align: St.Align.START, x_align: St.Align.START,
x_fill: true }); x_fill: true
});
this._app = app;
this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE); this._icon = this._app.create_icon_texture(LIST_ITEM_ICON_SIZE);
@ -68,16 +71,13 @@ var ListItem = class {
let labelBin = new St.Bin({ y_align: St.Align.MIDDLE, let labelBin = new St.Bin({ y_align: St.Align.MIDDLE,
child: this._nameLabel }); child: this._nameLabel });
layout.add(labelBin); layout.add(labelBin);
this.actor.connect('clicked', this._onClicked.bind(this));
} }
_onClicked() { vfunc_clicked() {
this.emit('activate'); this.emit('activate');
this._app.activate(); this._app.activate();
} }
}; });
Signals.addSignalMethods(ListItem.prototype);
var ShellMountOperation = class { var ShellMountOperation = class {
constructor(source, params) { constructor(source, params) {
@ -219,9 +219,10 @@ var ShellMountOperation = class {
} }
}; };
var ShellUnmountNotifier = class extends MessageTray.Source { var ShellUnmountNotifier = GObject.registerClass(
constructor() { class ShellUnmountNotifier extends MessageTray.Source {
super('', 'media-removable'); _init() {
super._init('', 'media-removable');
this._notification = null; this._notification = null;
Main.messageTray.add(this); Main.messageTray.add(this);
@ -238,7 +239,7 @@ var ShellUnmountNotifier = class extends MessageTray.Source {
this._notification.update(header, text); this._notification.update(header, text);
} }
this.notify(this._notification); this.showNotification(this._notification);
} }
done(message) { done(message) {
@ -251,10 +252,10 @@ var ShellUnmountNotifier = class extends MessageTray.Source {
let notification = new MessageTray.Notification(this, message, null); let notification = new MessageTray.Notification(this, message, null);
notification.setTransient(true); notification.setTransient(true);
this.notify(notification); this.showNotification(notification);
} }
} }
}; });
var ShellMountQuestionDialog = GObject.registerClass({ var ShellMountQuestionDialog = GObject.registerClass({
Signals: { 'response': { param_types: [GObject.TYPE_INT] } } Signals: { 'response': { param_types: [GObject.TYPE_INT] } }
@ -303,14 +304,14 @@ var ShellMountPasswordDialog = GObject.registerClass({
visible: false })); visible: false }));
this._hiddenVolume = new CheckBox.CheckBox(_("Hidden Volume")); this._hiddenVolume = new CheckBox.CheckBox(_("Hidden Volume"));
content.messageBox.add(this._hiddenVolume.actor); content.messageBox.add(this._hiddenVolume);
this._systemVolume = new CheckBox.CheckBox(_("Windows System Volume")); this._systemVolume = new CheckBox.CheckBox(_("Windows System Volume"));
content.messageBox.add(this._systemVolume.actor); content.messageBox.add(this._systemVolume);
this._keyfilesCheckbox = new CheckBox.CheckBox(_("Uses Keyfiles")); this._keyfilesCheckbox = new CheckBox.CheckBox(_("Uses Keyfiles"));
this._keyfilesCheckbox.actor.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this)); this._keyfilesCheckbox.connect("clicked", this._onKeyfilesCheckboxClicked.bind(this));
content.messageBox.add(this._keyfilesCheckbox.actor); content.messageBox.add(this._keyfilesCheckbox);
this._keyfilesLabel.clutter_text.set_markup( this._keyfilesLabel.clutter_text.set_markup(
/* Translators: %s is the Disks application */ /* Translators: %s is the Disks application */
@ -360,7 +361,7 @@ var ShellMountPasswordDialog = GObject.registerClass({
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this.setInitialKeyFocus(this._passwordEntry); this.setInitialKeyFocus(this._passwordEntry);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true); this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._passwordEntry.secondary_icon = this._workSpinner.actor; this._passwordEntry.secondary_icon = this._workSpinner;
if (rtl) { if (rtl) {
layout.attach(this._passwordEntry, 0, 1, 1, 1); layout.attach(this._passwordEntry, 0, 1, 1, 1);
@ -381,9 +382,9 @@ var ShellMountPasswordDialog = GObject.registerClass({
if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) { if (flags & Gio.AskPasswordFlags.SAVING_SUPPORTED) {
this._rememberChoice = new CheckBox.CheckBox(_("Remember Password")); this._rememberChoice = new CheckBox.CheckBox(_("Remember Password"));
this._rememberChoice.actor.checked = this._rememberChoice.checked =
global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY); global.settings.get_boolean(REMEMBER_MOUNT_PASSWORD_KEY);
content.messageBox.add(this._rememberChoice.actor); content.messageBox.add(this._rememberChoice);
} else { } else {
this._rememberChoice = null; this._rememberChoice = null;
} }
@ -439,22 +440,22 @@ var ShellMountPasswordDialog = GObject.registerClass({
} }
global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY, global.settings.set_boolean(REMEMBER_MOUNT_PASSWORD_KEY,
this._rememberChoice && this._rememberChoice.actor.checked); this._rememberChoice && this._rememberChoice.checked);
this._workSpinner.play(); this._workSpinner.play();
this.emit('response', 1, this.emit('response', 1,
this._passwordEntry.get_text(), this._passwordEntry.get_text(),
this._rememberChoice && this._rememberChoice &&
this._rememberChoice.actor.checked, this._rememberChoice.checked,
this._hiddenVolume && this._hiddenVolume &&
this._hiddenVolume.actor.checked, this._hiddenVolume.checked,
this._systemVolume && this._systemVolume &&
this._systemVolume.actor.checked, this._systemVolume.checked,
parseInt(pim)); parseInt(pim));
} }
_onKeyfilesCheckboxClicked() { _onKeyfilesCheckboxClicked() {
let useKeyfiles = this._keyfilesCheckbox.actor.checked; let useKeyfiles = this._keyfilesCheckbox.checked;
this._passwordEntry.reactive = !useKeyfiles; this._passwordEntry.reactive = !useKeyfiles;
this._passwordEntry.can_focus = !useKeyfiles; this._passwordEntry.can_focus = !useKeyfiles;
this._passwordEntry.clutter_text.editable = !useKeyfiles; this._passwordEntry.clutter_text.editable = !useKeyfiles;
@ -463,8 +464,8 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._pimEntry.can_focus = !useKeyfiles; this._pimEntry.can_focus = !useKeyfiles;
this._pimEntry.clutter_text.editable = !useKeyfiles; this._pimEntry.clutter_text.editable = !useKeyfiles;
this._pimEntry.clutter_text.selectable = !useKeyfiles; this._pimEntry.clutter_text.selectable = !useKeyfiles;
this._rememberChoice.actor.reactive = !useKeyfiles; this._rememberChoice.reactive = !useKeyfiles;
this._rememberChoice.actor.can_focus = !useKeyfiles; this._rememberChoice.can_focus = !useKeyfiles;
this._keyfilesLabel.visible = useKeyfiles; this._keyfilesLabel.visible = useKeyfiles;
this.setButtons(useKeyfiles ? this._usesKeyfilesButtons : this._defaultButtons); this.setButtons(useKeyfiles ? this._usesKeyfilesButtons : this._defaultButtons);
} }
@ -527,7 +528,7 @@ var ShellProcessesDialog = GObject.registerClass({
return; return;
let item = new ListItem(app); let item = new ListItem(app);
this._applicationList.add(item.actor, { x_fill: true }); this._applicationList.add(item, { x_fill: true });
item.connect('activate', () => { item.connect('activate', () => {
// use -1 to indicate Cancel // use -1 to indicate Cancel

View File

@ -22,12 +22,7 @@ var Slider = GObject.registerClass({
accessible_role: Atk.Role.SLIDER accessible_role: Atk.Role.SLIDER
}); });
this.connect('button-press-event', this._startDragging.bind(this)); this._releaseId = 0;
this.connect('touch-event', this._touchDragging.bind(this));
this.connect('scroll-event', this._onScrollEvent.bind(this));
this.connect('key-press-event', this.onKeyPressEvent.bind(this));
this._releaseId = this._motionId = 0;
this._dragging = false; this._dragging = false;
this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this)); this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this));
@ -62,8 +57,8 @@ var Slider = GObject.registerClass({
cr.$dispose(); cr.$dispose();
} }
_startDragging(actor, event) { vfunc_button_press_event() {
return this.startDragging(event); return this.startDragging(Clutter.get_current_event());
} }
startDragging(event) { startDragging(event) {
@ -83,11 +78,6 @@ var Slider = GObject.registerClass({
this._grabbedDevice = device; this._grabbedDevice = device;
this._grabbedSequence = sequence; this._grabbedSequence = sequence;
if (sequence == null) {
this._releaseId = this.connect('button-release-event', this._endDragging.bind(this));
this._motionId = this.connect('motion-event', this._motionEvent.bind(this));
}
// We need to emit 'drag-begin' before moving the handle to make // We need to emit 'drag-begin' before moving the handle to make
// sure that no 'notify::value' signal is emitted before this one. // sure that no 'notify::value' signal is emitted before this one.
this.emit('drag-begin'); this.emit('drag-begin');
@ -105,11 +95,6 @@ var Slider = GObject.registerClass({
this._releaseId = 0; this._releaseId = 0;
} }
if (this._motionId) {
this.disconnect(this._motionId);
this._motionId = 0;
}
if (this._grabbedSequence != null) if (this._grabbedSequence != null)
this._grabbedDevice.sequence_ungrab(this._grabbedSequence); this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
else else
@ -124,7 +109,15 @@ var Slider = GObject.registerClass({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_touchDragging(actor, event) { vfunc_button_release_event() {
if (this._dragging && !this._grabbedSequence)
return this._endDragging();
return Clutter.EVENT_PROPAGATE;
}
vfunc_touch_event() {
let event = Clutter.get_current_event();
let device = event.get_device(); let device = event.get_device();
let sequence = event.get_event_sequence(); let sequence = event.get_event_sequence();
@ -132,9 +125,9 @@ var Slider = GObject.registerClass({
event.type() == Clutter.EventType.TOUCH_BEGIN) { event.type() == Clutter.EventType.TOUCH_BEGIN) {
this.startDragging(event); this.startDragging(event);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} else if (device.sequence_get_grabbed_actor(sequence) == actor) { } else if (device.sequence_get_grabbed_actor(sequence) == this) {
if (event.type() == Clutter.EventType.TOUCH_UPDATE) if (event.type() == Clutter.EventType.TOUCH_UPDATE)
return this._motionEvent(actor, event); return this._motionEvent(this, event);
else if (event.type() == Clutter.EventType.TOUCH_END) else if (event.type() == Clutter.EventType.TOUCH_END)
return this._endDragging(); return this._endDragging();
} }
@ -165,8 +158,15 @@ var Slider = GObject.registerClass({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_onScrollEvent(actor, event) { vfunc_scroll_event() {
return this.scroll(event); return this.scroll(Clutter.get_current_event());
}
vfunc_motion_event() {
if (this._dragging && !this._grabbedSequence)
return this._motionEvent(this, Clutter.get_current_event());
return Clutter.EVENT_PROPAGATE;
} }
_motionEvent(actor, event) { _motionEvent(actor, event) {
@ -176,8 +176,8 @@ var Slider = GObject.registerClass({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
onKeyPressEvent(actor, event) { vfunc_key_press_event(keyPressEvent) {
let key = event.get_key_symbol(); let key = keyPressEvent.keyval;
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) { if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1; let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
this.emit('drag-begin'); this.emit('drag-begin');

View File

@ -102,7 +102,7 @@ class ATIndicator extends PanelMenu.Button {
_buildItemExtended(string, initialValue, writable, onSet) { _buildItemExtended(string, initialValue, writable, onSet) {
let widget = new PopupMenu.PopupSwitchMenuItem(string, initialValue); let widget = new PopupMenu.PopupSwitchMenuItem(string, initialValue);
if (!writable) if (!writable)
widget.actor.reactive = false; widget.reactive = false;
else else
widget.connect('toggled', item => { widget.connect('toggled', item => {
onSet(item.state); onSet(item.state);

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */ /* exported Indicator */
const { Gio, GnomeBluetooth } = imports.gi; const { Gio, GnomeBluetooth, GObject } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
@ -17,9 +17,11 @@ const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface
const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup'; const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup';
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Bluetooth_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._indicator.icon_name = 'bluetooth-active-symbolic'; this._indicator.icon_name = 'bluetooth-active-symbolic';
@ -133,4 +135,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off"); this._toggleItem.label.text = this._proxy.BluetoothAirplaneMode ? _("Turn On") : _("Turn Off");
} }
}; });

View File

@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen'); const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen');
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface); const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Brightness_Indicator'
super('display-brightness-symbolic'); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
(proxy, error) => { (proxy, error) => {
if (error) { if (error) {
@ -45,7 +47,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
return this._slider.startDragging(event); return this._slider.startDragging(event);
}); });
this._item.connect('key-press-event', (actor, event) => { this._item.connect('key-press-event', (actor, event) => {
return this._slider.onKeyPressEvent(actor, event); return this._slider.emit('key-press-event', event);
}); });
} }
@ -67,4 +69,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
if (visible) if (visible)
this._changeSlider(this._proxy.Brightness / 100.0); this._changeSlider(this._proxy.Brightness / 100.0);
} }
}; });

View File

@ -923,7 +923,7 @@ class InputSourceIndicator extends PanelMenu.Button {
} }
_buildPropSection(properties) { _buildPropSection(properties) {
this._propSeparator.actor.hide(); this._propSeparator.hide();
this._propSection.actor.hide(); this._propSection.actor.hide();
this._propSection.removeAll(); this._propSection.removeAll();
@ -931,7 +931,7 @@ class InputSourceIndicator extends PanelMenu.Button {
if (!this._propSection.isEmpty()) { if (!this._propSection.isEmpty()) {
this._propSection.actor.show(); this._propSection.actor.show();
this._propSeparator.actor.show(); this._propSeparator.show();
} }
} }

View File

@ -42,9 +42,11 @@ const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent'); var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Location_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA }); this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA });
this._settings.connect(`changed::${ENABLED}`, this._settings.connect(`changed::${ENABLED}`,
@ -222,7 +224,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._permStoreProxy = proxy; this._permStoreProxy = proxy;
} }
}; });
function clamp(value, min, max) { function clamp(value, min, max) {
return Math.max(min, Math.min(max, value)); return Math.max(min, Math.min(max, value));

View File

@ -630,7 +630,6 @@ var NMWirelessDialogItem = GObject.registerClass({
can_focus: true, can_focus: true,
reactive: true }); reactive: true });
this.connect('key-focus-in', () => this.emit('selected'));
let action = new Clutter.ClickAction(); let action = new Clutter.ClickAction();
action.connect('clicked', () => this.grab_key_focus()); action.connect('clicked', () => this.grab_key_focus());
this.add_action(action); this.add_action(action);
@ -659,6 +658,10 @@ var NMWirelessDialogItem = GObject.registerClass({
this._sync(); this._sync();
} }
vfunc_key_focus_in() {
this.emit('selected');
}
_sync() { _sync() {
this._signalIcon.icon_name = this._getSignalIcon(); this._signalIcon.icon_name = this._getSignalIcon();
} }
@ -860,7 +863,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
this._noNetworksSpinner = new Animation.Spinner(16); this._noNetworksSpinner = new Animation.Spinner(16);
this._noNetworksBox.add_actor(this._noNetworksSpinner.actor); this._noNetworksBox.add_actor(this._noNetworksSpinner);
this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label', this._noNetworksBox.add_actor(new St.Label({ style_class: 'no-networks-label',
text: _("No Networks") })); text: _("No Networks") }));
this._stack.add_child(this._noNetworksBox); this._stack.add_child(this._noNetworksBox);
@ -1588,9 +1591,11 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection {
} }
}; };
var NMApplet = class extends PanelMenu.SystemIndicator { var NMApplet = GObject.registerClass({
constructor() { GTypeName: 'Network_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._primaryIndicator = this._addIndicator(); this._primaryIndicator = this._addIndicator();
this._vpnIndicator = this._addIndicator(); this._vpnIndicator = this._addIndicator();
@ -1706,7 +1711,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
this._notification.connect('destroy', () => { this._notification.connect('destroy', () => {
this._notification = null; this._notification = null;
}); });
this._source.notify(this._notification); this._source.showNotification(this._notification);
} }
_onActivationFailed(_device, _reason) { _onActivationFailed(_device, _reason) {
@ -1939,7 +1944,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
} }
_syncNMState() { _syncNMState() {
this.indicators.visible = this._client.nm_running; this.visible = this._client.nm_running;
this.menu.actor.visible = this._client.networking_enabled; this.menu.actor.visible = this._client.networking_enabled;
this._updateIcon(); this._updateIcon();
@ -2058,4 +2063,4 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon(); this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon();
this._vpnIndicator.visible = (this._vpnIndicator.icon_name != ''); this._vpnIndicator.visible = (this._vpnIndicator.icon_name != '');
} }
}; });

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */ /* exported Indicator */
const Gio = imports.gi.Gio; const { Gio, GObject } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color';
const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color'); const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color');
const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface); const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface);
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'NightLight_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._indicator.icon_name = 'night-light-symbolic'; this._indicator.icon_name = 'night-light-symbolic';
@ -66,4 +68,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
: _("Disable Until Tomorrow"); : _("Disable Until Tomorrow");
this._item.visible = this._indicator.visible = visible; this._item.visible = this._indicator.visible = visible;
} }
}; });

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */ /* exported Indicator */
const { Clutter, Gio, St, UPowerGlib: UPower } = imports.gi; const { Clutter, Gio, GObject, St, UPowerGlib: UPower } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
@ -17,9 +17,11 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface)
const SHOW_BATTERY_PERCENTAGE = 'show-battery-percentage'; const SHOW_BATTERY_PERCENTAGE = 'show-battery-percentage';
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Power_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' }); this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect(`changed::${SHOW_BATTERY_PERCENTAGE}`, this._desktopSettings.connect(`changed::${SHOW_BATTERY_PERCENTAGE}`,
@ -28,8 +30,8 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._percentageLabel = new St.Label({ y_expand: true, this._percentageLabel = new St.Label({ y_expand: true,
y_align: Clutter.ActorAlign.CENTER }); y_align: Clutter.ActorAlign.CENTER });
this.indicators.add(this._percentageLabel, { expand: true, y_fill: true }); this.add(this._percentageLabel, { expand: true, y_fill: true });
this.indicators.add_style_class_name('power-status'); this.add_style_class_name('power-status');
this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH, this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
(proxy, error) => { (proxy, error) => {
@ -140,4 +142,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
// The status label // The status label
this._item.label.text = this._getStatus(); this._item.label.text = this._getStatus();
} }
}; });

View File

@ -1,14 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported RemoteAccessApplet */ /* exported RemoteAccessApplet */
const Meta = imports.gi.Meta; const { GObject, Meta } = imports.gi;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
var RemoteAccessApplet = class extends PanelMenu.SystemIndicator { var RemoteAccessApplet = GObject.registerClass({
constructor() { GTypeName: 'RemoteAccess_Indicator'
super(); }, class RemoteAccessApplet extends PanelMenu.SystemIndicator {
_init() {
super._init();
let backend = Meta.get_backend(); let backend = Meta.get_backend();
let controller = backend.get_remote_access_controller(); let controller = backend.get_remote_access_controller();
@ -75,4 +77,4 @@ var RemoteAccessApplet = class extends PanelMenu.SystemIndicator {
this._sync(); this._sync();
} }
} }
}; });

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */ /* exported Indicator */
const Gio = imports.gi.Gio; const { Gio, GObject } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -61,9 +61,11 @@ function getRfkillManager() {
return _manager; return _manager;
} }
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Rfkill_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._manager = getRfkillManager(); this._manager = getRfkillManager();
this._manager.connect('airplane-mode-changed', this._sync.bind(this)); this._manager.connect('airplane-mode-changed', this._sync.bind(this));
@ -106,4 +108,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
else else
this._offItem.label.text = _("Turn Off"); this._offItem.label.text = _("Turn Off");
} }
}; });

View File

@ -1,12 +1,16 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */ /* exported Indicator */
const GObject = imports.gi.GObject;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Screencast_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._indicator.icon_name = 'media-record-symbolic'; this._indicator.icon_name = 'media-record-symbolic';
@ -19,4 +23,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
_sync() { _sync() {
this._indicator.visible = Main.screencastService.isRecording; this._indicator.visible = Main.screencastService.isRecording;
} }
}; });

View File

@ -10,8 +10,10 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
var AltSwitcher = class { var AltSwitcher = GObject.registerClass(
constructor(standard, alternate) { class AltSwitcher extends St.Bin {
_init(standard, alternate) {
super._init();
this._standard = standard; this._standard = standard;
this._standard.connect('notify::visible', this._sync.bind(this)); this._standard.connect('notify::visible', this._sync.bind(this));
if (this._standard instanceof St.Button) if (this._standard instanceof St.Button)
@ -31,9 +33,17 @@ var AltSwitcher = class {
this._clickAction = new Clutter.ClickAction(); this._clickAction = new Clutter.ClickAction();
this._clickAction.connect('long-press', this._onLongPress.bind(this)); this._clickAction.connect('long-press', this._onLongPress.bind(this));
this.actor = new St.Bin(); this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this)); }
this.actor.connect('notify::mapped', () => (this._flipped = false));
vfunc_map() {
super.vfunc_map();
this._flipped = false;
}
vfunc_unmap() {
super.vfunc_unmap();
this._flipped = false;
} }
_sync() { _sync() {
@ -51,11 +61,11 @@ var AltSwitcher = class {
} else if (this._alternate.visible) { } else if (this._alternate.visible) {
childToShow = this._alternate; childToShow = this._alternate;
} else { } else {
this.actor.hide(); this.hide();
return; return;
} }
let childShown = this.actor.get_child(); let childShown = this.get_child();
if (childShown != childToShow) { if (childShown != childToShow) {
if (childShown) { if (childShown) {
if (childShown.fake_release) if (childShown.fake_release)
@ -64,8 +74,8 @@ var AltSwitcher = class {
} }
childToShow.add_action(this._clickAction); childToShow.add_action(this._clickAction);
let hasFocus = this.actor.contains(global.stage.get_key_focus()); let hasFocus = this.contains(global.stage.get_key_focus());
this.actor.set_child(childToShow); this.set_child(childToShow);
if (hasFocus) if (hasFocus)
childToShow.grab_key_focus(); childToShow.grab_key_focus();
@ -74,7 +84,7 @@ var AltSwitcher = class {
global.sync_pointer(); global.sync_pointer();
} }
this.actor.show(); this.show();
} }
_onDestroy() { _onDestroy() {
@ -104,11 +114,13 @@ var AltSwitcher = class {
this._sync(); this._sync();
return true; return true;
} }
}; });
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'System_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
let userManager = AccountsService.UserManager.get_default(); let userManager = AccountsService.UserManager.get_default();
this._user = userManager.get_user(GLib.get_user_name()); this._user = userManager.get_user(GLib.get_user_name());
@ -289,7 +301,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
bindFlags); bindFlags);
this._altSwitcher = new AltSwitcher(this._powerOffAction, this._suspendAction); this._altSwitcher = new AltSwitcher(this._powerOffAction, this._suspendAction);
item.add(this._altSwitcher.actor, { expand: true, x_fill: false }); item.add(this._altSwitcher, { expand: true, x_fill: false });
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
@ -297,7 +309,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._settingsAction, this._settingsAction,
this._orientationLockAction, this._orientationLockAction,
this._lockScreenAction, this._lockScreenAction,
this._altSwitcher.actor, this._altSwitcher,
]; ];
for (let actor of visibilityGroup) { for (let actor of visibilityGroup) {
@ -312,4 +324,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
Main.overview.hide(); Main.overview.hide();
this._settingsApp.activate(); this._settingsApp.activate();
} }
}; });

View File

@ -3,7 +3,7 @@
// the following is a modified version of bolt/contrib/js/client.js // the following is a modified version of bolt/contrib/js/client.js
const { Gio, GLib, Polkit, Shell } = imports.gi; const { Gio, GLib, GObject, Polkit, Shell } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -221,9 +221,11 @@ Signals.addSignalMethods(AuthRobot.prototype);
/* eof client.js */ /* eof client.js */
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Thunderbolt_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._indicator.icon_name = 'thunderbolt-symbolic'; this._indicator.icon_name = 'thunderbolt-symbolic';
@ -284,7 +286,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
if (app) if (app)
app.activate(); app.activate();
}); });
this._source.notify(this._notification); this._source.showNotification(this._notification);
} }
/* Session callbacks */ /* Session callbacks */
@ -334,4 +336,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
const body = _("Could not authorize the Thunderbolt device: %s").format(error.message); const body = _("Could not authorize the Thunderbolt device: %s").format(error.message);
this._notify(title, body); this._notify(title, body);
} }
}; });

View File

@ -47,7 +47,7 @@ var StreamSlider = class {
return this._slider.startDragging(event); return this._slider.startDragging(event);
}); });
this.item.connect('key-press-event', (actor, event) => { this.item.connect('key-press-event', (actor, event) => {
return this._slider.onKeyPressEvent(actor, event); return this._slider.emit('key-press-event', event);
}); });
this._stream = null; this._stream = null;
@ -299,6 +299,9 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this.addMenuItem(this._output.item); this.addMenuItem(this._output.item);
this._input = new InputStreamSlider(this._control); this._input = new InputStreamSlider(this._control);
this._input.item.connect('notify::visible', () => {
this.emit('input-visible-changed');
});
this.addMenuItem(this._input.item); this.addMenuItem(this._input.item);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@ -338,34 +341,44 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
getMaxLevel() { getMaxLevel() {
return this._output.getMaxLevel(); return this._output.getMaxLevel();
} }
getInputVisible() {
return this._input.item.visible;
}
}; };
var Indicator = class extends PanelMenu.SystemIndicator { var Indicator = GObject.registerClass({
constructor() { GTypeName: 'Volume_Indicator'
super(); }, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._primaryIndicator = this._addIndicator(); this._primaryIndicator = this._addIndicator();
this._inputIndicator = this._addIndicator();
this._control = getMixerControl(); this._control = getMixerControl();
this._volumeMenu = new VolumeMenu(this._control); this._volumeMenu = new VolumeMenu(this._control);
this._volumeMenu.connect('icon-changed', () => { this._volumeMenu.connect('icon-changed', () => {
let icon = this._volumeMenu.getIcon(); let icon = this._volumeMenu.getIcon();
if (icon != null) { if (icon != null)
this.indicators.show();
this._primaryIndicator.icon_name = icon; this._primaryIndicator.icon_name = icon;
} else { this._primaryIndicator.visible = icon !== null;
this.indicators.hide(); });
}
this._inputIndicator.set({
icon_name: 'audio-input-microphone-symbolic',
visible: this._volumeMenu.getInputVisible(),
});
this._volumeMenu.connect('input-visible-changed', () => {
this._inputIndicator.visible = this._volumeMenu.getInputVisible();
}); });
this.menu.addMenuItem(this._volumeMenu); this.menu.addMenuItem(this._volumeMenu);
this.indicators.connect('scroll-event', this._onScrollEvent.bind(this));
} }
_onScrollEvent(actor, event) { vfunc_scroll_event() {
let result = this._volumeMenu.scroll(event); let result = this._volumeMenu.scroll(Clutter.get_current_event());
if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped) if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped)
return result; return result;
@ -375,4 +388,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
Main.osdWindowManager.show(-1, gicon, null, level, maxLevel); Main.osdWindowManager.show(-1, gicon, null, level, maxLevel);
return result; return result;
} }
}; });

View File

@ -105,12 +105,6 @@ var SwitcherPopup = GObject.registerClass({
this._haveModal = true; this._haveModal = true;
this._modifierMask = primaryModifier(mask); this._modifierMask = primaryModifier(mask);
this.connect('key-press-event', this._keyPressEvent.bind(this));
this.connect('key-release-event', this._keyReleaseEvent.bind(this));
this.connect('button-press-event', this._clickedOutside.bind(this));
this.connect('scroll-event', this._scrollEvent.bind(this));
this.add_actor(this._switcherList); this.add_actor(this._switcherList);
this._switcherList.connect('item-activated', this._itemActivated.bind(this)); this._switcherList.connect('item-activated', this._itemActivated.bind(this));
this._switcherList.connect('item-entered', this._itemEntered.bind(this)); this._switcherList.connect('item-entered', this._itemEntered.bind(this));
@ -166,9 +160,10 @@ var SwitcherPopup = GObject.registerClass({
throw new GObject.NotImplementedError(`_keyPressHandler in ${this.constructor.name}`); throw new GObject.NotImplementedError(`_keyPressHandler in ${this.constructor.name}`);
} }
_keyPressEvent(actor, event) { vfunc_key_press_event(keyEvent) {
let keysym = event.get_key_symbol(); let keysym = keyEvent.keyval;
let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state()); let action = global.display.get_keybinding_action(
keyEvent.hardware_keycode, keyEvent.modifier_state);
this._disableHover(); this._disableHover();
@ -183,13 +178,13 @@ var SwitcherPopup = GObject.registerClass({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_keyReleaseEvent(actor, event) { vfunc_key_release_event(keyEvent) {
if (this._modifierMask) { if (this._modifierMask) {
let [x_, y_, mods] = global.get_pointer(); let [x_, y_, mods] = global.get_pointer();
let state = mods & this._modifierMask; let state = mods & this._modifierMask;
if (state == 0) if (state == 0)
this._finish(event.get_time()); this._finish(keyEvent.time);
} else { } else {
this._resetNoModsTimeout(); this._resetNoModsTimeout();
} }
@ -197,7 +192,8 @@ var SwitcherPopup = GObject.registerClass({
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_clickedOutside() { vfunc_button_press_event() {
/* We clicked outside */
this.fadeAndDestroy(); this.fadeAndDestroy();
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }
@ -209,8 +205,8 @@ var SwitcherPopup = GObject.registerClass({
this._select(this._next()); this._select(this._next());
} }
_scrollEvent(actor, event) { vfunc_scroll_event(scrollEvent) {
this._scrollHandler(event.get_scroll_direction()); this._scrollHandler(scrollEvent.scroll_direction);
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
} }

View File

@ -44,7 +44,7 @@ var UnlockDialog = GObject.registerClass({
this._authPrompt.setPasswordChar('\u25cf'); this._authPrompt.setPasswordChar('\u25cf');
this._authPrompt.nextButton.label = _("Unlock"); this._authPrompt.nextButton.label = _("Unlock");
this._promptBox.add_child(this._authPrompt.actor); this._promptBox.add_child(this._authPrompt);
this.allowCancel = false; this.allowCancel = false;

View File

@ -14,29 +14,47 @@ var AVATAR_ICON_SIZE = 64;
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>. // Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
// Copyright (C) 2008,2009 Red Hat, Inc. // Copyright (C) 2008,2009 Red Hat, Inc.
var Avatar = class { var Avatar = GObject.registerClass({
constructor(user, params) { GTypeName: 'UserWidget_Avatar'
this._user = user; }, class Avatar extends St.Bin {
_init(user, params) {
let themeContext = St.ThemeContext.get_for_stage(global.stage);
params = Params.parse(params, { reactive: false, params = Params.parse(params, { reactive: false,
iconSize: AVATAR_ICON_SIZE, iconSize: AVATAR_ICON_SIZE,
styleClass: 'user-icon' }); styleClass: 'user-icon' });
this._iconSize = params.iconSize;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor; super._init({
this.actor = new St.Bin({ style_class: params.styleClass, style_class: params.styleClass,
track_hover: params.reactive,
reactive: params.reactive, reactive: params.reactive,
width: this._iconSize * scaleFactor, width: params.iconSize * themeContext.scaleFactor,
height: this._iconSize * scaleFactor }); height: params.iconSize * themeContext.scaleFactor
});
this._iconSize = params.iconSize;
this._user = user;
this.bind_property('reactive', this, 'track-hover',
GObject.BindingFlags.SYNC_CREATE);
this.bind_property('reactive', this, 'can-focus',
GObject.BindingFlags.SYNC_CREATE);
// Monitor the scaling factor to make sure we recreate the avatar when needed. // Monitor the scaling factor to make sure we recreate the avatar when needed.
let themeContext = St.ThemeContext.get_for_stage(global.stage); this._scaleFactorChangeId =
themeContext.connect('notify::scale-factor', this.update.bind(this)); themeContext.connect('notify::scale-factor', this.update.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._scaleFactorChangeId) {
let themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.disconnect(this._scaleFactorChangeId);
delete this._scaleFactorChangeId;
}
} }
setSensitive(sensitive) { setSensitive(sensitive) {
this.actor.can_focus = sensitive; this.reactive = sensitive;
this.actor.reactive = sensitive;
} }
update() { update() {
@ -45,21 +63,21 @@ var Avatar = class {
iconFile = null; iconFile = null;
if (iconFile) { if (iconFile) {
this.actor.child = null; this.child = null;
let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage); let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
this.actor.set_size( this.set_size(
this._iconSize * scaleFactor, this._iconSize * scaleFactor,
this._iconSize * scaleFactor); this._iconSize * scaleFactor);
this.actor.style = ` this.style = `
background-image: url("${iconFile}"); background-image: url("${iconFile}");
background-size: cover;`; background-size: cover;`;
} else { } else {
this.actor.style = null; this.style = null;
this.actor.child = new St.Icon({ icon_name: 'avatar-default-symbolic', this.child = new St.Icon({ icon_name: 'avatar-default-symbolic',
icon_size: this._iconSize }); icon_size: this._iconSize });
} }
} }
}; });
var UserWidgetLabel = GObject.registerClass( var UserWidgetLabel = GObject.registerClass(
class UserWidgetLabel extends St.Widget { class UserWidgetLabel extends St.Widget {
@ -140,21 +158,22 @@ class UserWidgetLabel extends St.Widget {
} }
}); });
var UserWidget = class { var UserWidget = GObject.registerClass(
constructor(user) { class UserWidget extends St.BoxLayout {
_init(user) {
super._init({ style_class: 'user-widget', vertical: false });
this._user = user; this._user = user;
this.actor = new St.BoxLayout({ style_class: 'user-widget', this.connect('destroy', this._onDestroy.bind(this));
vertical: false });
this.actor.connect('destroy', this._onDestroy.bind(this));
this._avatar = new Avatar(user); this._avatar = new Avatar(user);
this.actor.add_child(this._avatar.actor); this.add_child(this._avatar);
this._label = new UserWidgetLabel(user); this._label = new UserWidgetLabel(user);
this.actor.add_child(this._label); this.add_child(this._label);
this._label.bind_property('label-actor', this.actor, 'label-actor', this._label.bind_property('label-actor', this, 'label-actor',
GObject.BindingFlags.SYNC_CREATE); GObject.BindingFlags.SYNC_CREATE);
this._userLoadedId = this._user.connect('notify::is-loaded', this._updateUser.bind(this)); this._userLoadedId = this._user.connect('notify::is-loaded', this._updateUser.bind(this));
@ -177,4 +196,4 @@ var UserWidget = class {
_updateUser() { _updateUser() {
this._avatar.update(); this._avatar.update();
} }
}; });

View File

@ -123,9 +123,14 @@ var ShowOverviewAction = GObject.registerClass({
} }
}); });
var ViewSelector = class { var ViewSelector = GObject.registerClass({
constructor(searchEntry, showAppsButton) { Signals: {
this.actor = new Shell.Stack({ name: 'viewSelector' }); 'page-changed': {},
'page-empty': {},
}
}, class ViewSelector extends Shell.Stack {
_init(searchEntry, showAppsButton) {
super._init({ name: 'viewSelector' });
this._showAppsButton = showAppsButton; this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this)); this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
@ -165,15 +170,15 @@ var ViewSelector = class {
this._capturedEventId = 0; this._capturedEventId = 0;
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay(); this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._workspacesPage = this._addPage(this._workspacesDisplay.actor, this._workspacesPage = this._addPage(this._workspacesDisplay,
_("Windows"), 'focus-windows-symbolic'); _("Windows"), 'focus-windows-symbolic');
this.appDisplay = new AppDisplay.AppDisplay(); this.appDisplay = new AppDisplay.AppDisplay();
this._appsPage = this._addPage(this.appDisplay.actor, this._appsPage = this._addPage(this.appDisplay,
_("Applications"), 'view-app-grid-symbolic'); _("Applications"), 'view-app-grid-symbolic');
this._searchResults = new Search.SearchResults(); this._searchResults = new Search.SearchResultsView();
this._searchPage = this._addPage(this._searchResults.actor, this._searchPage = this._addPage(this._searchResults,
_("Search"), 'edit-find-symbolic', _("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry }); { a11yFocus: this._entry });
@ -184,9 +189,9 @@ var ViewSelector = class {
this._focusTrap.connect('key-focus-in', () => { this._focusTrap.connect('key-focus-in', () => {
this._entry.grab_key_focus(); this._entry.grab_key_focus();
}); });
this._searchResults.actor.add_actor(this._focusTrap); this._searchResults.add_actor(this._focusTrap);
global.focus_manager.add_group(this._searchResults.actor); global.focus_manager.add_group(this._searchResults);
this._stageKeyPressId = 0; this._stageKeyPressId = 0;
Main.overview.connect('showing', () => { Main.overview.connect('showing', () => {
@ -310,11 +315,11 @@ var ViewSelector = class {
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon); Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
else else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, { Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, {
proxy: this.actor, proxy: this,
focusCallback: () => this._a11yFocusPage(page), focusCallback: () => this._a11yFocusPage(page),
}); });
page.hide(); page.hide();
this.actor.add_actor(page); this.add_actor(page);
return page; return page;
} }
@ -454,7 +459,7 @@ var ViewSelector = class {
_onStageKeyFocusChanged() { _onStageKeyFocusChanged() {
let focus = global.stage.get_key_focus(); let focus = global.stage.get_key_focus();
let appearFocused = (this._entry.contains(focus) || let appearFocused = (this._entry.contains(focus) ||
this._searchResults.actor.contains(focus)); this._searchResults.contains(focus));
this._text.set_cursor_visible(appearFocused); this._text.set_cursor_visible(appearFocused);
@ -599,5 +604,4 @@ var ViewSelector = class {
else else
return ViewPage.SEARCH; return ViewPage.SEARCH;
} }
}; });
Signals.addSignalMethods(ViewSelector.prototype);

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowAttentionHandler */ /* exported WindowAttentionHandler */
const Shell = imports.gi.Shell; const { GObject, Shell } = imports.gi;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
@ -34,7 +34,7 @@ var WindowAttentionHandler = class {
return; return;
let app = this._tracker.get_window_app(window); let app = this._tracker.get_window_app(window);
let source = new Source(app, window); let source = new WindowAttentionSource(app, window);
Main.messageTray.add(source); Main.messageTray.add(source);
let [title, banner] = this._getTitleAndBanner(app, window); let [title, banner] = this._getTitleAndBanner(app, window);
@ -45,7 +45,7 @@ var WindowAttentionHandler = class {
}); });
notification.setForFeedback(true); notification.setForFeedback(true);
source.notify(notification); source.showNotification(notification);
source.signalIDs.push(window.connect('notify::title', () => { source.signalIDs.push(window.connect('notify::title', () => {
let [title, banner] = this._getTitleAndBanner(app, window); let [title, banner] = this._getTitleAndBanner(app, window);
@ -54,9 +54,10 @@ var WindowAttentionHandler = class {
} }
}; };
var Source = class WindowAttentionSource extends MessageTray.Source { var WindowAttentionSource = GObject.registerClass(
constructor(app, window) { class WindowAttentionSource extends MessageTray.Source {
super(app.get_name()); _init(app, window) {
super._init(app.get_name());
this._window = window; this._window = window;
this._app = app; this._app = app;
@ -102,4 +103,4 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
open() { open() {
Main.activateWindow(this._window); Main.activateWindow(this._window);
} }
}; });

View File

@ -40,6 +40,8 @@ const GSD_WACOM_OBJECT_PATH = '/org/gnome/SettingsDaemon/Wacom';
const GsdWacomIface = loadInterfaceXML('org.gnome.SettingsDaemon.Wacom'); const GsdWacomIface = loadInterfaceXML('org.gnome.SettingsDaemon.Wacom');
const GsdWacomProxy = Gio.DBusProxy.makeProxyWrapper(GsdWacomIface); const GsdWacomProxy = Gio.DBusProxy.makeProxyWrapper(GsdWacomIface);
const WINDOW_DIMMER_EFFECT_NAME = "gnome-shell-window-dimmer";
var DisplayChangeDialog = GObject.registerClass( var DisplayChangeDialog = GObject.registerClass(
class DisplayChangeDialog extends ModalDialog.ModalDialog { class DisplayChangeDialog extends ModalDialog.ModalDialog {
_init(wm) { _init(wm) {
@ -114,21 +116,20 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
} }
}); });
var WindowDimmer = class { var WindowDimmer = GObject.registerClass(
constructor(actor) { class WindowDimmer extends Clutter.BrightnessContrastEffect {
this._brightnessEffect = new Clutter.BrightnessContrastEffect({ _init() {
name: 'dim', super._init({
name: WINDOW_DIMMER_EFFECT_NAME,
enabled: false enabled: false
}); });
actor.add_effect(this._brightnessEffect);
this.actor = actor;
this._enabled = true; this._enabled = true;
} }
_syncEnabled() { _syncEnabled() {
let animating = this.actor.get_transition('@effects.dim.brightness') != null; let animating = this.actor.get_transition(`@effects.${this.name}.brightness`) != null;
let dimmed = this._brightnessEffect.brightness.red != 127; let dimmed = this.brightness.red != 127;
this._brightnessEffect.enabled = this._enabled && (animating || dimmed); this.enabled = this._enabled && (animating || dimmed);
} }
setEnabled(enabled) { setEnabled(enabled) {
@ -140,7 +141,7 @@ var WindowDimmer = class {
let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS); let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS);
let color = Clutter.Color.new(val, val, val, 255); let color = Clutter.Color.new(val, val, val, 255);
this.actor.ease_property('@effects.dim.brightness', color, { this.actor.ease_property(`@effects.${this.name}.brightness`, color, {
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR,
duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0), duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0),
onComplete: () => this._syncEnabled() onComplete: () => this._syncEnabled()
@ -148,20 +149,19 @@ var WindowDimmer = class {
this._syncEnabled(); this._syncEnabled();
} }
}; });
function getWindowDimmer(actor) { function getWindowDimmer(actor) {
let enabled = Meta.prefs_get_attach_modal_dialogs(); let enabled = Meta.prefs_get_attach_modal_dialogs();
if (actor._windowDimmer) let effect = actor.get_effect(WINDOW_DIMMER_EFFECT_NAME);
actor._windowDimmer.setEnabled(enabled);
if (enabled) { if (effect) {
if (!actor._windowDimmer) effect.setEnabled(enabled);
actor._windowDimmer = new WindowDimmer(actor); } else if (enabled) {
return actor._windowDimmer; effect = new WindowDimmer();
} else { actor.add_effect(effect);
return null;
} }
return effect;
} }
/* /*
@ -379,21 +379,22 @@ var WorkspaceTracker = class {
} }
}; };
var TilePreview = class { var TilePreview = GObject.registerClass(
constructor() { class TilePreview extends St.Widget {
this.actor = new St.Widget(); _init() {
global.window_group.add_actor(this.actor); super._init();
global.window_group.add_actor(this);
this._reset(); this._reset();
this._showing = false; this._showing = false;
} }
show(window, tileRect, monitorIndex) { open(window, tileRect, monitorIndex) {
let windowActor = window.get_compositor_private(); let windowActor = window.get_compositor_private();
if (!windowActor) if (!windowActor)
return; return;
global.window_group.set_child_below_sibling(this.actor, windowActor); global.window_group.set_child_below_sibling(this, windowActor);
if (this._rect && this._rect.equal(tileRect)) if (this._rect && this._rect.equal(tileRect))
return; return;
@ -414,14 +415,14 @@ var TilePreview = class {
width: monitor.width, width: monitor.width,
height: monitor.height }); height: monitor.height });
let [, rect] = window.get_frame_rect().intersect(monitorRect); let [, rect] = window.get_frame_rect().intersect(monitorRect);
this.actor.set_size(rect.width, rect.height); this.set_size(rect.width, rect.height);
this.actor.set_position(rect.x, rect.y); this.set_position(rect.x, rect.y);
this.actor.opacity = 0; this.opacity = 0;
} }
this._showing = true; this._showing = true;
this.actor.show(); this.show();
this.actor.ease({ this.ease({
x: tileRect.x, x: tileRect.x,
y: tileRect.y, y: tileRect.y,
width: tileRect.width, width: tileRect.width,
@ -432,12 +433,12 @@ var TilePreview = class {
}); });
} }
hide() { close() {
if (!this._showing) if (!this._showing)
return; return;
this._showing = false; this._showing = false;
this.actor.ease({ this.ease({
opacity: 0, opacity: 0,
duration: WINDOW_ANIMATION_TIME, duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@ -446,7 +447,7 @@ var TilePreview = class {
} }
_reset() { _reset() {
this.actor.hide(); this.hide();
this._rect = null; this._rect = null;
this._monitorIndex = -1; this._monitorIndex = -1;
} }
@ -460,9 +461,9 @@ var TilePreview = class {
if (this._rect.x + this._rect.width == monitor.x + monitor.width) if (this._rect.x + this._rect.width == monitor.x + monitor.width)
styles.push('tile-preview-right'); styles.push('tile-preview-right');
this.actor.style_class = styles.join(' '); this.style_class = styles.join(' ');
} }
}; });
var TouchpadWorkspaceSwitchAction = class { var TouchpadWorkspaceSwitchAction = class {
constructor(actor, allowedModes) { constructor(actor, allowedModes) {
@ -669,15 +670,16 @@ var AppSwitchAction = GObject.registerClass({
} }
}); });
var ResizePopup = class { var ResizePopup = GObject.registerClass(
constructor() { class ResizePopup extends St.Widget {
this._widget = new St.Widget({ layout_manager: new Clutter.BinLayout() }); _init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._label = new St.Label({ style_class: 'resize-popup', this._label = new St.Label({ style_class: 'resize-popup',
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER, y_align: Clutter.ActorAlign.CENTER,
x_expand: true, y_expand: true }); x_expand: true, y_expand: true });
this._widget.add_child(this._label); this.add_child(this._label);
Main.uiGroup.add_actor(this._widget); Main.uiGroup.add_actor(this);
} }
set(rect, displayW, displayH) { set(rect, displayW, displayH) {
@ -686,15 +688,10 @@ var ResizePopup = class {
let text = _("%d × %d").format(displayW, displayH); let text = _("%d × %d").format(displayW, displayH);
this._label.set_text(text); this._label.set_text(text);
this._widget.set_position(rect.x, rect.y); this.set_position(rect.x, rect.y);
this._widget.set_size(rect.width, rect.height); this.set_size(rect.width, rect.height);
} }
});
destroy() {
this._widget.destroy();
this._widget = null;
}
};
var WindowManager = class { var WindowManager = class {
constructor() { constructor() {
@ -1089,7 +1086,7 @@ var WindowManager = class {
let mode = Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN; let mode = Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN;
let bottomDragAction = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM, mode); let bottomDragAction = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM, mode);
bottomDragAction.connect('activated', () => { bottomDragAction.connect('activated', () => {
Main.keyboard.show(Main.layoutManager.bottomIndex); Main.keyboard.open(Main.layoutManager.bottomIndex);
}); });
Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => { Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => {
bottomDragAction.cancel(); bottomDragAction.cancel();
@ -1119,7 +1116,7 @@ var WindowManager = class {
this._currentPadOsd = new PadOsd.PadOsd(device, settings, imagePath, editionMode, monitorIndex); this._currentPadOsd = new PadOsd.PadOsd(device, settings, imagePath, editionMode, monitorIndex);
this._currentPadOsd.connect('closed', () => (this._currentPadOsd = null)); this._currentPadOsd.connect('closed', () => (this._currentPadOsd = null));
return this._currentPadOsd.actor; return this._currentPadOsd;
} }
_switchWorkspaceMotion(action, xRel, yRel) { _switchWorkspaceMotion(action, xRel, yRel) {
@ -2045,13 +2042,13 @@ var WindowManager = class {
_showTilePreview(shellwm, window, tileRect, monitorIndex) { _showTilePreview(shellwm, window, tileRect, monitorIndex) {
if (!this._tilePreview) if (!this._tilePreview)
this._tilePreview = new TilePreview(); this._tilePreview = new TilePreview();
this._tilePreview.show(window, tileRect, monitorIndex); this._tilePreview.open(window, tileRect, monitorIndex);
} }
_hideTilePreview() { _hideTilePreview() {
if (!this._tilePreview) if (!this._tilePreview)
return; return;
this._tilePreview.hide(); this._tilePreview.close();
} }
_showWindowMenu(shellwm, window, menu, rect) { _showWindowMenu(shellwm, window, menu, rect) {

View File

@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Workspace */ /* exported Workspace */
const { Atk, Clutter, GLib, GObject, Meta, Pango, Shell, St } = imports.gi; const { Atk, Clutter, GLib, GObject,
Graphene, Meta, Pango, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
@ -93,6 +94,7 @@ class WindowCloneLayout extends Clutter.LayoutManager {
}); });
var WindowClone = GObject.registerClass({ var WindowClone = GObject.registerClass({
GTypeName: 'Workspace_WindowClone',
Signals: { Signals: {
'drag-begin': {}, 'drag-begin': {},
'drag-cancelled': {}, 'drag-cancelled': {},
@ -102,7 +104,7 @@ var WindowClone = GObject.registerClass({
'show-chrome': {}, 'show-chrome': {},
'size-changed': {} 'size-changed': {}
}, },
}, class WorkspaceWindowClone extends St.Widget { }, class WindowClone extends St.Widget {
_init(realWindow, workspace) { _init(realWindow, workspace) {
this.realWindow = realWindow; this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window; this.metaWindow = realWindow.meta_window;
@ -157,18 +159,13 @@ var WindowClone = GObject.registerClass({
this.x = this._boundingBox.x; this.x = this._boundingBox.x;
this.y = this._boundingBox.y; this.y = this._boundingBox.y;
this._computeWindowCenter();
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', this._onClicked.bind(this)); clickAction.connect('clicked', this._onClicked.bind(this));
clickAction.connect('long-press', this._onLongPress.bind(this)); clickAction.connect('long-press', this._onLongPress.bind(this));
this.add_action(clickAction); this.add_action(clickAction);
this.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
this.connect('key-press-event', this._onKeyPress.bind(this));
this.connect('enter-event', () => this.emit('show-chrome'));
this.connect('key-focus-in', () => this.emit('show-chrome'));
this.connect('leave-event', () => this.emit('hide-chrome'));
this.connect('key-focus-out', () => this.emit('hide-chrome'));
this._draggable = DND.makeDraggable(this, this._draggable = DND.makeDraggable(this,
{ restoreOnSuccess: true, { restoreOnSuccess: true,
@ -299,6 +296,18 @@ var WindowClone = GObject.registerClass({
this.layout_manager.boundingBox = rect; this.layout_manager.boundingBox = rect;
} }
get windowCenter() {
return this._windowCenter;
}
_computeWindowCenter() {
let box = this.realWindow.get_allocation_box();
this._windowCenter = new Graphene.Point({
x: box.get_x() + box.get_width() / 2,
y: box.get_y() + box.get_height() / 2,
});
}
// Find the actor just below us, respecting reparenting done by DND code // Find the actor just below us, respecting reparenting done by DND code
getActualStackAbove() { getActualStackAbove() {
if (this._stackAbove == null) if (this._stackAbove == null)
@ -368,8 +377,28 @@ var WindowClone = GObject.registerClass({
this.emit('selected', global.get_current_time()); this.emit('selected', global.get_current_time());
} }
_onKeyPress(actor, event) { vfunc_enter_event(crossingEvent) {
let symbol = event.get_key_symbol(); this.emit('show-chrome');
return super.vfunc_enter_event(crossingEvent);
}
vfunc_leave_event(crossingEvent) {
this.emit('hide-chrome');
return super.vfunc_leave_event(crossingEvent);
}
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this.emit('show-chrome');
}
vfunc_key_focus_out() {
super.vfunc_key_focus_out();
this.emit('hide-chrome');
}
vfunc_key_press_event(keyEvent) {
let symbol = keyEvent.keyval;
let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter); let isEnter = (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_KP_Enter);
if (isEnter) { if (isEnter) {
this._activate(); this._activate();
@ -1003,11 +1032,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
_sortRow(row) { _sortRow(row) {
// Sort windows horizontally to minimize travel distance. // Sort windows horizontally to minimize travel distance.
// This affects in what order the windows end up in a row. // This affects in what order the windows end up in a row.
row.windows.sort((a, b) => { row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
let aCenter = a.realWindow.x + a.realWindow.width / 2;
let bCenter = b.realWindow.x + b.realWindow.width / 2;
return aCenter - bCenter;
});
} }
computeLayout(windows, layout) { computeLayout(windows, layout) {
@ -1026,11 +1051,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
// Sort windows vertically to minimize travel distance. // Sort windows vertically to minimize travel distance.
// This affects what rows the windows get placed in. // This affects what rows the windows get placed in.
let sortedWindows = windows.slice(); let sortedWindows = windows.slice();
sortedWindows.sort((a, b) => { sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
let aCenter = a.realWindow.y + a.realWindow.height / 2;
let bCenter = b.realWindow.y + b.realWindow.height / 2;
return aCenter - bCenter;
});
let windowIdx = 0; let windowIdx = 0;
for (let i = 0; i < numRows; i++) { for (let i = 0; i < numRows; i++) {
@ -1094,23 +1115,14 @@ function rectEqual(one, two) {
one.height == two.height); one.height == two.height);
} }
const WorkspaceActor = GObject.registerClass(
class WorkspaceActor extends St.Widget {
vfunc_get_focus_chain() {
return this.get_children().filter(c => c.visible).sort((a, b) => {
if (a instanceof WindowClone && b instanceof WindowClone)
return a.slotId - b.slotId;
return 0;
});
}
});
/** /**
* @metaWorkspace: a #Meta.Workspace, or null * @metaWorkspace: a #Meta.Workspace, or null
*/ */
var Workspace = class { var Workspace = GObject.registerClass(
constructor(metaWorkspace, monitorIndex) { class Workspace extends St.Widget {
_init(metaWorkspace, monitorIndex) {
super._init({ style_class: 'window-picker' });
// When dragging a window, we use this slot for reserve space. // When dragging a window, we use this slot for reserve space.
this._reservedSlot = null; this._reservedSlot = null;
this._reservedSlotWindow = null; this._reservedSlotWindow = null;
@ -1136,18 +1148,17 @@ var Workspace = class {
// Without this the drop area will be overlapped. // Without this the drop area will be overlapped.
this._windowOverlaysGroup.set_size(0, 0); this._windowOverlaysGroup.set_size(0, 0);
this.actor = new WorkspaceActor({ style_class: 'window-picker' });
if (monitorIndex != Main.layoutManager.primaryIndex) if (monitorIndex != Main.layoutManager.primaryIndex)
this.actor.add_style_class_name('external-monitor'); this.add_style_class_name('external-monitor');
this.actor.set_size(0, 0); this.set_size(0, 0);
this._dropRect = new Clutter.Actor({ opacity: 0 }); this._dropRect = new Clutter.Actor({ opacity: 0 });
this._dropRect._delegate = this; this._dropRect._delegate = this;
this.actor.add_actor(this._dropRect); this.add_actor(this._dropRect);
this.actor.add_actor(this._windowOverlaysGroup); this.add_actor(this._windowOverlaysGroup);
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
let windows = global.get_window_actors().filter(this._isMyWindow, this); let windows = global.get_window_actors().filter(this._isMyWindow, this);
@ -1177,10 +1188,19 @@ var Workspace = class {
this._positionWindowsFlags = 0; this._positionWindowsFlags = 0;
this._positionWindowsId = 0; this._positionWindowsId = 0;
}
this.actor.connect('notify::mapped', () => { vfunc_map() {
if (this.actor.mapped) super.vfunc_map();
this._syncActualGeometry(); this._syncActualGeometry();
}
vfunc_get_focus_chain() {
return this.get_children().filter(c => c.visible).sort((a, b) => {
if (a instanceof WindowClone && b instanceof WindowClone)
return a.slotId - b.slotId;
return 0;
}); });
} }
@ -1190,7 +1210,7 @@ var Workspace = class {
this._fullGeometry = geom; this._fullGeometry = geom;
if (this.actor.mapped) if (this.mapped)
this._recalculateWindowPositions(WindowPositionFlags.NONE); this._recalculateWindowPositions(WindowPositionFlags.NONE);
} }
@ -1201,7 +1221,7 @@ var Workspace = class {
this._actualGeometry = geom; this._actualGeometry = geom;
this._actualGeometryDirty = true; this._actualGeometryDirty = true;
if (this.actor.mapped) if (this.mapped)
this._syncActualGeometry(); this._syncActualGeometry();
} }
@ -1213,7 +1233,7 @@ var Workspace = class {
this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._actualGeometryLater = 0; this._actualGeometryLater = 0;
if (!this.actor.mapped) if (!this.mapped)
return false; return false;
let geom = this._actualGeometry; let geom = this._actualGeometry;
@ -1504,8 +1524,7 @@ var Workspace = class {
// Newly-created windows are added to a workspace before // Newly-created windows are added to a workspace before
// the compositor finds out about them... // the compositor finds out about them...
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => { let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (this.actor && if (metaWin.get_compositor_private() &&
metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace) metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin); this._doAddWindow(metaWin);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
@ -1541,8 +1560,8 @@ var Workspace = class {
let [clone, overlay_] = this._addWindowClone(win, false); let [clone, overlay_] = this._addWindowClone(win, false);
if (win._overviewHint) { if (win._overviewHint) {
let x = win._overviewHint.x - this.actor.x; let x = win._overviewHint.x - this.x;
let y = win._overviewHint.y - this.actor.y; let y = win._overviewHint.y - this.y;
let scale = win._overviewHint.scale; let scale = win._overviewHint.scale;
delete win._overviewHint; delete win._overviewHint;
@ -1777,10 +1796,6 @@ var Workspace = class {
} }
} }
destroy() {
this.actor.destroy();
}
_onDestroy() { _onDestroy() {
if (this._overviewHiddenId) { if (this._overviewHiddenId) {
Main.overview.disconnect(this._overviewHiddenId); Main.overview.disconnect(this._overviewHiddenId);
@ -1861,11 +1876,11 @@ var Workspace = class {
this._removeWindowClone(clone.metaWindow); this._removeWindowClone(clone.metaWindow);
}); });
this.actor.add_actor(clone); this.add_actor(clone);
overlay.connect('chrome-visible', () => { overlay.connect('chrome-visible', () => {
let focus = global.stage.key_focus; let focus = global.stage.key_focus;
if (focus == null || this.actor.contains(focus)) if (focus == null || this.contains(focus))
clone.grab_key_focus(); clone.grab_key_focus();
this._windowOverlays.forEach(o => { this._windowOverlays.forEach(o => {
@ -1949,7 +1964,7 @@ var Workspace = class {
} }
_getSpacingAndPadding() { _getSpacingAndPadding() {
let node = this.actor.get_theme_node(); let node = this.get_theme_node();
// Window grid spacing // Window grid spacing
let columnSpacing = node.get_length('-horizontal-spacing'); let columnSpacing = node.get_length('-horizontal-spacing');
@ -2047,5 +2062,4 @@ var Workspace = class {
return false; return false;
} }
}; });
Signals.addSignalMethods(Workspace.prototype);

View File

@ -2,7 +2,6 @@
/* exported WorkspaceThumbnail, ThumbnailsBox */ /* exported WorkspaceThumbnail, ThumbnailsBox */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background; const Background = imports.ui.background;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
@ -44,36 +43,40 @@ class PrimaryActorLayout extends Clutter.FixedLayout {
} }
}); });
var WindowClone = class { var WindowClone = GObject.registerClass({
constructor(realWindow) { GTypeName: 'WorkspaceThumbnail_WindowClone',
this.clone = new Clutter.Clone({ source: realWindow }); Signals: {
'drag-begin': {},
'drag-cancelled': {},
'drag-end': {},
'selected': { param_types: [GObject.TYPE_UINT] },
}
}, class WindowClone extends Clutter.Actor {
_init(realWindow) {
let clone = new Clutter.Clone({ source: realWindow });
super._init({
layout_manager: new PrimaryActorLayout(clone),
reactive: true
});
this._delegate = this;
/* Can't use a Shell.GenericContainer because of DND and reparenting... */ this.add_child(clone);
this.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
reactive: true });
this.actor._delegate = this;
this.actor.add_child(this.clone);
this.realWindow = realWindow; this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window; this.metaWindow = realWindow.meta_window;
this.clone._updateId = this.realWindow.connect('notify::position', clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this)); this._onPositionChanged.bind(this));
this.clone._destroyId = this.realWindow.connect('destroy', () => { clone._destroyId = this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything // First destroy the clone and then destroy everything
// This will ensure that we never see it in the _disconnectSignals loop // This will ensure that we never see it in the _disconnectSignals loop
this.clone.destroy(); clone.destroy();
this.destroy(); this.destroy();
}); });
this._onPositionChanged(); this._onPositionChanged();
this.actor.connect('button-release-event', this.connect('destroy', this._onDestroy.bind(this));
this._onButtonRelease.bind(this));
this.actor.connect('touch-event',
this._onTouchEvent.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this)); this._draggable = DND.makeDraggable(this,
this._draggable = DND.makeDraggable(this.actor,
{ restoreOnSuccess: true, { restoreOnSuccess: true,
dragActorMaxSize: Workspace.WINDOW_DND_SIZE, dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY }); dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
@ -124,13 +127,9 @@ var WindowClone = class {
let actualAbove = this.getActualStackAbove(); let actualAbove = this.getActualStackAbove();
if (actualAbove == null) if (actualAbove == null)
this.actor.lower_bottom(); this.lower_bottom();
else else
this.actor.raise(actualAbove); this.raise(actualAbove);
}
destroy() {
this.actor.destroy();
} }
addAttachedDialog(win) { addAttachedDialog(win) {
@ -147,7 +146,7 @@ var WindowClone = class {
clone._destroyId = realDialog.connect('destroy', () => { clone._destroyId = realDialog.connect('destroy', () => {
clone.destroy(); clone.destroy();
}); });
this.actor.add_child(clone); this.add_child(clone);
} }
_updateDialogPosition(realDialog, cloneDialog) { _updateDialogPosition(realDialog, cloneDialog) {
@ -159,11 +158,11 @@ var WindowClone = class {
} }
_onPositionChanged() { _onPositionChanged() {
this.actor.set_position(this.realWindow.x, this.realWindow.y); this.set_position(this.realWindow.x, this.realWindow.y);
} }
_disconnectSignals() { _disconnectSignals() {
this.actor.get_children().forEach(child => { this.get_children().forEach(child => {
let realWindow = child.source; let realWindow = child.source;
realWindow.disconnect(child._updateId); realWindow.disconnect(child._updateId);
@ -174,28 +173,30 @@ var WindowClone = class {
_onDestroy() { _onDestroy() {
this._disconnectSignals(); this._disconnectSignals();
this.actor._delegate = null; this._delegate = null;
if (this.inDrag) { if (this.inDrag) {
this.emit('drag-end'); this.emit('drag-end');
this.inDrag = false; this.inDrag = false;
} }
this.disconnectAll();
} }
_onButtonRelease(actor, event) { vfunc_button_press_event() {
this.emit('selected', event.get_time()); return Clutter.EVENT_STOP;
}
vfunc_button_release_event(buttonEvent) {
this.emit('selected', buttonEvent.time);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_onTouchEvent(actor, event) { vfunc_touch_event(touchEvent) {
if (event.type() != Clutter.EventType.TOUCH_END || if (touchEvent.type != Clutter.EventType.TOUCH_END ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence())) !global.display.is_pointer_emulating_sequence(touchEvent.sequence))
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
this.emit('selected', event.get_time()); this.emit('selected', touchEvent.time);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@ -214,18 +215,17 @@ var WindowClone = class {
// We may not have a parent if DnD completed successfully, in // We may not have a parent if DnD completed successfully, in
// which case our clone will shortly be destroyed and replaced // which case our clone will shortly be destroyed and replaced
// with a new one on the target workspace. // with a new one on the target workspace.
if (this.actor.get_parent() != null) { if (this.get_parent() != null) {
if (this._stackAbove == null) if (this._stackAbove == null)
this.actor.lower_bottom(); this.lower_bottom();
else else
this.actor.raise(this._stackAbove); this.raise(this._stackAbove);
} }
this.emit('drag-end'); this.emit('drag-end');
} }
}; });
Signals.addSignalMethods(WindowClone.prototype);
var ThumbnailState = { var ThumbnailState = {
@ -340,7 +340,7 @@ var WorkspaceThumbnail = GObject.registerClass({
clone.setStackAbove(this._bgManager.backgroundActor); clone.setStackAbove(this._bgManager.backgroundActor);
} else { } else {
let previousClone = this._windows[i - 1]; let previousClone = this._windows[i - 1];
clone.setStackAbove(previousClone.actor); clone.setStackAbove(previousClone);
} }
} }
} }
@ -522,15 +522,15 @@ var WorkspaceThumbnail = GObject.registerClass({
clone.connect('drag-end', () => { clone.connect('drag-end', () => {
Main.overview.endWindowDrag(clone.metaWindow); Main.overview.endWindowDrag(clone.metaWindow);
}); });
clone.actor.connect('destroy', () => { clone.connect('destroy', () => {
this._removeWindowClone(clone.metaWindow); this._removeWindowClone(clone.metaWindow);
}); });
this._contents.add_actor(clone.actor); this._contents.add_actor(clone);
if (this._windows.length == 0) if (this._windows.length == 0)
clone.setStackAbove(this._bgManager.backgroundActor); clone.setStackAbove(this._bgManager.backgroundActor);
else else
clone.setStackAbove(this._windows[this._windows.length - 1].actor); clone.setStackAbove(this._windows[this._windows.length - 1]);
this._windows.push(clone); this._windows.push(clone);
@ -668,10 +668,6 @@ var ThumbnailsBox = GObject.registerClass({
this._thumbnails = []; this._thumbnails = [];
this.connect('button-press-event', () => Clutter.EVENT_STOP);
this.connect('button-release-event', this._onButtonRelease.bind(this));
this.connect('touch-event', this._onTouchEvent.bind(this));
Main.overview.connect('showing', Main.overview.connect('showing',
this._createThumbnails.bind(this)); this._createThumbnails.bind(this));
Main.overview.connect('hidden', Main.overview.connect('hidden',
@ -728,17 +724,17 @@ var ThumbnailsBox = GObject.registerClass({
thumbnail.activate(time); thumbnail.activate(time);
} }
_onButtonRelease(actor, event) { vfunc_button_release_event(buttonEvent) {
let [stageX, stageY] = event.get_coords(); let { x, y } = buttonEvent;
this._activateThumbnailAtPoint(stageX, stageY, event.get_time()); this._activateThumbnailAtPoint(x, y, buttonEvent.time);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
_onTouchEvent(actor, event) { vfunc_touch_event(touchEvent) {
if (event.type() == Clutter.EventType.TOUCH_END && if (touchEvent.type == Clutter.EventType.TOUCH_END &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence())) { global.display.is_pointer_emulating_sequence(touchEvent.sequence)) {
let [stageX, stageY] = event.get_coords(); let { x, y } = touchEvent;
this._activateThumbnailAtPoint(stageX, stageY, event.get_time()); this._activateThumbnailAtPoint(x, y, touchEvent.time);
} }
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;

View File

@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WorkspacesView */ /* exported WorkspacesView, WorkspacesDisplay */
const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi; const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main; const Main = imports.ui.main;
const WindowManager = imports.ui.windowManager; const WindowManager = imports.ui.windowManager;
@ -17,15 +16,16 @@ var AnimationType = {
const MUTTER_SCHEMA = 'org.gnome.mutter'; const MUTTER_SCHEMA = 'org.gnome.mutter';
var WorkspacesViewBase = class { var WorkspacesViewBase = GObject.registerClass({
constructor(monitorIndex) { GTypeFlags: GObject.TypeFlags.ABSTRACT
this.actor = new St.Widget({ style_class: 'workspaces-view', }, class WorkspacesViewBase extends St.Widget {
reactive: true }); _init(monitorIndex) {
this.actor.connect('destroy', this._onDestroy.bind(this)); super._init({ style_class: 'workspaces-view', reactive: true });
global.focus_manager.add_group(this.actor); this.connect('destroy', this._onDestroy.bind(this));
global.focus_manager.add_group(this);
// The actor itself isn't a drop target, so we don't want to pick on its area // The actor itself isn't a drop target, so we don't want to pick on its area
this.actor.set_size(0, 0); this.set_size(0, 0);
this._monitorIndex = monitorIndex; this._monitorIndex = monitorIndex;
@ -60,10 +60,6 @@ var WorkspacesViewBase = class {
this._setReservedSlot(null); this._setReservedSlot(null);
} }
destroy() {
this.actor.destroy();
}
setFullGeometry(geom) { setFullGeometry(geom) {
this._fullGeometry = geom; this._fullGeometry = geom;
this._syncFullGeometry(); this._syncFullGeometry();
@ -73,13 +69,14 @@ var WorkspacesViewBase = class {
this._actualGeometry = geom; this._actualGeometry = geom;
this._syncActualGeometry(); this._syncActualGeometry();
} }
}; });
var WorkspacesView = class extends WorkspacesViewBase { var WorkspacesView = GObject.registerClass(
constructor(monitorIndex) { class WorkspacesView extends WorkspacesViewBase {
_init(monitorIndex) {
let workspaceManager = global.workspace_manager; let workspaceManager = global.workspace_manager;
super(monitorIndex); super._init(monitorIndex);
this._animating = false; // tweening this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling this._scrolling = false; // swipe-scrolling
@ -112,7 +109,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
this._overviewShownId = this._overviewShownId =
Main.overview.connect('shown', () => { Main.overview.connect('shown', () => {
this.actor.set_clip(this._fullGeometry.x, this._fullGeometry.y, this.set_clip(this._fullGeometry.x, this._fullGeometry.y,
this._fullGeometry.width, this._fullGeometry.height); this._fullGeometry.width, this._fullGeometry.height);
}); });
@ -153,7 +150,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
} }
animateFromOverview(animationType) { animateFromOverview(animationType) {
this.actor.remove_clip(); this.remove_clip();
for (let w = 0; w < this._workspaces.length; w++) { for (let w = 0; w < this._workspaces.length; w++) {
if (animationType == AnimationType.ZOOM) if (animationType == AnimationType.ZOOM)
@ -187,12 +184,12 @@ var WorkspacesView = class extends WorkspacesViewBase {
for (let w = 0; w < this._workspaces.length; w++) { for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w]; let workspace = this._workspaces[w];
workspace.actor.remove_all_transitions(); workspace.remove_all_transitions();
let params = {}; let params = {};
if (workspaceManager.layout_rows == -1) if (workspaceManager.layout_rows == -1)
params.y = (w - active) * this._fullGeometry.height; params.y = (w - active) * this._fullGeometry.height;
else if (this.actor.text_direction == Clutter.TextDirection.RTL) else if (this.text_direction == Clutter.TextDirection.RTL)
params.x = (active - w) * this._fullGeometry.width; params.x = (active - w) * this._fullGeometry.width;
else else
params.x = (w - active) * this._fullGeometry.width; params.x = (w - active) * this._fullGeometry.width;
@ -212,9 +209,9 @@ var WorkspacesView = class extends WorkspacesViewBase {
this._updateVisibility(); this._updateVisibility();
}; };
} }
workspace.actor.ease(easeParams); workspace.ease(easeParams);
} else { } else {
workspace.actor.set(params); workspace.set(params);
if (w == 0) if (w == 0)
this._updateVisibility(); this._updateVisibility();
} }
@ -228,12 +225,12 @@ var WorkspacesView = class extends WorkspacesViewBase {
for (let w = 0; w < this._workspaces.length; w++) { for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w]; let workspace = this._workspaces[w];
if (this._animating || this._scrolling || this._gestureActive) { if (this._animating || this._scrolling || this._gestureActive) {
workspace.actor.show(); workspace.show();
} else { } else {
if (this._inDrag) if (this._inDrag)
workspace.actor.visible = (Math.abs(w - active) <= 1); workspace.visible = (Math.abs(w - active) <= 1);
else else
workspace.actor.visible = (w == active); workspace.visible = (w == active);
} }
} }
} }
@ -263,7 +260,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
if (j >= this._workspaces.length) { /* added */ if (j >= this._workspaces.length) { /* added */
workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex); workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
this.actor.add_actor(workspace.actor); this.add_actor(workspace);
this._workspaces[j] = workspace; this._workspaces[j] = workspace;
} else { } else {
workspace = this._workspaces[j]; workspace = this._workspaces[j];
@ -355,8 +352,8 @@ var WorkspacesView = class extends WorkspacesViewBase {
let last = this._workspaces.length - 1; let last = this._workspaces.length - 1;
if (workspaceManager.layout_rows == -1) { if (workspaceManager.layout_rows == -1) {
let firstWorkspaceY = this._workspaces[0].actor.y; let firstWorkspaceY = this._workspaces[0].y;
let lastWorkspaceY = this._workspaces[last].actor.y; let lastWorkspaceY = this._workspaces[last].y;
let workspacesHeight = lastWorkspaceY - firstWorkspaceY; let workspacesHeight = lastWorkspaceY - firstWorkspaceY;
let currentY = firstWorkspaceY; let currentY = firstWorkspaceY;
@ -365,12 +362,12 @@ var WorkspacesView = class extends WorkspacesViewBase {
let dy = newY - currentY; let dy = newY - currentY;
for (let i = 0; i < this._workspaces.length; i++) { for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
this._workspaces[i].actor.y += dy; this._workspaces[i].y += dy;
} }
} else { } else {
let firstWorkspaceX = this._workspaces[0].actor.x; let firstWorkspaceX = this._workspaces[0].x;
let lastWorkspaceX = this._workspaces[last].actor.x; let lastWorkspaceX = this._workspaces[last].x;
let workspacesWidth = lastWorkspaceX - firstWorkspaceX; let workspacesWidth = lastWorkspaceX - firstWorkspaceX;
let currentX = firstWorkspaceX; let currentX = firstWorkspaceX;
@ -379,19 +376,19 @@ var WorkspacesView = class extends WorkspacesViewBase {
let dx = newX - currentX; let dx = newX - currentX;
for (let i = 0; i < this._workspaces.length; i++) { for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; this._workspaces[i].visible = Math.abs(i - adj.value) <= 1;
this._workspaces[i].actor.x += dx; this._workspaces[i].x += dx;
} }
} }
} }
}; });
Signals.addSignalMethods(WorkspacesView.prototype);
var ExtraWorkspaceView = class extends WorkspacesViewBase { var ExtraWorkspaceView = GObject.registerClass(
constructor(monitorIndex) { class ExtraWorkspaceView extends WorkspacesViewBase {
super(monitorIndex); _init(monitorIndex) {
super._init(monitorIndex);
this._workspace = new Workspace.Workspace(null, monitorIndex); this._workspace = new Workspace.Workspace(null, monitorIndex);
this.actor.add_actor(this._workspace.actor); this.add_actor(this._workspace);
} }
_setReservedSlot(window) { _setReservedSlot(window) {
@ -439,21 +436,13 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
endTouchGesture() { endTouchGesture() {
} }
};
var DelegateFocusNavigator = GObject.registerClass(
class DelegateFocusNavigator extends St.Widget {
vfunc_navigate_focus(from, direction) {
return this._delegate.navigateFocus(from, direction);
}
}); });
var WorkspacesDisplay = class { var WorkspacesDisplay = GObject.registerClass(
constructor() { class WorkspacesDisplay extends St.Widget {
this.actor = new DelegateFocusNavigator({ clip_to_allocation: true }); _init() {
this.actor._delegate = this; super._init({ clip_to_allocation: true });
this.actor.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this)); this.connect('notify::allocation', this._updateWorkspacesActualGeometry.bind(this));
this.actor.connect('parent-set', this._parentSet.bind(this));
let clickAction = new Clutter.ClickAction(); let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', action => { clickAction.connect('clicked', action => {
@ -467,7 +456,7 @@ var WorkspacesDisplay = class {
Main.overview.hide(); Main.overview.hide();
}); });
Main.overview.addAction(clickAction); Main.overview.addAction(clickAction);
this.actor.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); this.bind_property('mapped', clickAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER }); let panAction = new Clutter.PanAction({ threshold_trigger_edge: Clutter.GestureTriggerEdge.AFTER });
panAction.connect('pan', this._onPan.bind(this)); panAction.connect('pan', this._onPan.bind(this));
@ -490,7 +479,7 @@ var WorkspacesDisplay = class {
this._endSwipeScroll(); this._endSwipeScroll();
}); });
Main.overview.addAction(panAction); Main.overview.addAction(panAction);
this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE); this.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
let allowedModes = Shell.ActionMode.OVERVIEW; let allowedModes = Shell.ActionMode.OVERVIEW;
let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes); let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
@ -498,20 +487,15 @@ var WorkspacesDisplay = class {
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this)); switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
switchGesture.connect('cancel', this._endTouchGesture.bind(this)); switchGesture.connect('cancel', this._endTouchGesture.bind(this));
Main.overview.addAction(switchGesture); Main.overview.addAction(switchGesture);
this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE); this.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes); switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this)); switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this)); switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
switchGesture.connect('cancel', this._endTouchGesture.bind(this)); switchGesture.connect('cancel', this._endTouchGesture.bind(this));
this.actor.connect('notify::mapped', () => {
switchGesture.enabled = this.actor.mapped;
});
this._primaryIndex = Main.layoutManager.primaryIndex; this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = []; this._workspacesViews = [];
switchGesture.enabled = this.actor.mapped;
this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA }); this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
this._settings.connect('changed::workspaces-only-on-primary', this._settings.connect('changed::workspaces-only-on-primary',
@ -525,12 +509,12 @@ var WorkspacesDisplay = class {
this._fullGeometry = null; this._fullGeometry = null;
this.actor.connect('destroy', this._onDestroy.bind(this)); this.connect('destroy', this._onDestroy.bind(this));
} }
_onDestroy() { _onDestroy() {
if (this._notifyOpacityId) { if (this._notifyOpacityId) {
let parent = this.actor.get_parent(); let parent = this.get_parent();
if (parent) if (parent)
parent.disconnect(this._notifyOpacityId); parent.disconnect(this._notifyOpacityId);
this._notifyOpacityId = 0; this._notifyOpacityId = 0;
@ -546,11 +530,11 @@ var WorkspacesDisplay = class {
let [dist_, dx, dy] = action.get_motion_delta(0); let [dist_, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollAdjustment; let adjustment = this._scrollAdjustment;
if (global.workspace_manager.layout_rows == -1) if (global.workspace_manager.layout_rows == -1)
adjustment.value -= (dy / this.actor.height) * adjustment.page_size; adjustment.value -= (dy / this.height) * adjustment.page_size;
else if (this.actor.text_direction == Clutter.TextDirection.RTL) else if (this.text_direction == Clutter.TextDirection.RTL)
adjustment.value += (dx / this.actor.width) * adjustment.page_size; adjustment.value += (dx / this.width) * adjustment.page_size;
else else
adjustment.value -= (dx / this.actor.width) * adjustment.page_size; adjustment.value -= (dx / this.width) * adjustment.page_size;
return false; return false;
} }
@ -583,11 +567,11 @@ var WorkspacesDisplay = class {
let active = workspaceManager.get_active_workspace_index(); let active = workspaceManager.get_active_workspace_index();
let adjustment = this._scrollAdjustment; let adjustment = this._scrollAdjustment;
if (workspaceManager.layout_rows == -1) if (workspaceManager.layout_rows == -1)
adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size; adjustment.value = (active - yRel / this.height) * adjustment.page_size;
else if (this.actor.text_direction == Clutter.TextDirection.RTL) else if (this.text_direction == Clutter.TextDirection.RTL)
adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size; adjustment.value = (active + xRel / this.width) * adjustment.page_size;
else else
adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size; adjustment.value = (active - xRel / this.width) * adjustment.page_size;
} }
_onSwitchWorkspaceActivated(action, direction) { _onSwitchWorkspaceActivated(action, direction) {
@ -600,8 +584,8 @@ var WorkspacesDisplay = class {
this._endTouchGesture(); this._endTouchGesture();
} }
navigateFocus(from, direction) { vfunc_navigate_focus(from, direction) {
return this._getPrimaryView().actor.navigate_focus(from, direction, false); return this._getPrimaryView().navigate_focus(from, direction, false);
} }
show(fadeOnPrimary) { show(fadeOnPrimary) {
@ -677,7 +661,7 @@ var WorkspacesDisplay = class {
else else
view = new WorkspacesView(i); view = new WorkspacesView(i);
view.actor.connect('scroll-event', this._onScrollEvent.bind(this)); view.connect('scroll-event', this._onScrollEvent.bind(this));
if (i == this._primaryIndex) { if (i == this._primaryIndex) {
this._scrollAdjustment = view.scrollAdjustment; this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value', this._scrollAdjustment.connect('notify::value',
@ -685,13 +669,13 @@ var WorkspacesDisplay = class {
} }
// HACK: Avoid spurious allocation changes while updating views // HACK: Avoid spurious allocation changes while updating views
view.actor.hide(); view.hide();
this._workspacesViews.push(view); this._workspacesViews.push(view);
Main.layoutManager.overviewGroup.add_actor(view.actor); Main.layoutManager.overviewGroup.add_actor(view);
} }
this._workspacesViews.forEach(v => v.actor.show()); this._workspacesViews.forEach(v => v.show());
this._updateWorkspacesFullGeometry(); this._updateWorkspacesFullGeometry();
this._updateWorkspacesActualGeometry(); this._updateWorkspacesActualGeometry();
@ -728,7 +712,7 @@ var WorkspacesDisplay = class {
return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows(); return this._getPrimaryView().getActiveWorkspace().hasMaximizedWindows();
} }
_parentSet(actor, oldParent) { vfunc_parent_set(oldParent) {
if (oldParent && this._notifyOpacityId) if (oldParent && this._notifyOpacityId)
oldParent.disconnect(this._notifyOpacityId); oldParent.disconnect(this._notifyOpacityId);
this._notifyOpacityId = 0; this._notifyOpacityId = 0;
@ -738,20 +722,20 @@ var WorkspacesDisplay = class {
this._parentSetLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._parentSetLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._parentSetLater = 0; this._parentSetLater = 0;
let newParent = this.actor.get_parent(); let newParent = this.get_parent();
if (!newParent) if (!newParent)
return; return;
// This is kinda hackish - we want the primary view to // This is kinda hackish - we want the primary view to
// appear as parent of this.actor, though in reality it // appear as parent of this, though in reality it
// is added directly to Main.layoutManager.overviewGroup // is added directly to Main.layoutManager.overviewGroup
this._notifyOpacityId = newParent.connect('notify::opacity', () => { this._notifyOpacityId = newParent.connect('notify::opacity', () => {
let opacity = this.actor.get_parent().opacity; let opacity = this.get_parent().opacity;
let primaryView = this._getPrimaryView(); let primaryView = this._getPrimaryView();
if (!primaryView) if (!primaryView)
return; return;
primaryView.actor.opacity = opacity; primaryView.opacity = opacity;
primaryView.actor.visible = opacity != 0; primaryView.visible = opacity != 0;
}); });
}); });
} }
@ -779,8 +763,8 @@ var WorkspacesDisplay = class {
if (!this._workspacesViews.length) if (!this._workspacesViews.length)
return; return;
let [x, y] = this.actor.get_transformed_position(); let [x, y] = this.get_transformed_position();
let allocation = this.actor.allocation; let allocation = this.allocation;
let width = allocation.x2 - allocation.x1; let width = allocation.x2 - allocation.x1;
let height = allocation.y2 - allocation.y1; let height = allocation.y2 - allocation.y1;
let primaryGeometry = { x: x, y: y, width: width, height: height }; let primaryGeometry = { x: x, y: y, width: width, height: height };
@ -798,7 +782,7 @@ var WorkspacesDisplay = class {
} }
_onScrollEvent(actor, event) { _onScrollEvent(actor, event) {
if (!this.actor.mapped) if (!this.mapped)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (this._workspacesOnlyOnPrimary && if (this._workspacesOnlyOnPrimary &&
@ -829,7 +813,7 @@ var WorkspacesDisplay = class {
} }
_onKeyPressEvent(actor, event) { _onKeyPressEvent(actor, event) {
if (!this.actor.mapped) if (!this.mapped)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let workspaceManager = global.workspace_manager; let workspaceManager = global.workspace_manager;
let activeWs = workspaceManager.get_active_workspace(); let activeWs = workspaceManager.get_active_workspace();
@ -847,5 +831,4 @@ var WorkspacesDisplay = class {
Main.wm.actionMoveWorkspace(ws); Main.wm.actionMoveWorkspace(ws);
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
}; });
Signals.addSignalMethods(WorkspacesDisplay.prototype);

477
po/es.po

File diff suppressed because it is too large Load Diff

980
po/fa.po

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,15 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: video-subtitles master\n" "Project-Id-Version: video-subtitles master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2019-09-17 11:44+0000\n" "POT-Creation-Date: 2019-10-12 20:48+0000\n"
"PO-Revision-Date: 2019-09-26 16:19+0200\n" "PO-Revision-Date: 2019-10-17 15:53+0200\n"
"Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n" "Last-Translator: Fabio Tomat <f.t.public@gmail.com>\n"
"Language-Team: Friulian <fur@li.org>\n" "Language-Team: Friulian <fur@li.org>\n"
"Language: fur\n" "Language: fur\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.2.3\n" "X-Generator: Poedit 2.2.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: data/50-gnome-shell-system.xml:6 #: data/50-gnome-shell-system.xml:6
@ -467,7 +467,7 @@ msgid "Next"
msgstr "Indenant" msgstr "Indenant"
#: js/gdm/authPrompt.js:197 js/ui/shellMountOperation.js:396 #: js/gdm/authPrompt.js:197 js/ui/shellMountOperation.js:396
#: js/ui/unlockDialog.js:42 #: js/ui/unlockDialog.js:45
msgid "Unlock" msgid "Unlock"
msgstr "Sbloche" msgstr "Sbloche"
@ -497,8 +497,8 @@ msgstr "(p.e., utent o %s)"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (and don't even care of which one)
#: js/gdm/loginDialog.js:884 js/ui/components/networkAgent.js:247 #: js/gdm/loginDialog.js:884 js/ui/components/networkAgent.js:248
#: js/ui/components/networkAgent.js:267 js/ui/components/networkAgent.js:285 #: js/ui/components/networkAgent.js:268 js/ui/components/networkAgent.js:286
msgid "Username: " msgid "Username: "
msgstr "Non utent: " msgstr "Non utent: "
@ -760,32 +760,32 @@ msgstr "Dispès"
msgid "All" msgid "All"
msgstr "Dutis" msgstr "Dutis"
#: js/ui/appDisplay.js:1749 #: js/ui/appDisplay.js:1745
msgid "Rename" msgid "Rename"
msgstr "Cambie non" msgstr "Cambie non"
#. Translators: This is the heading of a list of open windows #. Translators: This is the heading of a list of open windows
#: js/ui/appDisplay.js:2397 js/ui/panel.js:76 #: js/ui/appDisplay.js:2418 js/ui/panel.js:76
msgid "Open Windows" msgid "Open Windows"
msgstr "Barcons vierts" msgstr "Barcons vierts"
#: js/ui/appDisplay.js:2416 js/ui/panel.js:83 #: js/ui/appDisplay.js:2437 js/ui/panel.js:83
msgid "New Window" msgid "New Window"
msgstr "Gnûf barcon" msgstr "Gnûf barcon"
#: js/ui/appDisplay.js:2428 #: js/ui/appDisplay.js:2449
msgid "Launch using Dedicated Graphics Card" msgid "Launch using Dedicated Graphics Card"
msgstr "Invie doprant une schede grafiche dedicade" msgstr "Invie doprant une schede grafiche dedicade"
#: js/ui/appDisplay.js:2457 js/ui/dash.js:239 #: js/ui/appDisplay.js:2478 js/ui/dash.js:239
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Gjave dai preferîts" msgstr "Gjave dai preferîts"
#: js/ui/appDisplay.js:2463 #: js/ui/appDisplay.js:2484
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Zonte tai preferîts" msgstr "Zonte tai preferîts"
#: js/ui/appDisplay.js:2473 js/ui/panel.js:94 #: js/ui/appDisplay.js:2494 js/ui/panel.js:94
msgid "Show Details" msgid "Show Details"
msgstr "Mostre Detais" msgstr "Mostre Detais"
@ -1017,34 +1017,34 @@ msgid "Connect"
msgstr "Conet" msgstr "Conet"
#. Cisco LEAP #. Cisco LEAP
#: js/ui/components/networkAgent.js:216 js/ui/components/networkAgent.js:228 #: js/ui/components/networkAgent.js:217 js/ui/components/networkAgent.js:229
#: js/ui/components/networkAgent.js:250 js/ui/components/networkAgent.js:269 #: js/ui/components/networkAgent.js:251 js/ui/components/networkAgent.js:270
#: js/ui/components/networkAgent.js:289 js/ui/components/networkAgent.js:299 #: js/ui/components/networkAgent.js:290 js/ui/components/networkAgent.js:300
msgid "Password: " msgid "Password: "
msgstr "Password: " msgstr "Password: "
#. static WEP #. static WEP
#: js/ui/components/networkAgent.js:221 #: js/ui/components/networkAgent.js:222
msgid "Key: " msgid "Key: "
msgstr "Clâf: " msgstr "Clâf: "
#: js/ui/components/networkAgent.js:253 js/ui/components/networkAgent.js:275 #: js/ui/components/networkAgent.js:254 js/ui/components/networkAgent.js:276
msgid "Private key password: " msgid "Private key password: "
msgstr "Password di clâf privade: " msgstr "Password di clâf privade: "
#: js/ui/components/networkAgent.js:273 #: js/ui/components/networkAgent.js:274
msgid "Identity: " msgid "Identity: "
msgstr "Identitât: " msgstr "Identitât: "
#: js/ui/components/networkAgent.js:287 #: js/ui/components/networkAgent.js:288
msgid "Service: " msgid "Service: "
msgstr "Servizi: " msgstr "Servizi: "
#: js/ui/components/networkAgent.js:316 js/ui/components/networkAgent.js:691 #: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:692
msgid "Authentication required by wireless network" msgid "Authentication required by wireless network"
msgstr "La rêt cence fîl e domande autenticazion" msgstr "La rêt cence fîl e domande autenticazion"
#: js/ui/components/networkAgent.js:317 js/ui/components/networkAgent.js:692 #: js/ui/components/networkAgent.js:318 js/ui/components/networkAgent.js:693
#, javascript-format #, javascript-format
msgid "" msgid ""
"Passwords or encryption keys are required to access the wireless network " "Passwords or encryption keys are required to access the wireless network "
@ -1053,41 +1053,41 @@ msgstr ""
"Si scugne meti une password o une clâf di cifradure par jentrâ te rêt cence " "Si scugne meti une password o une clâf di cifradure par jentrâ te rêt cence "
"fîl \"%s\"." "fîl \"%s\"."
#: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:696 #: js/ui/components/networkAgent.js:322 js/ui/components/networkAgent.js:697
msgid "Wired 802.1X authentication" msgid "Wired 802.1X authentication"
msgstr "Autenticazion vie fîl 802.1X" msgstr "Autenticazion vie fîl 802.1X"
#: js/ui/components/networkAgent.js:323 #: js/ui/components/networkAgent.js:324
msgid "Network name: " msgid "Network name: "
msgstr "Non rêt: " msgstr "Non rêt: "
#: js/ui/components/networkAgent.js:328 js/ui/components/networkAgent.js:700 #: js/ui/components/networkAgent.js:329 js/ui/components/networkAgent.js:701
msgid "DSL authentication" msgid "DSL authentication"
msgstr "Autenticazion DSL" msgstr "Autenticazion DSL"
#: js/ui/components/networkAgent.js:335 js/ui/components/networkAgent.js:705 #: js/ui/components/networkAgent.js:336 js/ui/components/networkAgent.js:706
msgid "PIN code required" msgid "PIN code required"
msgstr "Si pretint un codiç PIN" msgstr "Si pretint un codiç PIN"
#: js/ui/components/networkAgent.js:336 js/ui/components/networkAgent.js:706 #: js/ui/components/networkAgent.js:337 js/ui/components/networkAgent.js:707
msgid "PIN code is needed for the mobile broadband device" msgid "PIN code is needed for the mobile broadband device"
msgstr "Si scugne meti un codiç PIN pal dispositîf a bande largje mobil" msgstr "Si scugne meti un codiç PIN pal dispositîf a bande largje mobil"
#: js/ui/components/networkAgent.js:337 #: js/ui/components/networkAgent.js:338
msgid "PIN: " msgid "PIN: "
msgstr "PIN: " msgstr "PIN: "
#: js/ui/components/networkAgent.js:344 js/ui/components/networkAgent.js:712 #: js/ui/components/networkAgent.js:345 js/ui/components/networkAgent.js:713
msgid "Mobile broadband network password" msgid "Mobile broadband network password"
msgstr "Passowrd rêt mobil a bande largje" msgstr "Passowrd rêt mobil a bande largje"
#: js/ui/components/networkAgent.js:345 js/ui/components/networkAgent.js:697 #: js/ui/components/networkAgent.js:346 js/ui/components/networkAgent.js:698
#: js/ui/components/networkAgent.js:701 js/ui/components/networkAgent.js:713 #: js/ui/components/networkAgent.js:702 js/ui/components/networkAgent.js:714
#, javascript-format #, javascript-format
msgid "A password is required to connect to “%s”." msgid "A password is required to connect to “%s”."
msgstr "A covente une password par tacâsi a '%s'." msgstr "A covente une password par tacâsi a '%s'."
#: js/ui/components/networkAgent.js:680 js/ui/status/network.js:1675 #: js/ui/components/networkAgent.js:681 js/ui/status/network.js:1675
msgid "Network Manager" msgid "Network Manager"
msgstr "Ministradôr di rêt" msgstr "Ministradôr di rêt"
@ -1475,6 +1475,26 @@ msgstr "Viôt sorzint"
msgid "Web Page" msgid "Web Page"
msgstr "Pagjine Web" msgstr "Pagjine Web"
#: js/ui/main.js:267
msgid "Logged in as a privileged user"
msgstr "Jentre come utent privilegjât"
#: js/ui/main.js:268
msgid ""
"Running a session as a privileged user should be avoided for security "
"reasons. If possible, you should log in as a normal user."
msgstr ""
"Si varès di evitâ di eseguî une session come utent privilegjât par resons di "
"sigurece. Se pussibil, tu varessis di jentrâ come utent normâl."
#: js/ui/main.js:274
msgid "Screen Lock disabled"
msgstr "Bloc dal schermi disabilitât"
#: js/ui/main.js:275
msgid "Screen Locking requires the GNOME display manager."
msgstr "Il bloc dal schermi al à bisugne dal gjestôr dai visôrs di GNOME."
#: js/ui/messageTray.js:1465 #: js/ui/messageTray.js:1465
msgid "System Information" msgid "System Information"
msgstr "Informazion di sisteme" msgstr "Informazion di sisteme"
@ -2219,11 +2239,11 @@ msgstr "Dome esterni"
msgid "Built-in Only" msgid "Built-in Only"
msgstr "Dome incorporât" msgstr "Dome incorporât"
#: js/ui/unlockDialog.js:50 #: js/ui/unlockDialog.js:53
msgid "Log in as another user" msgid "Log in as another user"
msgstr "Jentre come altri utent" msgstr "Jentre come altri utent"
#: js/ui/unlockDialog.js:67 #: js/ui/unlockDialog.js:70
msgid "Unlock Window" msgid "Unlock Window"
msgstr "Sbloche barcon" msgstr "Sbloche barcon"
@ -2266,7 +2286,7 @@ msgstr[1] ""
#. Translators: This represents the size of a window. The first number is #. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height. #. * the width of the window and the second is the height.
#: js/ui/windowManager.js:683 #: js/ui/windowManager.js:686
#, javascript-format #, javascript-format
msgid "%d × %d" msgid "%d × %d"
msgstr "%d × %d" msgstr "%d × %d"
@ -2604,7 +2624,7 @@ msgstr "Comants:"
msgid "Print help" msgid "Print help"
msgstr "Stampe jutori" msgstr "Stampe jutori"
#: src/extensions-tool/main.c:248 src/main.c:468 #: src/extensions-tool/main.c:248 src/main.c:460
msgid "Print version" msgid "Print version"
msgstr "Stampe version" msgstr "Stampe version"
@ -2653,15 +2673,15 @@ msgstr "Instale complès di estensions"
msgid "Use “%s” to get detailed help.\n" msgid "Use “%s” to get detailed help.\n"
msgstr "Dopre “%s” par vê un jutori detaiât.\n" msgstr "Dopre “%s” par vê un jutori detaiât.\n"
#: src/main.c:474 #: src/main.c:466
msgid "Mode used by GDM for login screen" msgid "Mode used by GDM for login screen"
msgstr "Modalitât doprade da GDM pe videade di acès" msgstr "Modalitât doprade da GDM pe videade di acès"
#: src/main.c:480 #: src/main.c:472
msgid "Use a specific mode, e.g. “gdm” for login screen" msgid "Use a specific mode, e.g. “gdm” for login screen"
msgstr "Dopre une modalitât specifiche, par esempli “gdm” pe videade di acès" msgstr "Dopre une modalitât specifiche, par esempli “gdm” pe videade di acès"
#: src/main.c:486 #: src/main.c:478
msgid "List possible modes" msgid "List possible modes"
msgstr "Liste modalitâts pussibilis" msgstr "Liste modalitâts pussibilis"

524
po/hr.po

File diff suppressed because it is too large Load Diff

View File

@ -509,7 +509,7 @@ shell_app_activate_full (ShellApp *app,
case SHELL_APP_STATE_STOPPED: case SHELL_APP_STATE_STOPPED:
{ {
GError *error = NULL; GError *error = NULL;
if (!shell_app_launch (app, timestamp, workspace, FALSE, &error)) if (!shell_app_launch (app, timestamp, workspace, SHELL_APP_GPU_SELECTION_AUTO, &error))
{ {
char *msg; char *msg;
msg = g_strdup_printf (_("Failed to launch “%s”"), shell_app_get_name (app)); msg = g_strdup_printf (_("Failed to launch “%s”"), shell_app_get_name (app));
@ -584,7 +584,7 @@ shell_app_open_new_window (ShellApp *app,
* instance (Firefox). There are a few less-sensical cases such * instance (Firefox). There are a few less-sensical cases such
* as say Pidgin. * as say Pidgin.
*/ */
shell_app_launch (app, 0, workspace, FALSE, NULL); shell_app_launch (app, 0, workspace, SHELL_APP_GPU_SELECTION_AUTO, NULL);
} }
/** /**
@ -1255,18 +1255,36 @@ wait_pid (GDesktopAppInfo *appinfo,
g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL); g_child_watch_add (pid, (GChildWatchFunc) g_spawn_close_pid, NULL);
} }
static gboolean
get_with_discrete_gpu (ShellApp *app,
ShellAppGpuSelection discrete_gpu)
{
switch (discrete_gpu)
{
case SHELL_APP_GPU_SELECTION_INTEGRATED:
return FALSE;
case SHELL_APP_GPU_SELECTION_DISCRETE:
return TRUE;
case SHELL_APP_GPU_SELECTION_AUTO:
return g_desktop_app_info_get_boolean (app->info, "PreferRunOnDiscreteGPU") ||
g_desktop_app_info_get_boolean (app->info, "X-KDE-RunOnDiscreteGpu");
default:
g_assert_not_reached();
}
}
/** /**
* shell_app_launch: * shell_app_launch:
* @timestamp: Event timestamp, or 0 for current event timestamp * @timestamp: Event timestamp, or 0 for current event timestamp
* @workspace: Start on this workspace, or -1 for default * @workspace: Start on this workspace, or -1 for default
* @discrete_gpu: Whether to start on the discrete GPU * @discrete_gpu: the preferred GPU to launch the application on.
* @error: A #GError * @error: A #GError
*/ */
gboolean gboolean
shell_app_launch (ShellApp *app, shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
int workspace, int workspace,
gboolean discrete_gpu, ShellAppGpuSelection discrete_gpu,
GError **error) GError **error)
{ {
ShellGlobal *global; ShellGlobal *global;
@ -1289,8 +1307,13 @@ shell_app_launch (ShellApp *app,
global = shell_global_get (); global = shell_global_get ();
context = shell_global_create_app_launch_context (global, timestamp, workspace); context = shell_global_create_app_launch_context (global, timestamp, workspace);
if (discrete_gpu) /* FIXME: this should probably check whether we're on a dual-GPU system */
if (get_with_discrete_gpu (app, discrete_gpu))
{
g_app_launch_context_setenv (context, "DRI_PRIME", "1"); g_app_launch_context_setenv (context, "DRI_PRIME", "1");
g_app_launch_context_setenv (context, "__NV_PRIME_RENDER_OFFLOAD", "1");
g_app_launch_context_setenv (context, "__GLX_VENDOR_LIBRARY_NAME", "nvidia");
}
/* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn /* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn
* codepath. The shell's open file descriptors should be marked CLOEXEC * codepath. The shell's open file descriptors should be marked CLOEXEC

View File

@ -18,6 +18,12 @@ typedef enum {
SHELL_APP_STATE_RUNNING SHELL_APP_STATE_RUNNING
} ShellAppState; } ShellAppState;
typedef enum {
SHELL_APP_GPU_SELECTION_AUTO = -1,
SHELL_APP_GPU_SELECTION_INTEGRATED = 0,
SHELL_APP_GPU_SELECTION_DISCRETE = 1
} ShellAppGpuSelection;
const char *shell_app_get_id (ShellApp *app); const char *shell_app_get_id (ShellApp *app);
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app); GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
@ -54,7 +60,7 @@ gboolean shell_app_is_on_workspace (ShellApp *app, MetaWorkspace *workspace);
gboolean shell_app_launch (ShellApp *app, gboolean shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
int workspace, int workspace,
gboolean discrete_gpu, ShellAppGpuSelection discrete_gpu,
GError **error); GError **error);
void shell_app_launch_action (ShellApp *app, void shell_app_launch_action (ShellApp *app,

View File

@ -457,7 +457,6 @@ grab_window_screenshot (ClutterActor *stage,
ClutterActor *window_actor; ClutterActor *window_actor;
gfloat actor_x, actor_y; gfloat actor_x, actor_y;
MetaRectangle rect; MetaRectangle rect;
cairo_rectangle_int_t clip;
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window)); window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
clutter_actor_get_position (window_actor, &actor_x, &actor_y); clutter_actor_get_position (window_actor, &actor_x, &actor_y);
@ -467,16 +466,10 @@ grab_window_screenshot (ClutterActor *stage,
if (!priv->include_frame) if (!priv->include_frame)
meta_window_frame_rect_to_client_rect (window, &rect, &rect); meta_window_frame_rect_to_client_rect (window, &rect, &rect);
priv->screenshot_area.x = rect.x; priv->screenshot_area = rect;
priv->screenshot_area.y = rect.y;
clip.x = rect.x - (gint) actor_x;
clip.y = rect.y - (gint) actor_y;
clip.width = priv->screenshot_area.width = rect.width;
clip.height = priv->screenshot_area.height = rect.height;
priv->image = meta_window_actor_get_image (META_WINDOW_ACTOR (window_actor), priv->image = meta_window_actor_get_image (META_WINDOW_ACTOR (window_actor),
&clip); NULL);
priv->datetime = g_date_time_new_now_local (); priv->datetime = g_date_time_new_now_local ();
if (priv->include_cursor) if (priv->include_cursor)

View File

@ -35,8 +35,7 @@
#endif #endif
static void static void
stop_pick (ClutterActor *actor, stop_pick (ClutterActor *actor)
const ClutterColor *color)
{ {
g_signal_stop_emission_by_name (actor, "pick"); g_signal_stop_emission_by_name (actor, "pick");
} }
@ -97,7 +96,7 @@ shell_util_get_transformed_allocation (ClutterActor *actor,
/* Code adapted from clutter-actor.c: /* Code adapted from clutter-actor.c:
* Copyright 2006, 2007, 2008 OpenedHand Ltd * Copyright 2006, 2007, 2008 OpenedHand Ltd
*/ */
ClutterVertex v[4]; graphene_point3d_t v[4];
gfloat x_min, x_max, y_min, y_max; gfloat x_min, x_max, y_min, y_max;
guint i; guint i;

View File

@ -443,8 +443,7 @@ st_box_layout_paint (ClutterActor *actor)
} }
static void static void
st_box_layout_pick (ClutterActor *actor, st_box_layout_pick (ClutterActor *actor)
const ClutterColor *color)
{ {
StBoxLayout *self = ST_BOX_LAYOUT (actor); StBoxLayout *self = ST_BOX_LAYOUT (actor);
StBoxLayoutPrivate *priv = self->priv; StBoxLayoutPrivate *priv = self->priv;
@ -462,7 +461,7 @@ st_box_layout_pick (ClutterActor *actor,
cogl_framebuffer_translate (fb, (int)x, (int)y, 0); cogl_framebuffer_translate (fb, (int)x, (int)y, 0);
} }
CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, color); CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor);
if (x != 0 || y != 0) if (x != 0 || y != 0)
{ {
@ -490,7 +489,7 @@ st_box_layout_pick (ClutterActor *actor,
for (child = clutter_actor_get_first_child (actor); for (child = clutter_actor_get_first_child (actor);
child != NULL; child != NULL;
child = clutter_actor_get_next_sibling (child)) child = clutter_actor_get_next_sibling (child))
clutter_actor_paint (child); clutter_actor_pick (child);
if (priv->hadjustment || priv->vadjustment) if (priv->hadjustment || priv->vadjustment)
cogl_framebuffer_pop_clip (fb); cogl_framebuffer_pop_clip (fb);
@ -506,7 +505,7 @@ st_box_layout_get_paint_volume (ClutterActor *actor,
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
ClutterActorBox allocation_box; ClutterActorBox allocation_box;
ClutterActorBox content_box; ClutterActorBox content_box;
ClutterVertex origin; graphene_point3d_t origin;
/* Setting the paint volume does not make sense when we don't have any allocation */ /* Setting the paint volume does not make sense when we don't have any allocation */
if (!clutter_actor_has_allocation (actor)) if (!clutter_actor_has_allocation (actor))

View File

@ -40,7 +40,7 @@ struct _StButtonClass
void (* transition) (StButton *button); void (* transition) (StButton *button);
/* signals */ /* signals */
void (* clicked) (StButton *button); void (* clicked) (StButton *button, int clicked_button);
}; };
StWidget *st_button_new (void); StWidget *st_button_new (void);

View File

@ -60,7 +60,7 @@ struct _StIconPrivate
CoglPipeline *shadow_pipeline; CoglPipeline *shadow_pipeline;
StShadow *shadow_spec; StShadow *shadow_spec;
ClutterSize shadow_size; graphene_size_t shadow_size;
}; };
G_DEFINE_TYPE_WITH_PRIVATE (StIcon, st_icon, ST_TYPE_WIDGET) G_DEFINE_TYPE_WITH_PRIVATE (StIcon, st_icon, ST_TYPE_WIDGET)
@ -290,7 +290,7 @@ st_icon_clear_shadow_pipeline (StIcon *icon)
StIconPrivate *priv = icon->priv; StIconPrivate *priv = icon->priv;
g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref); g_clear_pointer (&priv->shadow_pipeline, cogl_object_unref);
clutter_size_init (&priv->shadow_size, 0, 0); graphene_size_init (&priv->shadow_size, 0, 0);
} }
static void static void
@ -317,7 +317,7 @@ st_icon_update_shadow_pipeline (StIcon *icon)
priv->icon_texture); priv->icon_texture);
if (priv->shadow_pipeline) if (priv->shadow_pipeline)
clutter_size_init (&priv->shadow_size, width, height); graphene_size_init (&priv->shadow_size, width, height);
} }
} }
} }

View File

@ -100,7 +100,7 @@ st_scroll_view_fade_paint_target (ClutterOffscreenEffect *effect)
float fade_area_topleft[2]; float fade_area_topleft[2];
float fade_area_bottomright[2]; float fade_area_bottomright[2];
ClutterVertex verts[4]; graphene_point3d_t verts[4];
clutter_actor_get_paint_box (self->actor, &paint_box); clutter_actor_get_paint_box (self->actor, &paint_box);
clutter_actor_get_abs_allocation_vertices (self->actor, verts); clutter_actor_get_abs_allocation_vertices (self->actor, verts);

View File

@ -294,20 +294,19 @@ st_scroll_view_paint (ClutterActor *actor)
} }
static void static void
st_scroll_view_pick (ClutterActor *actor, st_scroll_view_pick (ClutterActor *actor)
const ClutterColor *color)
{ {
StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv; StScrollViewPrivate *priv = ST_SCROLL_VIEW (actor)->priv;
/* Chain up so we get a bounding box pained (if we are reactive) */ /* Chain up so we get a bounding box pained (if we are reactive) */
CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor, color); CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor);
if (priv->child) if (priv->child)
clutter_actor_paint (priv->child); clutter_actor_pick (priv->child);
if (priv->hscrollbar_visible) if (priv->hscrollbar_visible)
clutter_actor_paint (priv->hscroll); clutter_actor_pick (priv->hscroll);
if (priv->vscrollbar_visible) if (priv->vscrollbar_visible)
clutter_actor_paint (priv->vscroll); clutter_actor_pick (priv->vscroll);
} }
static gboolean static gboolean
@ -963,23 +962,6 @@ st_scroll_view_remove (ClutterContainer *container,
} }
} }
static void
st_scroll_view_foreach_with_internals (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
StScrollViewPrivate *priv = ST_SCROLL_VIEW (container)->priv;
if (priv->child != NULL)
callback (priv->child, user_data);
if (priv->hscroll != NULL)
callback (priv->hscroll, user_data);
if (priv->vscroll != NULL)
callback (priv->vscroll, user_data);
}
static void static void
clutter_container_iface_init (ClutterContainerIface *iface) clutter_container_iface_init (ClutterContainerIface *iface)
{ {
@ -991,7 +973,6 @@ clutter_container_iface_init (ClutterContainerIface *iface)
iface->add = st_scroll_view_add; iface->add = st_scroll_view_add;
iface->remove = st_scroll_view_remove; iface->remove = st_scroll_view_remove;
iface->foreach_with_internals = st_scroll_view_foreach_with_internals;
} }
StWidget * StWidget *

View File

@ -762,7 +762,7 @@ st_widget_get_paint_volume (ClutterActor *self,
ClutterActorBox paint_box, alloc_box; ClutterActorBox paint_box, alloc_box;
StThemeNode *theme_node; StThemeNode *theme_node;
StWidgetPrivate *priv; StWidgetPrivate *priv;
ClutterVertex origin; graphene_point3d_t origin;
/* Setting the paint volume does not make sense when we don't have any allocation */ /* Setting the paint volume does not make sense when we don't have any allocation */
if (!clutter_actor_has_allocation (self)) if (!clutter_actor_has_allocation (self))
@ -2062,7 +2062,7 @@ filter_by_position (GList *children,
StDirectionType direction) StDirectionType direction)
{ {
ClutterActorBox cbox; ClutterActorBox cbox;
ClutterVertex abs_vertices[4]; graphene_point3d_t abs_vertices[4];
GList *l, *ret; GList *l, *ret;
ClutterActor *child; ClutterActor *child;
@ -2128,7 +2128,7 @@ get_distance (ClutterActor *actor,
{ {
int ax, ay, bx, by, dx, dy; int ax, ay, bx, by, dx, dy;
ClutterActorBox abox; ClutterActorBox abox;
ClutterVertex abs_vertices[4]; graphene_point3d_t abs_vertices[4];
clutter_actor_get_abs_allocation_vertices (actor, abs_vertices); clutter_actor_get_abs_allocation_vertices (actor, abs_vertices);
clutter_actor_box_from_vertices (&abox, abs_vertices); clutter_actor_box_from_vertices (&abox, abs_vertices);
@ -2232,7 +2232,7 @@ st_widget_real_navigate_focus (StWidget *widget,
else /* direction is an arrow key, not tab */ else /* direction is an arrow key, not tab */
{ {
ClutterActorBox sort_box; ClutterActorBox sort_box;
ClutterVertex abs_vertices[4]; graphene_point3d_t abs_vertices[4];
/* Compute the allocation box of the previous focused actor. If there /* Compute the allocation box of the previous focused actor. If there
* was no previous focus, use the coordinates of the appropriate edge of * was no previous focus, use the coordinates of the appropriate edge of

View File

@ -36,16 +36,16 @@ function test() {
obin.connect_after('paint', actor => { obin.connect_after('paint', actor => {
Cogl.set_source_color4f(0, 1, 0, 1); Cogl.set_source_color4f(0, 1, 0, 1);
let geom = actor.get_allocation_geometry(); let alloc = actor.get_allocation_box();
let width = 3; let width = 3;
// clockwise order // clockwise order
Cogl.rectangle(0, 0, geom.width, width); Cogl.rectangle(0, 0, alloc.get_width(), width);
Cogl.rectangle(geom.width - width, width, Cogl.rectangle(alloc.get_width() - width, width,
geom.width, geom.height); alloc.get_width(), alloc.get_height());
Cogl.rectangle(0, geom.height, Cogl.rectangle(0, alloc.get_height(),
geom.width - width, geom.height - width); alloc.get_width() - width, alloc.get_height() - width);
Cogl.rectangle(0, geom.height - width, Cogl.rectangle(0, alloc.get_height() - width,
width, width); width, width);
}); });
tbox.add(obin); tbox.add(obin);

View File

@ -17,7 +17,7 @@ function test() {
// Calendar can only be imported after Environment.init() // Calendar can only be imported after Environment.init()
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
let calendar = new Calendar.Calendar(); let calendar = new Calendar.Calendar();
vbox.add(calendar.actor, vbox.add(calendar,
{ expand: true, { expand: true,
x_fill: false, x_align: St.Align.MIDDLE, x_fill: false, x_align: St.Align.MIDDLE,
y_fill: false, y_align: St.Align.START }); y_fill: false, y_align: St.Align.START });