Compare commits

..

140 Commits

Author SHA1 Message Date
Bastien Nocera
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
Bastien Nocera
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
Bastien Nocera
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
Bastien Nocera
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
Philip Chimento
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
Florian Müllner
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
Georges Basile Stavracas Neto
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
Danial Behzadi
80680803aa Update Persian translation 2019-10-19 15:16:39 +00:00
Kalev Lember
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
Georges Basile Stavracas Neto
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
Georges Basile Stavracas Neto
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
Georges Basile Stavracas Neto
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
Florian Müllner
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
Fabio Tomat
6f7e5976e2 Update Friulian translation 2019-10-17 13:54:18 +00:00
Goran Vidović
29543f369f Update Croatian translation 2019-10-17 12:08:58 +00:00
Robert Mader
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
Andrew Watson
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
Florian Müllner
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
Florian Müllner
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
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
Florian Müllner
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
Daniel van Vugt
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
Georges Basile Stavracas Neto
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
Georges Basile Stavracas Neto
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
Georges Basile Stavracas Neto
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
Florian Müllner
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
Marco Trevisan (Treviño)
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
Marco Trevisan (Treviño)
d0d1845bb6 search: Rename SearchResults to SearchResultsView
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/765
2019-10-16 11:52:55 +02:00
Robert Mader
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
Marco Trevisan (Treviño)
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
Florian Müllner
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
Daniel Mustieles
f78136182f Updated Spanish translation 2019-10-14 09:15:23 +02:00
Florian Müllner
11d46cf5b3 Bump version to 3.35.1
Update NEWS.
2019-10-12 22:38:36 +02:00
Matthias Clasen
7326e7a9fa main: Show a warning when gdm is missing
If we are not running under gdm, some functionaliy (such as
the lock screen) does not work, and we should inform the
user about this.

https://bugzilla.gnome.org/show_bug.cgi?id=701212
2019-10-12 20:36:38 +00:00
Matthias Clasen
a65164e540 main: Show a warning when running as root
gnome-session used to show a dialog in this case, but a
notification is more natural nowadays. Doing it in gnome-shell
avoids complicated synchronization between gnome-session and
gnome-shell.

https://bugzilla.gnome.org/show_bug.cgi?id=701212
2019-10-12 20:36:38 +00:00
Marco Trevisan (Treviño)
279024afc2 js: Replace Tweener time leftovers with ease duration
In some places we were not properly animating the actors as still using the
non-existent 'time' property instead of 'duration'

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/758
2019-10-10 02:14:28 +02:00
Marco Trevisan (Treviño)
ef8000d2e6 animation: Finish porting to clutter transitions
Animation when stopping the spinner was still using the old
parameters that not working, although if silently failing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/758
2019-10-10 02:08:59 +02:00
Florian Müllner
986600ab31 Bump version to 3.34.1
Update NEWS.
2019-10-09 02:50:29 +02:00
Florian Müllner
3d39b32a0b Revert "windowManager: Use new reorder_workspace() API"
It's too easy to break, so revert to the old code until we
figure out a fix.

This reverts commit ff9bb5399b.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1497
2019-10-08 21:11:19 +02:00
Florian Müllner
6205d5eb27 windowManager: Handle reordering of workspaces
MetaWorkspaceManager gained the ability to reorder workspaces, so make
sure to pick up the new order when that happens.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1497
2019-10-08 21:11:19 +02:00
Carlos Garnacho
a722b4c51d ibusCandidatePopup: Use an internal actor to track IM focus position
We share this actor with other shell menus, which arguably track a different
"cursor" as we care of the caret/anchor text positions, and menus care about
pointer click coordinates.

Use a standalone actor for this, so popups/IM are entirely decoupled.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1571
2019-10-08 17:12:43 +00:00
Marco Trevisan (Treviño)
31fe517007 shell-global: Ignore modal operations if we have no compositor
Modal dialog actions might be triggered during display closing, and in such
cases we should just ignore the requests.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/746
2019-10-08 17:51:52 +02:00
Marco Trevisan (Treviño)
31d915a38a shell-global: Disconnect from stage events on X11 display close
As per GNOME/mutter!385 [1], the compositor is finalized an its pointer
cleared on display close.

However, since the shell reacts to such events instead of controlling them,
when the shell is stopping or restarting and its display closing, the shell
stage destroys its children after the display closing is finished and during
this process the focus is unset, causing focus_actor_changed() to be called
and thus calls to meta_stage_is_focused() which deferences the now NULL
compositor, leading to a crash on shutdown.

Since after this point we should just ignore any stage event, disconnect
from them all.

[1] https://gitlab.gnome.org/GNOME/mutter/merge_requests/385

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/746
2019-10-08 17:49:30 +02:00
Florian Müllner
e00878ab75 shellDBus: Don't assume devices have a node
Clutter.InputDevice.get_device_node() may return null. Handle that
case when building the 'AcceleratorActivated' vardict parameter.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1641
2019-10-07 21:24:13 +00:00
Lubomir Rintel
3b5675b79a networkAgent: add support for SAE secrets
NetworkManager supports "WPA3 Personal" networks for some time now, they
use the SAE authentication. Add support for it alongside other
password-based mechanisms.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/751
2019-10-07 22:44:39 +02:00
Alan Mortensen
ee97512bcc Updated Danish translation 2019-10-06 18:16:32 +02:00
Iain Lane
085531b43d main, util: Notify systemd once we are fully initialised
If graphical applications want to start from systemd units, they need to
start after we're properly ready to display them. This is particularly
important under X where `_GTK_FRAME_EXTENTS` and other xprops are needed
to have the right theming.

We're doing this in an idle callback so that the dynamic starting of
`gnome-session-x11-service.target` (which launches `gsd-xsettings`) as
the result of a signal emission happens before us signalling we're ready
for later things to start.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/750
2019-10-04 15:40:05 +00:00
Ryuta Fujii
9e8b97d474 Update Japanese translation 2019-10-04 14:54:06 +00:00
Ryuta Fujii
a3a7953704 Update Japanese translation 2019-10-04 14:52:49 +00:00
Marco Trevisan (Treviño)
92c0171aeb lightbox: Show the actor before easing it
As per clutter optimizations in should_skip_implicit_transition() any
transition will be ignored if applied to an actor with unmapped clones.

Since we initialize the lightbox as hidden, when we use it standalone (as it
happens for the long fade in screenShield) the transition will be ignored.
This causes the lockscreen fade-out after the idle delay not to work, but
instead to have an apparently locked system that is instead not locked at
all.

So, just ensure that the lightbox actor is visible before applying to it any
transition.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1683
2019-10-03 15:26:13 +02:00
Marco Trevisan (Treviño)
6a6d66486d ibusManager: Cancel the preload engines timeout on clear
This is created when preloading but never cancelled if ibus disappears

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/743
2019-10-02 18:19:53 +02:00
Marco Trevisan (Treviño)
1cc766d636 ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.

In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-10-02 18:19:53 +02:00
Takao Fujiwara
60cad01880 inputMethod: Do not change IBus.Capabilite by focus events
gnome-shell calls ibus_input_context_focus_in() in InputMethod.focus_in()
but the event is not actually forwarded to panels and engines in GNOME
Wayland because gnome-shell changes IBus.Capabilite by focus events and
disables IBus.Capabilite.FOCUS when ibus_input_context_focus_in() is called.

IBus.Capabilite is assumed a fixed value per input context in the
first place and it should not be changed by focus events.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/573
2019-10-02 08:40:27 +00:00
Ask Hjorth Larsen
63c9a6efd0 Updated Danish translation 2019-10-02 05:35:36 +02:00
Marek Černocký
1d1b42756f Updated Czech translation 2019-10-02 03:57:00 +02:00
Matej Urbančič
a95601afdb Updated Slovenian translation 2019-09-28 21:13:30 +02:00
Matej Urbančič
2dbdf792db Updated Slovenian translation 2019-09-26 22:02:27 +02:00
Fabio Tomat
e23ce37e62 Update Friulian translation 2019-09-26 14:20:38 +00:00
Dušan Kazik
a05cb76e0d Update Slovak translation 2019-09-26 06:43:01 +00:00
Florian Müllner
60cab56f86 shell-util: Handle NULL from meta_window_get_image()
Until commit 506b75fc7f we got away with not handling a NULL return
value, as cairo_surface_destroy() deals with a NULL surface; the same
isn't true for get_width/get_height, so guard to code in question to
prevent a crash.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1678
2019-09-25 14:34:27 +00:00
Nathan Follens
70a5c3875c Update Dutch translation 2019-09-25 11:11:56 +00:00
Benjamin Berg
0fdbde9101 main: Remove NOTIFY_SOCKET from environment
It is only used exactly once to notify systemd about the service
startup. So unset it as soon as possible as it can leak into
subprocesses we spawn otherwise.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/741
2019-09-23 11:09:39 +02:00
Jonas Dreßler
2156577333 slider: Unset signal IDs when ending the slider drag
Unset the signal IDs we connected to when starting the drag. Otherwise
we get error messages if a touch drag is ended after a mouse drag
happened because the signal IDs are still set but no signals are
connected.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/740
2019-09-22 22:20:41 +00:00
Ryuta Fujii
f3e09b2b2f Update Japanese translation 2019-09-22 11:29:14 +00:00
Ryuta Fujii
6180f59c13 Update Japanese translation 2019-09-22 11:27:23 +00:00
Robert Mader
506b75fc7f shell-util: Do not scale the clip in get_content_for_window_actor()
This is now handled in Mutter. Also, respect the result size instead
of assuming it to be equal to the clip size, as the clip takes actor
coordinates while the result takes buffer coordinates.

This can be fixed in a future API iteration.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/728
2019-09-20 17:27:34 +00:00
Fran Dieguez
a0d0a17d68 Update Galician translation 2019-09-20 17:19:17 +00:00
Florian Müllner
92e5713e29 screenShield: Stop using deprecated actor property
Both LoginDialog and UnlockDialog are now actor subclasses, so stop
using the deprecated actor delegate that will trigger a warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
856c32db91 unlockDialog: Use inheritance instead of composition
The screen shield creates the unlock dialog based on the session mode.

However since commit 0c0d76f7d6 turned LoginDialog into an actor
subclass (while UnlockDialog kept using the delegate pattern), it is
no longer possible to handle both objects the same way without warnings.

Allow this again by turning UnlockDialog into an actor subclass as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
7b45ffa511 loginDialog: Stop using deprecated actor property
Commit 0c0d76f7d6 made the class an actor subclass, so the actor
property is just a deprecated synonym of the object itself.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
b6754d7db7 environment: Try harder to find a transition
When easing, we need the transition of one of the involved properties
to connect our callbacks. Currently we simply get the transition for
the first property, however as Clutter optimizes the case where a
property doesn't actually change, that transition may be NULL even
though we still animate other properties.

So instead of only looking at the transition of the first property,
try to find a transition for any of the involved properties.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1572
2019-09-20 16:40:46 +00:00
Marco Trevisan (Treviño)
2a9977a5b3 layout: Don't use the actors pick workaround on update regions
As per introduction of geometric picking in mutter [1], the workaround we
had consisting in picking all the actors to ensure that all the stage
projections were computed to get valid actors stage-transformed coordinates
and sizes is not working anymore as there is more caching involved.

However since this can be now handled properly in mutter [2], initializing a
valid projection matrix since the beginning, we can get rid of the
workaround.

[1] https://gitlab.gnome.org/GNOME/mutter/commit/14c706e51
[2] https://gitlab.gnome.org/GNOME/mutter/merge_requests/803

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/734
2019-09-20 16:05:32 +00:00
Marco Trevisan (Treviño)
dab60d5580 renameFolderMenu: Use a custom menu item inheriting from PopupBaseMenuItem
The RenameFolderMenu uses the internal box as a menu item, while PopupMenu
expects to have PopupBaseMenuItem based children with a delegate set.

Instead of using a custom menu with a customized box acting as menu
item,just add a RenameFolderMenuItem that inherits from the parent,
adjusting the features as we need them. In fact, the rename folder menu item
doesn't need any label, padding or default styling so we can reuse
PopupMenuBaseItem after we use our styling properties and we set the
Ornament to HIDDEN.

To get the proper style in place, define rename-folder-popup and
rename-folder-popup-item to override the default popup-menu-item rule
padding instead of using margins.

Pass the menu item as menu's focusActor as this will key-focus it on pop-up,
by overriding the key_focus_in() vfunc we can then delegate the focus
handling to the entry's clutter-text.

Also override the map() vfunc in order to update the entry's content before
mapping the entry.

Finally, use the item's activate method in order to tell the parent menu
we're done with it and that the menu can be closed.

As consequence we can also remove the menu's popup() method, and just use
the default open().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
8e3aac8ed7 renameFolderMenu: Move to non-legacy coding style
Use proper indentation on multi-line methods calls and use single quotes on
button label.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
147cb53140 renameFolderMenu: Set the entry as menu focus actor
When the rename folder menu is opened the text entry is expected to be
focused and selected for a quick editing.
While this is required it doesn't actually happens since PopupMenu by
default gives the key focus to the source actor, that is then free to pass
the key focus to the menu if there's an user interaction.

In this case however, we want the text entry to be focused once we prompt
the menu, so just use the PopupMenu's focusActor property to ensure it will
handle it for us.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1604
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
54f369404a popupMenu: Add focusActor property to define the default focus actor
The PopupMenuManager is supposed to grab and focus the menu actors, with
normal menus we always need to grab the actual menu but set the key focus to
the source actor so that it will be able to move the focus to the menu
child, if requested.

However there are menus such as the RenameFolderMenu that requires the
key-focus once prompted, so provide a focusActor property (defaulting to the
sourceActor) that can be set in order to define the actor to give the
keyboard focus to, when the menu is popped-up.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1604
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
af1aabff75 popupBaseMenuItem: Add support for Hidden Ornament
The menu item ornament is used to put dots or checks in menus or otherwise
to define a padding for a label.
However in some cases we want to create a menu item with no left (in ltr)
padding.

In order to do that, define a HIDDEN Ornament mode that completely hides the
ornament actor.

The naming here might be confusing as this should probably be called NONE,
while the default mode is the invisible one, but it's too late to change it
now.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
d6ba6dc554 renameFolderMenu: Don't save the source
The source actor is already tracked by the PopupMenu internally as
sourceActor, while nothing in RenameFolderMenu uses the source, so we can
drop this.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
42188b7698 folderIcon: Remove duplicated addMenu call
The RenameFolderMenu is added already to its menu manager, so no need to
repeat the operation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Jonas Dreßler
48adb2ef4b workspace: Fix an incorrect signal check
While commit 3094f863 was intended to cancel the ongoing idle hide
timeout before we start a new one, a mistake slipped in there while
rebasing: Obviously we should check if the signal id is NOT 0 here.

This didn't prevent timeouts being started while old ones are still
running and did override `this._idleHideOverlayId`, which caused the old
timeouts to run indefinitely after an overlay actor was destroyed
because we fail early (and don't return TRUE) in `_idleHideOverlay()`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/735
2019-09-20 11:50:24 +02:00
Jonas Dreßler
f8e648b7e3 appDisplay: Animate DnD app icons at the position they were dropped
Indicate whether dropping an app icon was successful or not by using the
newly added `animateLaunchAtPos()` API of AppIcon which starts a zoom
out animation of the icon at the position the drop happened.

To get the position of the drag actor, we have to forward the arguments
passed to `acceptDrop()` and `handleDragOver()` to the internal drag
handlers of the WorkspaceThumbnails. We can use this position directly
without transforming it to stage coordinates because the actor is a
child of `Main.uiGroup` and the animation actor will also be a child of
this container.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
daa5452af2 appDisplay: Add API to animate launch at given position
Add a `animateLaunchAtPos()` method to the AppIcon class to animate the
launch of an app at a given position. This allows for a visual
indication of whether dropping an app icon using DnD was successful at
the position the drop happened in a later commit.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
259874d731 workspace: Return results of forwarded acceptDrop
Return the results of calls to acceptDrop that we forwarded to the
Workspace object.

This fixes a bug where app icons that were dragged and released above a
window clone would get animated back to their original position
(indicating that nothing happened) even though they opened correctly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
23344701de overview: Only accept AppIcon drops if the app can open a new window
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
00e95de114 shell-app: Never allow opening new windows while an app is starting
We allow opening new windows as a fallback in case the app doesn't give
us explicit information about it, but we don't want to allow opening new
windows if we're unable to ask for this information (we can only use the
APIs to get this information while the app is RUNNING).

So always return FALSE in case the app is STARTING, always return TRUE
in case the app is STOPPED (starting an app always opens a new window)
and go through the usual checks in case the app is RUNNING (and
eventually fall back to FALSE).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
942758bb30 workspace: Use AppIcon.app to check action-support by the drag source
`AppIcon.shellWorkspaceLaunch()` can easily be replaced by checking for
`AppIcon.app` and calling `AppIcon.app.open_new_window()` directly.

For compatibility and to prevent breaking extensions implementing the
function, keep supporting the `shellWorkspaceLaunch` API in AppIcon
while logging a deprecation warning. Also keep supporting the API on
drag sources (without deprecating it) to allow extensions to define
custom actions on their drag sources.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Ådahl
e0947b01bd introspect: Check whitelist also for GetRunningWindows()
Otherwise the xdg-desktop-portal-gtk screen cast widget won't work.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/732
2019-09-18 16:17:25 +00:00
Daniel García Moreno
cf00231aa8 st: Fix box-shadow drawing with prerendered_texture
The use of box-shadow on a StWidget that has a background-gradient was
not been rendered correctly, the shadow borders was calculated inside
the st_theme_node_prerender_shadow function and in the case that we've a
prerendered_texture the max_borders was not calculated and are 0.

This patch creates a new static function to compute shadow maximum
borders copying the code from st_theme_node_prerender_shadow, and call
this new method in the case that we've a prerendered_texture.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1186
2019-09-18 16:09:36 +00:00
Jonas Dreßler
5c3f4f5f8b workspace: Remove unused properties of WindowClone
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
5f10047b58 viewSelector: Only reset search entry if it has key focus
If the search entry does not have any text typed in and a button press
happens outside of the search entry, we set key focus to NULL to make
the search entry appear unfocused.

This is quite intrusive and can easily cause unwanted focus changes, so
change the captured-event handler to only call `reset()` if the search
entry actually is focused.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
3094f86334 workspace: Reset idle hide timeout for overlays on reentry
Instead of returning and waiting until the old timeout is finished,
start a new idle hide timeout for the overlay when the pointer enters a
window clone. This makes sure the timeout for hiding the overlay after
the pointer left the clone mostly stays the same (except when leaving
the clone via the title or the close button).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
8ffea9d5c5 workspace: Make title of overlay reactive
Also make the title of the overlay reactive so we can keep the overlay
visible if the mouse is hovering over the title.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
4f3c8b8d69 workspace: Continue overlay idle hide timeout when pointing at close button
While it makes sense to remove the timeout in every other case, restart it
if the pointer is hovering over the close button to make sure the overlay
will be hidden afterwards.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Kjartan Maraas
edf6bd6909 Update Norwegian Bokmål translation 2019-09-18 13:34:34 +00:00
Charles Monzat
3e58af10ca Update French translation 2019-09-17 18:47:13 +00:00
Alexandre Franke
9e55d262f9 Update French translation 2019-09-17 11:44:09 +00:00
Florian Müllner
252e694979 util: Handle trailing LTR/RTL markers in URLs
Some electron apps apparently spread those generously over their
notification text, so may sure to not include them accidentally
in URLs.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1614
2019-09-16 20:41:47 +00:00
Florian Müllner
efed695eca cleanup: Don't add linebreak before operators
When breaking overly long conditions into multiple lines, the operator
should end the previous line instead of starting the new one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
b446667df6 cleanup: Disambiguate assignments in arrow functions
As arrow functions have an implicit return value, an assignment of
this.foo = bar could have been intended as a this.foo === bar
comparison. To catch those errors, we will disallow these kinds
of assignments unless they are marked explicitly by an extra pair
of parentheses.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
133a1e7bef cleanup: Remove trailing spaces
We generally avoid these (not least because Linus hates them enough
to make git complain loudly), but some sneaked in over time ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
5b3935fa43 cleanup: Fix up "special" comments
Our coding style asks for a space after the comment start, which
some of our ASCII-artsy comments violate. Adjust them to fit the
rule, or remove them altogether.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
471165ca9b cleanup: Use consistent brace style of blocks
Our coding style has always been to either put braces around all
blocks, or avoid them for all. Fix the couple of places that slipped
through.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
111f87a1b2 cleanup: Avoid pointless "renames" in destructuring
ES5 allows to rename variables in object destructuring, however this
only makes sense when we want to use a different name than the object
property.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
93525539c2 cleanup: Avoid unnecessary parentheses in arrow functions
Parentheses are only needed if there are zero or multiple arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
a77377efe7 cleanup: Avoid useless return statements
Return statements are only useful if they return a value or break
the regular function flow (i.e. early returns). Remove all returns
that do neither.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
81ab2865f7 cleanup: Don't use Array/Object constructors
The corresponding literals are more concise and cleaner.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
e585f7d97b scripting: Disable an eslint warning
Calling await in a loop means the asynchronous operations are
run sequentially instead of in-parallel. Usually that's not
what's wanted, so eslint has a rule to warn about this.

However here we use async/await to handle control back to the
mainloop between steps, so running operations sequentially is
actually intended.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
1a32e3e74a volume: Clarify some code
We have more idiomatic ways to check whether any element fullfills
some condition than breaking out of a loop.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
8d6820c4df magnifier: Do not modify function argument
The intention of the code is clearly to operate on a copy, but that's
not how the Object constructor works. While it doesn't matter in
practice that we modify the passed-in object parameter, it's still
a good idea to fix the code.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
2546445884 magnifier: Simplify some code
We don't need nested if blocks to set or unset the crosshairs'
clip size.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
e44b7df078 lint: Drop extra ignored nodes in legacy config
They didn't just allow for the style patterns they were added to,
but allowed for some messed up indentation to slip through. Now
that we adapted the code to not use the old style, it's time to
drop the exceptions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
3a9eaa39ea cleanup: Switch some method calls to new indentation style
The legacy indent rule currently ignores arrow functions in parameters
to allow callbacks to not align with the other arguments:

    this._someFunctionWithFairlyLongishName(arg1, arg2, arg3,
        () => {
            this._someOtherFunctionWithLongName(arg1);
        });

But as ignoring entire nodes means we can end up with arbitrary
indentation, we should drop the exception. While this would make
the above "illegal" under the legacy config, it conforms with the
non-legacy style, so everything should be fine ...

... except that eslint starts to complain about some function args
that should be fine under the legacy config. Maybe it's thrown off
by the function-arg-in-arrow-function-in-function-arg structure, but
rather than figuring it out, let's just move those to the new style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
af87bd8c87 cleanup: Use consistent style for ternary operator
We are currently inconsistent whether to put the operators in front
of the corresponding line or at the end of the preceding one. The
most dominant style for now is to put condition and first branch on
the same line, and then align the second branch:

  let foo = condition ? fooValue
                      : notFooValue;

Unfortunately that's a style that eslint doesn't support, so to account
for it, our legacy configuration currently plainly ignores all indentation
in conditionals.

In order to drop that exception and not let messed up indentation slip
through, change all ternary operators to the non-legacy style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
4bfb4a0e3d cleanup: Fix wrong indentation
Some more places where the indentation doesn't comply with either
the old or new style. They slipped through because the legacy eslint
configuration accounts for some patterns by plainly ignoring certain
nodes. We'll address that later, first fix up the indentation errors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Martin Zurowietz
d1a6601e60 theme: Equalize dimensions of ws switcher popup boxes
The indicator for the active workspace is currently two pixels
smaller because it doesn't account for the border used for
inactive workspaces.

Fix that to make sure all indicators have the same size.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1243
2019-09-15 01:23:56 +02:00
Harshula Jayasuriya
817aec5466 overview: Fix fading out desktop icons
A typo in commit 0846238f69 broke the animation.

Signed-off-by: Harshula Jayasuriya <harshula@hj.id.au>

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1616
2019-09-14 14:05:12 +02:00
132 changed files with 9692 additions and 7380 deletions

View File

@@ -16,8 +16,14 @@ run_eslint() {
ARGS_LEGACY='--config lint/eslintrc-legacy.json'
local extra_args=ARGS_$1
local output=OUTPUT_$1
eslint -f unix ${!extra_args} -o ${!output} js
local output_var=OUTPUT_$1
local output=${!output_var}
# ensure output exists even if eslint doesn't report any errors
mkdir -p $(dirname $output)
touch $output
eslint -f unix ${!extra_args} -o $output js
}
list_commit_range_additions() {
@@ -70,10 +76,13 @@ create_common() {
# non-legacy style just yet ...
unset CI_MERGE_REQUEST_TARGET_BRANCH_NAME
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
REMOTE=${1:-$CI_MERGE_REQUEST_PROJECT_URL.git}
BRANCH_NAME=${2:-$CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
if [ "$BRANCH_NAME" ]; then
git fetch $REMOTE $BRANCH_NAME
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
@@ -96,7 +105,7 @@ if ! is_empty $OUTPUT_FINAL; then
fi
# 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
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
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,
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
that has a property called `actor`. We call this wrapper class the "delegate".
you could inherit from GTypes natively in JS, in some cases we have a wrapper
class that has a property called `actor` (now deprecated). We call this
wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on
the actor itself:
```javascript
var MyActor = GObject.registerClass(
class MyActor extends Clutter.Actor {
_init(params) {
super._init(params);
this._delegate = this;
}
});
```
Or using the deprecated `actor`:
```javascript
var MyClass = class {
constructor() {
@@ -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"
when the user drags an item over it. If you do not set the `_delegate`
property, your actor will not be able to be dropped onto.
In case the class is an actor itself, the `_delegate` can be just set to `this`.
## Functional style

48
NEWS
View File

@@ -1,3 +1,51 @@
3.35.1
======
* Misc. bug fixes and cleanups [Marco; Matthias; !758, #701212]
Contributors:
Marco Trevisan (Treviño)
3.34.1
======
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
* Allow editing app folder names [Georges, Marco; !675, !720]
* Skip property transitions while hidden [Florian; !708]
* Make menu animations more consistent [Florian, GB_2; #1595, !717]
* Improve performance when enabling/disabling all extensions [Jonas D.; !96]
* Fix extra icons appearing in "Frequent" view animation [Georges; !696]
* Fix fading out desktop icons [Harshula; #1616]
* Fix box-shadow glitch with prerendered resources [Daniel; #1186]
* Fix accidentally skipped animations [Florian; #1572]
* Fix screenshots and window animations when scaled [Robert; !728]
* Don't leak NOTIFY_SOCKET environment variable to applications [Benjamin; !741]
* Fix lock-up on X11 when ibus is already running on startup [Marco; #1712]
* Fix screen dimming on idle [Marco; #1683]
* Do not notify systemd before initialization is complete [Iain; !750]
* Support SAE secrets in network agent [Lubomir; !751]
* Fix various regressions with dynamic workspaces [Florian; #1497]
* Fixed crashes [Florian, Marco; #1678, !746]
* Misc. bug fixes and cleanups [Marco, Jonas D., Florian, Iain, Georges,
Jonas Å., Martin, Takao, Carlos; !700, !705, !709, !711, !707, #1538, !710,
!713, !699, !715, !718, !716, !719, !721, #1243, !725, !731, #1614, !683,
!732, !121, !735, !736, !740, #573, #1641, #1571]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Jonas Dreßler, Takao Fujiwara, GB_2,
Carlos Garnacho, Harshula Jayasuriya, Iain Lane, Robert Mader,
Daniel García Moreno, Florian Müllner, Georges Basile Stavracas Neto,
Lubomir Rintel, Martin Zurowietz, Jonas Ådahl
Translators:
Rafael Fontenelle [pt_BR], Fran Dieguez [gl], Balázs Úr [hu],
Milo Casagrande [it], Daniel Șerbănescu [ro], Kukuh Syafaat [id],
Jiri Grönroos [fi], Daniel Mustieles [es], Piotr Drąg [pl],
Anders Jonsson [sv], Marek Černocký [cs], Jordi Mas [ca],
Aurimas Černius [lt], Christian Kirbach [de], Emin Tufan Çetin [tr],
Enrico Nicoletto [pt_BR], Danial Behzadi [fa], Марко Костић [sr],
Alexandre Franke [fr], Charles Monzat [fr], Kjartan Maraas [nb],
Ryuta Fujii [ja], Nathan Follens [nl], Dušan Kazik [sk], Fabio Tomat [fur],
Matej Urbančič [sl], Ask Hjorth Larsen [da], Alan Mortensen [da]
3.34.0
======
* Handle startup/shutdown of misc X11 services [Carlos; !680]

View File

@@ -50,7 +50,7 @@
</description>
</key>
<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>
<description>
The applications corresponding to these identifiers

View File

@@ -610,13 +610,12 @@ StScrollBar {
border-bottom-style: solid;
}
// Rename popup
.rename-folder-popup-box {
spacing: 6px;
margin-left: 12px;
margin-right: 12px;
.rename-folder-popup {
.rename-folder-popup-item {
spacing: 6px;
&:ltr, &:rtl { padding: 0, 12px; }
}
}
// Background menu
@@ -750,7 +749,7 @@ StScrollBar {
.ws-switcher-active-up, .ws-switcher-active-down,
.ws-switcher-active-left, .ws-switcher-active-right {
height: 50px;
height: 52px;
background-color: $selected_bg_color;
color: $selected_fg_color;
background-size: 32px;

View File

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

View File

@@ -285,8 +285,9 @@ var Application = GObject.registerClass({
log(`Failed to connect to shell proxy: ${e}`);
this._mainStack.add_named(new NoShellPlaceholder(), 'noshell');
this._mainStack.visible_child_name = 'noshell';
} else
} else {
throw e;
}
return;
}

View File

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

View File

@@ -202,7 +202,6 @@ var ConsecutiveBatch = class extends Batch {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();

View File

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

View File

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

View File

@@ -72,6 +72,16 @@ var IBusManager = class {
}
_clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
if (this._preloadEnginesId) {
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
if (this._panelService)
this._panelService.destroy();
@@ -86,28 +96,41 @@ var IBusManager = class {
}
_onConnected() {
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
this._cancellable = new Gio.Cancellable();
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
this._initPanelService.bind(this));
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
this._initPanelService.bind(this));
}
_initEngines(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
try {
let enginesList = this._ibus.list_engines_async_finish(result);
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
}
this._updateReadiness();
} else {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
this._clear();
}
}
_initPanelService(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
let success = false;
try {
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
@@ -134,7 +157,7 @@ var IBusManager = class {
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, (i, result) => {
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
@@ -206,8 +229,18 @@ var IBusManager = class {
return;
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback || null);
this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
}
preloadEngines(ids) {
@@ -227,7 +260,7 @@ var IBusManager = class {
this._ibus.preload_engines_async(
ids,
-1,
null,
this._cancellable,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;

View File

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

View File

@@ -127,7 +127,8 @@ var IntrospectService = class {
let apps = this._appSystem.get_running();
let windowsList = {};
if (!this._isIntrospectEnabled()) {
if (!this._isIntrospectEnabled() &&
!this._isSenderWhitelisted(invocation.get_sender())) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');

View File

@@ -172,7 +172,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
allProps.map(p => propsUnique[p] = null);
allProps.map(p => (propsUnique[p] = null));
}
return Object.keys(propsUnique).sort();
}

View File

@@ -84,9 +84,9 @@ function _findProviderForSid(sid) {
}
//------------------------------------------------------------------------------
// Support for the old ModemManager interface (MM < 0.7)
//------------------------------------------------------------------------------
// ----------------------------------------------------- //
// Support for the old ModemManager interface (MM < 0.7) //
// ----------------------------------------------------- //
// The following are not the complete interfaces, just the methods we need
@@ -182,9 +182,9 @@ var ModemCdma = class {
Signals.addSignalMethods(ModemCdma.prototype);
//------------------------------------------------------------------------------
// Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------
// ------------------------------------------------------- //
// Support for the new ModemManager1 interface (MM >= 0.7) //
// ------------------------------------------------------- //
const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem');
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);

View File

@@ -244,8 +244,9 @@ const SystemActions = GObject.registerClass({
_updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock');
let iconName = locked ? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic';
let iconName = locked
? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic';
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
this.notify('orientation-lock-icon');
@@ -268,7 +269,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map((term) => term.toLowerCase());
terms = terms.map(term => term.toLowerCase());
let results = [];

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView */
makeCloseButton, ensureActorVisibleInScrollView, wiggle */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
@@ -14,7 +14,7 @@ var SCROLL_TIME = 100;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]';
const _urlRegexp = new RegExp(
`(^|${_leadingJunk})` +
@@ -429,3 +429,37 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
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++) {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = false;
Main.overview.dash.showAppsButton.checked = false;
yield Scripting.waitLeisure();
}
}

View File

@@ -57,7 +57,7 @@ function waitAndDraw(milliseconds) {
cb();
});
return callback => cb = callback;
return callback => (cb = callback);
}
function waitSignal(object, signal) {
@@ -69,7 +69,7 @@ function waitSignal(object, signal) {
cb();
});
return callback => cb = callback;
return callback => (cb = callback);
}
function extractBootTimestamp() {
@@ -127,7 +127,7 @@ function *run() {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
Main.overview.dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
@@ -137,9 +137,9 @@ function *run() {
Main.overview.hide();
yield Scripting.waitLeisure();
////////////////////////////////////////
// Tests of redraw speed
////////////////////////////////////////
// --------------------- //
// Tests of redraw speed //
// --------------------- //
global.frame_timestamps = true;
global.frame_finish_timestamp = true;
@@ -186,8 +186,6 @@ function *run() {
yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop');

View File

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

View File

@@ -405,27 +405,26 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
});
class CyclerHighlight {
constructor() {
var CyclerHighlight = GObject.registerClass(
class CyclerHighlight extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
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.actor.add_actor(this._highlight);
this.add_actor(this._highlight);
let coordinate = Clutter.BindCoordinate.ALL;
let constraint = new Clutter.BindConstraint({ coordinate: coordinate });
this._clone.bind_property('source', constraint, 'source', 0);
this.actor.add_constraint(constraint);
this.add_constraint(constraint);
this.actor.connect('notify::allocation',
this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this.connect('notify::allocation', this._onAllocationChanged.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
set window(w) {
@@ -437,8 +436,8 @@ class CyclerHighlight {
if (this._clone.source)
this._clone.source.sync_visibility();
let windowActor = this._window ? this._window.get_compositor_private()
: null;
let windowActor = this._window
? this._window.get_compositor_private() : null;
if (windowActor)
windowActor.hide();
@@ -451,7 +450,7 @@ class CyclerHighlight {
this._highlight.set_size(0, 0);
this._highlight.hide();
} else {
let [x, y] = this.actor.allocation.get_origin();
let [x, y] = this.allocation.get_origin();
let rect = this._window.get_frame_rect();
this._highlight.set_size(rect.width, rect.height);
this._highlight.set_position(rect.x - x, rect.y - y);
@@ -462,7 +461,7 @@ class CyclerHighlight {
_onDestroy() {
this.window = null;
}
}
});
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
@@ -489,7 +488,7 @@ var CyclerPopup = GObject.registerClass({
return;
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.connect('item-highlighted', (list, index) => {
@@ -499,7 +498,7 @@ var CyclerPopup = GObject.registerClass({
_highlightItem(index, _justOutline) {
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() {
@@ -529,7 +528,7 @@ var CyclerPopup = GObject.registerClass({
}
_onDestroy() {
this._highlight.actor.destroy();
this._highlight.destroy();
super._onDestroy();
}
@@ -877,9 +876,9 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
_init(windows) {
super._init(false);
this._labels = new Array();
this._thumbnailBins = new Array();
this._clones = new Array();
this._labels = [];
this._thumbnailBins = [];
this._clones = [];
this._windows = windows;
for (let i = 0; i < windows.length; i++) {
@@ -940,7 +939,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
}
// Make sure we only do this once
this._thumbnailBins = new Array();
this._thumbnailBins = [];
}
_removeThumbnail(source, clone) {
@@ -1014,9 +1013,9 @@ class WindowIcon extends St.BoxLayout {
}
_createAppIcon(app, size) {
let appIcon = app ? app.create_icon_texture(size)
: new St.Icon({ icon_name: 'icon-missing',
icon_size: size });
let appIcon = app
? app.create_icon_texture(size)
: new St.Icon({ icon_name: 'icon-missing', icon_size: size });
appIcon.x_expand = appIcon.y_expand = true;
appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END;
@@ -1043,7 +1042,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.addItem(icon, icon.label);
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
icon._unmanagedSignalId = icon.window.connect('unmanaged', window => {
this._removeWindow(window);
});
}

View File

@@ -1,19 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* 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 SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
var Animation = class {
constructor(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.set_size(width, height);
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('notify::size', this._syncAnimationSize.bind(this));
this.actor.connect('resource-scale-changed',
var Animation = GObject.registerClass(
class Animation extends St.Bin {
_init(file, width, height, speed) {
super._init({ width: width, height: height });
this.connect('destroy', this._onDestroy.bind(this));
this.connect('resource-scale-changed',
this._loadFile.bind(this, file, width, height));
let themeContext = St.ThemeContext.get_for_stage(global.stage);
@@ -52,14 +51,14 @@ var Animation = class {
}
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
let [validResourceScale, resourceScale] = this.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false;
this.actor.destroy_all_children();
this.destroy_all_children();
if (!validResourceScale) {
if (wasPlaying)
@@ -72,7 +71,7 @@ var Animation = class {
this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
this.set_child(this._animations);
if (wasPlaying)
this.play();
@@ -99,7 +98,7 @@ var Animation = class {
if (!this._isLoaded)
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)
this._animations.get_child_at_index(i).set_size(width, height);
@@ -122,20 +121,22 @@ var Animation = class {
themeContext.disconnect(this._scaleChangedId);
this._scaleChangedId = 0;
}
};
});
var AnimatedIcon = class extends Animation {
constructor(file, size) {
super(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
var AnimatedIcon = GObject.registerClass(
class AnimatedIcon extends Animation {
_init(file, size) {
super._init(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
};
});
var Spinner = class extends AnimatedIcon {
constructor(size, animate = false) {
var Spinner = GObject.registerClass(
class Spinner extends AnimatedIcon {
_init(size, animate = false) {
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;
}
@@ -145,35 +146,35 @@ var Spinner = class extends AnimatedIcon {
}
play() {
this.actor.remove_all_transitions();
this.remove_all_transitions();
if (this._animate) {
super.play();
this.actor.ease({
this.ease({
opacity: 255,
delay: SPINNER_ANIMATION_DELAY,
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR
});
} else {
this.actor.opacity = 255;
this.opacity = 255;
super.play();
}
}
stop() {
this.actor.remove_all_transitions();
this.remove_all_transitions();
if (this._animate) {
this.actor.ease({
this.ease({
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => super.stop()
});
} else {
this.actor.opacity = 0;
this.opacity = 0;
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.Weather.Application.desktop': 'org.gnome.Weather.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'shotwell.desktop': 'org.gnome.Shotwell.desktop',
'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop',

View File

@@ -161,7 +161,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
deviceNames.forEach(n => (devices |= AudioDevice[n.toUpperCase()]));
let dialog;
try {

View File

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

View File

@@ -46,12 +46,18 @@ var BoxPointer = GObject.registerClass({
this.add_actor(this._border);
this.bin.raise(this._border);
this._sourceAlignment = 0.5;
this._capturedEventId = 0;
this._muteInput();
this._muteInput = true;
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_captured_event() {
if (this._muteInput)
return Clutter.EVENT_STOP;
return Clutter.EVENT_PROPAGATE;
}
_onDestroy() {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
@@ -63,19 +69,6 @@ var BoxPointer = GObject.registerClass({
return this._arrowSide;
}
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.connect('captured-event',
() => Clutter.EVENT_STOP);
}
_unmuteInput() {
if (this._capturedEventId != 0) {
this.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
}
open(animate, onComplete) {
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
@@ -112,7 +105,7 @@ var BoxPointer = GObject.registerClass({
duration: animationTime,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
this._unmuteInput();
this._muteInput = false;
if (onComplete)
onComplete();
}
@@ -147,7 +140,7 @@ var BoxPointer = GObject.registerClass({
}
}
this._muteInput();
this._muteInput = true;
this.remove_all_transitions();
this.ease({
@@ -172,8 +165,8 @@ var BoxPointer = GObject.registerClass({
let borderWidth = themeNode.get_length('-arrow-border-width');
minSize += borderWidth * 2;
natSize += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
|| (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) ||
(isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let rise = themeNode.get_length('-arrow-rise');
minSize += rise;
natSize += rise;

View File

@@ -313,8 +313,10 @@ var DBusEventSource = class DBusEventSource {
};
Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = class Calendar {
constructor() {
var Calendar = GObject.registerClass({
Signals: { 'selected-date-changed': { param_types: [GLib.DateTime.$gtype] } }
}, class Calendar extends St.Widget {
_init() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
@@ -344,12 +346,11 @@ var Calendar = class Calendar {
this._shouldDateGrabFocus = false;
this.actor = new St.Widget({ style_class: 'calendar',
layout_manager: new Clutter.TableLayout(),
reactive: true });
this.actor.connect('scroll-event',
this._onScroll.bind(this));
super._init({
style_class: 'calendar',
layout_manager: new Clutter.TableLayout(),
reactive: true
});
this._buildHeader ();
}
@@ -373,7 +374,10 @@ var Calendar = class Calendar {
this._selectedDate = date;
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() {
@@ -384,9 +388,9 @@ var Calendar = class Calendar {
}
_buildHeader() {
let layout = this.actor.layout_manager;
let layout = this.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_all_children();
this.destroy_all_children();
// Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout();
@@ -428,7 +432,7 @@ var Calendar = class Calendar {
can_focus: true });
label.accessible_name = iter.toLocaleFormat('%A');
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;
else
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
this._firstDayIndex = this.actor.get_n_children();
this._firstDayIndex = this.get_n_children();
}
_onScroll(actor, event) {
switch (event.get_scroll_direction()) {
vfunc_scroll_event(scrollEvent) {
switch (scrollEvent.direction) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT:
this._onPrevMonthButtonClicked();
@@ -511,7 +515,7 @@ var Calendar = class Calendar {
let now = new Date();
// 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++)
children[i].destroy();
@@ -548,7 +552,7 @@ var Calendar = class Calendar {
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 row = 2;
// nRows here means 6 weeks + one header + one navbar
@@ -581,8 +585,9 @@ var Calendar = class Calendar {
if (row == 2)
styleClass = `calendar-day-top ${styleClass}`;
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
let leftMost = rtl
? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
if (leftMost)
styleClass = `calendar-day-left ${styleClass}`;
@@ -647,12 +652,12 @@ var Calendar = class Calendar {
}
});
}
};
Signals.addSignalMethods(Calendar.prototype);
});
var EventMessage = class EventMessage extends MessageList.Message {
constructor(event, date) {
super('', event.summary);
var EventMessage = GObject.registerClass(
class EventMessage extends MessageList.Message {
_init(event, date) {
super._init('', event.summary);
this._event = event;
this._date = date;
@@ -661,11 +666,12 @@ var EventMessage = class EventMessage extends MessageList.Message {
this._icon = new St.Icon({ icon_name: 'x-office-calendar-symbolic' });
this.setIcon(this._icon);
}
this.actor.connect('style-changed', () => {
let iconVisible = this.actor.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0);
});
vfunc_style_changed() {
let iconVisible = this.get_parent().has_style_pseudo_class('first-child');
this._icon.opacity = (iconVisible ? 255 : 0);
super.vfunc_style_changed();
}
_formatEventTime() {
@@ -680,8 +686,9 @@ var EventMessage = class EventMessage extends MessageList.Message {
*/
title = C_("event list time", "All Day");
} else {
let date = this._event.date >= periodBegin ? this._event.date
: this._event.end;
let date = this._event.date >= periodBegin
? this._event.date
: this._event.end;
title = Util.formatTime(date, { timeOnly: true });
}
@@ -700,12 +707,12 @@ var EventMessage = class EventMessage extends MessageList.Message {
}
return title;
}
};
});
var NotificationMessage =
var NotificationMessage = GObject.registerClass(
class NotificationMessage extends MessageList.Message {
constructor(notification) {
super(notification.title, notification.bannerBodyText);
_init(notification) {
super._init(notification.title, notification.bannerBodyText);
this.setUseBodyMarkup(notification.bannerBodyMarkup);
this.notification = notification;
@@ -742,7 +749,7 @@ class NotificationMessage extends MessageList.Message {
this.setUseBodyMarkup(n.bannerBodyMarkup);
}
_onClicked() {
vfunc_clicked() {
this.notification.activate();
}
@@ -764,11 +771,12 @@ class NotificationMessage extends MessageList.Message {
canClose() {
return true;
}
};
});
var EventsSection = class EventsSection extends MessageList.MessageListSection {
constructor() {
super();
var EventsSection = GObject.registerClass(
class EventsSection extends MessageList.MessageListSection {
_init() {
super._init();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
@@ -780,7 +788,7 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
label: '',
x_align: St.Align.START,
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('key-focus-in', this._onKeyFocusIn.bind(this));
@@ -899,12 +907,29 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
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 {
constructor() {
super();
_init() {
super._init();
this._sources = new Map();
this._nUrgent = 0;
@@ -913,8 +938,6 @@ class NotificationSection extends MessageList.MessageListSection {
Main.messageTray.getSources().forEach(source => {
this._sourceAdded(Main.messageTray, source);
});
this.actor.connect('notify::mapped', this._onMapped.bind(this));
}
get allowed() {
@@ -922,17 +945,6 @@ class NotificationSection extends MessageList.MessageListSection {
!Main.sessionMode.isGreeter;
}
_createTimeLabel(datetime) {
let label = new St.Label({ style_class: 'event-time',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END });
label.connect('notify::mapped', () => {
if (label.mapped)
label.text = Util.formatTimeSpan(datetime);
});
return label;
}
_sourceAdded(tray, source) {
let obj = {
destroyId: 0,
@@ -950,13 +962,13 @@ class NotificationSection extends MessageList.MessageListSection {
_onNotificationAdded(source, 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 updatedId = notification.connect('updated', () => {
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped);
message.setSecondaryActor(new TimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.mapped);
});
let destroyId = notification.connect('destroy', () => {
notification.disconnect(destroyId);
@@ -976,7 +988,7 @@ class NotificationSection extends MessageList.MessageListSection {
}
let index = isUrgent ? 0 : this._nUrgent;
this.addMessageAtIndex(message, index, this.actor.mapped);
this.addMessageAtIndex(message, index, this.mapped);
}
_onSourceDestroy(source, obj) {
@@ -986,25 +998,23 @@ class NotificationSection extends MessageList.MessageListSection {
this._sources.delete(source);
}
_onMapped() {
if (!this.actor.mapped)
return;
for (let message of this._messages.keys())
vfunc_map() {
this._messages.forEach(message => {
if (message.notification.urgency != MessageTray.Urgency.CRITICAL)
message.notification.acknowledged = true;
});
super.vfunc_map();
}
_shouldShow() {
return !this.empty && isToday(this._date);
}
};
var Placeholder = class Placeholder {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
vertical: true });
});
var Placeholder = GObject.registerClass(
class Placeholder extends St.BoxLayout {
_init() {
super._init({ style_class: 'message-list-placeholder', vertical: true });
this._date = new Date();
let todayFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/no-notifications.svg');
@@ -1013,10 +1023,10 @@ var Placeholder = class Placeholder {
this._otherIcon = new Gio.FileIcon({ file: otherFile });
this._icon = new St.Icon();
this.actor.add_actor(this._icon);
this.add_actor(this._icon);
this._label = new St.Label();
this.actor.add_actor(this._label);
this.add_actor(this._label);
this._sync();
}
@@ -1043,20 +1053,24 @@ var Placeholder = class Placeholder {
this._label.text = _("No Events");
}
}
};
});
var CalendarMessageList = class CalendarMessageList {
constructor() {
this.actor = new St.Widget({ style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
var CalendarMessageList = GObject.registerClass(
class CalendarMessageList extends St.Widget {
_init() {
super._init({
style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true
});
this._placeholder = new Placeholder();
this.actor.add_actor(this._placeholder.actor);
this.add_actor(this._placeholder);
let box = new St.BoxLayout({ vertical: true,
x_expand: true, y_expand: true });
this.actor.add_actor(box);
this.add_actor(box);
this._scrollView = new St.ScrollView({ style_class: 'vfade',
overlay_scrollbars: true,
@@ -1070,12 +1084,11 @@ var CalendarMessageList = class CalendarMessageList {
can_focus: true });
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()];
sections.forEach((s) => s.clear());
this._sectionList.get_children().forEach(s => s.clear());
});
box.add_actor(this._clearButton);
this._placeholder.actor.bind_property('visible',
this._placeholder.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
@@ -1083,8 +1096,9 @@ var CalendarMessageList = class CalendarMessageList {
vertical: true,
y_expand: true,
y_align: Clutter.ActorAlign.START });
this._sectionList.connect('actor-added', this._sync.bind(this));
this._sectionList.connect('actor-removed', this._sync.bind(this));
this._scrollView.add_actor(this._sectionList);
this._sections = new Map();
this._mediaSection = new Mpris.MediaSection();
this._addSection(this._mediaSection);
@@ -1099,58 +1113,35 @@ var CalendarMessageList = class CalendarMessageList {
}
_addSection(section) {
let obj = {
destroyId: 0,
visibleId: 0,
emptyChangedId: 0,
canClearChangedId: 0,
keyFocusId: 0
};
obj.destroyId = section.actor.connect('destroy', () => {
this._removeSection(section);
});
obj.visibleId = section.actor.connect('notify::visible',
this._sync.bind(this));
obj.emptyChangedId = section.connect('empty-changed',
this._sync.bind(this));
obj.canClearChangedId = section.connect('can-clear-changed',
this._sync.bind(this));
obj.keyFocusId = section.connect('key-focus-in',
this._onKeyFocusIn.bind(this));
let connectionsIds = [];
this._sections.set(section, obj);
this._sectionList.add_actor(section.actor);
this._sync();
}
for (let prop of ['visible', 'empty', 'can-clear']) {
connectionsIds.push(
section.connect(`notify::${prop}`, this._sync.bind(this)));
}
connectionsIds.push(section.connect('message-focused', (_s, messageActor) => {
Util.ensureActorVisibleInScrollView(this._scrollView, messageActor);
}));
_removeSection(section) {
let obj = this._sections.get(section);
section.actor.disconnect(obj.destroyId);
section.actor.disconnect(obj.visibleId);
section.disconnect(obj.emptyChangedId);
section.disconnect(obj.canClearChangedId);
section.disconnect(obj.keyFocusId);
connectionsIds.push(section.connect('destroy', (section) => {
connectionsIds.forEach(id => section.disconnect(id));
this._sectionList.remove_actor(section);
}));
this._sections.delete(section);
this._sectionList.remove_actor(section.actor);
this._sync();
}
_onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
this._sectionList.add_actor(section);
}
_sync() {
let sections = [...this._sections.keys()];
let sections = this._sectionList.get_children();
let visible = sections.some(s => s.allowed);
this.actor.visible = visible;
this.visible = visible;
if (!visible)
return;
let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty;
let empty = sections.every(s => s.empty || !s.visible);
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;
}
@@ -1159,8 +1150,7 @@ var CalendarMessageList = class CalendarMessageList {
}
setDate(date) {
for (let section of this._sections.keys())
section.setDate(date);
this._sectionList.get_children().forEach(s => s.setDate(date));
this._placeholder.setDate(date);
}
};
});

View File

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

View File

@@ -156,7 +156,7 @@ var AutomountManager = class {
!volume.should_automount() ||
!volume.can_mount()) {
// allow the autorun to run anyway; this can happen if the
// mount gets added programmatically later, even if
// mount gets added programmatically later, even if
// should_automount() or can_mount() are false, like for
// blank optical media.
this._allowAutorun(volume);
@@ -222,14 +222,14 @@ var AutomountManager = class {
GLib.source_remove(volume._allowAutorunExpireId);
delete volume._allowAutorunExpireId;
}
this._volumeQueue =
this._volumeQueue =
this._volumeQueue.filter(element => (element != volume));
}
_reaskPassword(volume) {
let prevOperation = this._activeOperations.get(volume);
let existingDialog = prevOperation ? prevOperation.borrowDialog() : null;
let operation =
let operation =
new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog: existingDialog });
this._mountVolume(volume, operation);

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, St } = imports.gi;
const { Gio, GObject, St } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
@@ -63,7 +63,7 @@ function startAppForMount(app, mount) {
files.push(root);
try {
retval = app.launch(files,
retval = app.launch(files,
global.create_app_launch_context(0, -1));
} catch (e) {
log(`Unable to launch the application ${app.get_name()}: ${e}`);
@@ -72,8 +72,6 @@ function startAppForMount(app, mount) {
return retval;
}
/******************************************/
const HotplugSnifferIface = loadInterfaceXML('org.gnome.Shell.HotplugSniffer');
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {
@@ -117,9 +115,9 @@ var ContentTypeDiscoverer = class {
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(),
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
});
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
});
}
}
@@ -215,11 +213,11 @@ var AutorunDispatcher = class {
}
_addSource(mount, apps) {
// if we already have a source showing for this
// if we already have a source showing for this
// mount, return
if (this._getSourceForMount(mount))
return;
// add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps));
}
@@ -264,7 +262,7 @@ var AutorunDispatcher = class {
removeMount(mount) {
let source = this._getSourceForMount(mount);
// if we aren't tracking this mount, don't do anything
if (!source)
return;
@@ -274,9 +272,10 @@ var AutorunDispatcher = class {
}
};
var AutorunSource = class extends MessageTray.Source {
constructor(manager, mount, apps) {
super(mount.get_name());
var AutorunSource = GObject.registerClass(
class AutorunSource extends MessageTray.Source {
_init(manager, mount, apps) {
super._init(mount.get_name());
this._manager = manager;
this.mount = mount;
@@ -286,7 +285,7 @@ var AutorunSource = class extends MessageTray.Source {
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
this.notify(this._notification);
this.showNotification(this._notification);
}
getIcon() {
@@ -296,11 +295,12 @@ var AutorunSource = class extends MessageTray.Source {
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
};
});
var AutorunNotification = class extends MessageTray.Notification {
constructor(manager, source) {
super(source, source.title);
var AutorunNotification = GObject.registerClass(
class AutorunNotification extends MessageTray.Notification {
_init(manager, source) {
super._init(source, source.title);
this._manager = manager;
this._mount = source.mount;
@@ -352,6 +352,6 @@ var AutorunNotification = class extends MessageTray.Notification {
let app = Gio.app_info_get_default_for_type('inode/directory', false);
startAppForMount(app, this._mount);
}
};
});
var Component = AutorunManager;

View File

@@ -77,13 +77,13 @@ class KeyringDialog extends ModalDialog.ModalDialog {
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
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(label, 2, row, 1, 1);
} else {
layout.attach(label, 0, row, 1, 1);
layout.attach(this._passwordEntry, 1, row, 1, 1);
layout.attach(this._workSpinner.actor, 2, row, 1, 1);
layout.attach(this._workSpinner, 2, row, 1, 1);
}
row++;
} else {
@@ -121,8 +121,8 @@ class KeyringDialog extends ModalDialog.ModalDialog {
if (this.prompt.choice_visible) {
let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice.actor, rtl ? 0 : 1, row, 1, 1);
this.prompt.bind_property('choice-chosen', choice, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.attach(choice, rtl ? 0 : 1, row, 1, 1);
row++;
}
@@ -232,8 +232,9 @@ var KeyringPrompter = class {
constructor() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => {
let dialog = this._enabled ? new KeyringDialog()
: new KeyringDummyDialog();
let dialog = this._enabled
? new KeyringDialog()
: new KeyringDummyDialog();
this._currentPrompt = dialog.prompt;
return this._currentPrompt;
});

View File

@@ -164,9 +164,9 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (value.length == 64) {
// must be composed of hexadecimal digits only
for (let i = 0; i < 64; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
if (!((value[i] >= 'a' && value[i] <= 'f') ||
(value[i] >= 'A' && value[i] <= 'F') ||
(value[i] >= '0' && value[i] <= '9')))
return false;
}
return true;
@@ -180,15 +180,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
if (!((value[i] >= 'a' && value[i] <= 'f') ||
(value[i] >= 'A' && value[i] <= 'F') ||
(value[i] >= '0' && value[i] <= '9')))
return false;
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'z')
|| (value[i] >= 'A' && value[i] <= 'Z')))
if (!((value[i] >= 'a' && value[i] <= 'z') ||
(value[i] >= 'A' && value[i] <= 'Z')))
return false;
}
} else {
@@ -213,6 +213,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
// First the easy ones
case 'wpa-none':
case 'wpa-psk':
case 'sae':
secrets.push({ label: _("Password: "), key: 'psk',
value: wirelessSecuritySetting.psk || '',
validate: this._validateWpaPsk, password: true });
@@ -624,7 +625,7 @@ var NetworkAgent = class {
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => this._vpnCacheBuilt = false);
monitor.connect('changed', () => (this._vpnCacheBuilt = false));
} catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
}
@@ -733,7 +734,7 @@ var NetworkAgent = class {
});
Main.messageTray.add(source);
source.notify(notification);
source.showNotification(notification);
}
_newRequest(agent, requestId, connection, settingName, hints, flags) {

View File

@@ -76,8 +76,8 @@ var AuthenticationDialog = GObject.registerClass({
this._userAvatar = new UserWidget.Avatar(this._user,
{ iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
this._userAvatar.hide();
userBox.add(this._userAvatar,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
@@ -106,7 +106,7 @@ var AuthenticationDialog = GObject.registerClass({
{ expand: 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._passwordBox.hide();
@@ -305,7 +305,7 @@ var AuthenticationDialog = GObject.registerClass({
_onUserChanged() {
if (this._user.is_loaded && this._userAvatar) {
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
let source = this._chatSources[channel.get_object_path()];
if (source)
source.notify();
source.showNotification();
}
}
}
@@ -266,9 +266,10 @@ class TelepathyClient extends Tp.BaseClient {
}
}) : null;
var ChatSource = class extends MessageTray.Source {
constructor(account, conn, channel, contact, client) {
super(contact.get_alias());
var ChatSource = HAVE_TP ? GObject.registerClass(
class ChatSource extends MessageTray.Source {
_init(account, conn, channel, contact, client) {
super._init(contact.get_alias());
this._account = account;
this._contact = contact;
@@ -326,7 +327,7 @@ var ChatSource = class extends MessageTray.Source {
// We ack messages when the user expands the new notification
let id = this._banner.connect('expanded', this._ackMessages.bind(this));
this._banner.actor.connect('destroy', () => {
this._banner.connect('destroy', () => {
this._banner.disconnect(id);
this._banner = null;
});
@@ -476,7 +477,7 @@ var ChatSource = class extends MessageTray.Source {
this._notification.appendMessage(pendingMessages[i], true);
if (pendingMessages.length > 0)
this.notify();
this.showNotification();
}
destroy(reason) {
@@ -553,7 +554,7 @@ var ChatSource = class extends MessageTray.Source {
_notifyTimeout() {
if (this._pendingMessages.length != 0)
this.notify();
this.showNotification();
this._notifyTimeoutId = 0;
@@ -568,8 +569,8 @@ var ChatSource = class extends MessageTray.Source {
this._notification.appendMessage(message);
}
notify() {
super.notify(this._notification);
showNotification() {
super.showNotification(this._notification);
}
respond(text) {
@@ -583,7 +584,7 @@ var ChatSource = class extends MessageTray.Source {
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
this._channel.send_message_finish(result);
});
}
@@ -625,12 +626,18 @@ var ChatSource = class extends MessageTray.Source {
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
}
};
}) : null;
var ChatNotification = class extends MessageTray.Notification {
constructor(source) {
super(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
var ChatNotification = HAVE_TP ? GObject.registerClass({
Signals: {
'message-removed': { param_types: [Tp.Message.$gtype] },
'message-added': { param_types: [Tp.Message.$gtype] },
'timestamp-changed': { param_types: [Tp.Message.$gtype] },
}
}, class ChatNotification extends MessageTray.Notification {
_init(source) {
super._init(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
this.setResident(true);
@@ -653,7 +660,7 @@ var ChatNotification = class extends MessageTray.Notification {
* sender: the name of the sender,
* timestamp: the time the message was sent
* direction: a #NotificationDirection
*
*
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp
* will be added, regardless of the difference since the
* last timestamp
@@ -673,8 +680,8 @@ var ChatNotification = class extends MessageTray.Notification {
{ datetime: GLib.DateTime.new_from_unix_local (message.timestamp),
bannerMarkup: true });
let group = (message.direction == NotificationDirection.RECEIVED ?
'received' : 'sent');
let group = (message.direction == NotificationDirection.RECEIVED
? 'received' : 'sent');
this._append({ body: messageBody,
group: group,
@@ -696,8 +703,8 @@ var ChatNotification = class extends MessageTray.Notification {
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
// we'll keep SCROLLBACK_IDLE_LENGTH messages.
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ?
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME)
? SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(item => item.realMessage);
if (filteredHistory.length > maxLength) {
@@ -782,7 +789,7 @@ var ChatNotification = class extends MessageTray.Notification {
this._filterMessages();
}
};
}) : null;
var ChatLineBox = GObject.registerClass(
class ChatLineBox extends St.BoxLayout {
@@ -792,9 +799,10 @@ class ChatLineBox extends St.BoxLayout {
}
});
var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
constructor(notification) {
super(notification);
var ChatNotificationBanner = GObject.registerClass(
class ChatNotificationBanner extends MessageTray.NotificationBanner {
_init(notification) {
super._init(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true,
@@ -879,8 +887,7 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
}
_addMessage(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
let body = highlighter.actor;
let body = new MessageList.URLHighlighter(message.body, true, true);
let styles = message.styles;
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);
}
}
};
});
var Component = TelepathyComponent;

View File

@@ -1,8 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const { Clutter, GLib, GObject,
Graphene, Meta, Shell, St } = imports.gi;
const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites;
@@ -23,9 +23,10 @@ function getAppFromSource(source) {
}
}
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
constructor(app) {
super(app, {
var DashIcon = GObject.registerClass(
class DashIcon extends AppDisplay.AppIcon {
_init(app) {
super._init(app, {
setSizeManually: true,
showLabel: false
});
@@ -45,7 +46,7 @@ var DashIcon = class DashIcon extends AppDisplay.AppIcon {
acceptDrop() {
return false;
}
};
});
// A container like StBin, but taking the child's scale into account
// when requesting a size
@@ -53,7 +54,7 @@ var DashItemContainer = GObject.registerClass(
class DashItemContainer extends St.Widget {
_init() {
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_y: 0,
opacity: 0,
@@ -330,8 +331,10 @@ class DashActor extends St.Widget {
const baseIconSizes = [16, 22, 24, 32, 48, 64];
var Dash = class Dash {
constructor() {
var Dash = GObject.registerClass({
Signals: { 'icon-size-changed': {} }
}, class Dash extends St.Bin {
_init() {
this._maxHeight = -1;
this.iconSize = 64;
this._shownInitially = false;
@@ -359,11 +362,11 @@ var Dash = class Dash {
this._container.add_actor(this._showAppsIcon);
this.actor = new St.Bin({ child: this._container });
this.actor.connect('notify::height', () => {
if (this._maxHeight != this.actor.height)
super._init({ child: this._container });
this.connect('notify::height', () => {
if (this._maxHeight != this.height)
this._queueRedisplay();
this._maxHeight = this.actor.height;
this._maxHeight = this.height;
});
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
// the left of the overview
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
Main.ctrlAltTabManager.addGroup(this, _("Dash"), 'user-bookmarks-symbolic');
}
_onDragBegin() {
@@ -481,11 +484,11 @@ var Dash = class Dash {
});
let item = new DashItemContainer();
item.setChild(appIcon.actor);
item.setChild(appIcon);
// Override default AppIcon label_actor, now the
// accessible_name is set at DashItemContainer.setLabelText
appIcon.actor.label_actor = null;
appIcon.label_actor = null;
item.setLabelText(app.get_name());
appIcon.icon.setIconSize(this.iconSize);
@@ -623,7 +626,7 @@ var Dash = class Dash {
icon.icon.ease({
width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@@ -703,8 +706,8 @@ var Dash = class Dash {
}
// App moved
let nextApp = newApps.length > newIndex + 1 ? newApps[newIndex + 1]
: null;
let nextApp = newApps.length > newIndex + 1
? newApps[newIndex + 1] : null;
let insertHere = nextApp && nextApp == oldApp;
let alreadyRemoved = removedActors.reduce((result, actor) => {
let removedApp = actor.child._delegate.app;
@@ -902,5 +905,4 @@ var Dash = class Dash {
return true;
}
};
Signals.addSignalMethods(Dash.prototype);
});

View File

@@ -25,24 +25,26 @@ function _isToday(date) {
now.getDate() == date.getDate();
}
var TodayButton = class TodayButton {
constructor(calendar) {
function _gDateTimeToDate(datetime) {
return new Date(datetime.to_unix() * 1000 + datetime.get_microsecond() / 1000);
}
var TodayButton = GObject.registerClass(
class TodayButton extends St.Button {
_init(calendar) {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
this.actor = new St.Button({
super._init({
style_class: 'datemenu-today-button',
x_align: St.Align.START,
x_expand: true,
can_focus: true,
reactive: false,
});
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
reactive: false
});
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',
x_align: Clutter.ActorAlign.START });
@@ -52,13 +54,17 @@ var TodayButton = class TodayButton {
hbox.add_actor(this._dateLabel);
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
// current date.
this.actor.reactive = !_isToday(date);
this.reactive = !_isToday(_gDateTimeToDate(datetime));
});
}
vfunc_clicked() {
this._calendar.setDate(new Date(), false);
}
setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A'));
@@ -75,34 +81,29 @@ var TodayButton = class TodayButton {
* date, e.g. "Tuesday February 17 2015".
*/
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 {
constructor() {
var WorldClocksSection = GObject.registerClass(
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._clockNotifyId = 0;
this._locations = [];
this.actor = new St.Button({ style_class: 'world-clocks-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
});
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._grid = new St.Widget({ style_class: 'world-clocks-grid',
layout_manager: layout });
layout.hookup_style(this._grid);
this.actor.child = this._grid;
this.child = this._grid;
this._clocksApp = null;
this._clocksProxy = new ClocksProxy(
@@ -125,9 +126,17 @@ var WorldClocksSection = class WorldClocksSection {
this._sync();
}
vfunc_clicked() {
if (this._clocksApp)
this._clocksApp.activate();
Main.overview.hide();
Main.panel.closeCalendar();
}
_sync() {
this._clocksApp = this._appSystem.lookup_app('org.gnome.clocks.desktop');
this.actor.visible = this._clocksApp != null;
this.visible = this._clocksApp != null;
}
_clocksChanged() {
@@ -148,13 +157,14 @@ var WorldClocksSection = class WorldClocksSection {
});
let layout = this._grid.layout_manager;
let title = (this._locations.length == 0) ? _("Add world clocks…")
: _("World Clocks");
let title = (this._locations.length == 0)
? _("Add world clocks")
: _("World Clocks");
let header = new St.Label({ style_class: 'world-clocks-header',
x_align: Clutter.ActorAlign.START,
text: title });
layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header;
this.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
@@ -235,30 +245,23 @@ var WorldClocksSection = class WorldClocksSection {
this._settings.set_value('locations',
new GLib.Variant('av', this._clocksProxy.Locations));
}
};
});
var WeatherSection = GObject.registerClass(
class WeatherSection extends St.Button {
_init() {
super._init({
style_class: 'weather-button',
x_fill: true,
can_focus: true
});
var WeatherSection = class WeatherSection {
constructor() {
this._weatherClient = new Weather.WeatherClient();
this.actor = new St.Button({ style_class: 'weather-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', () => {
this._weatherClient.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
});
this.actor.connect('notify::mapped', () => {
if (this.actor.mapped)
this._weatherClient.update();
});
let box = new St.BoxLayout({ style_class: 'weather-box',
vertical: true });
this.actor.child = box;
this.child = box;
let titleBox = new St.BoxLayout();
titleBox.add_child(new St.Label({ style_class: 'weather-header',
@@ -281,6 +284,18 @@ var WeatherSection = class WeatherSection {
this._sync();
}
vfunc_map() {
this._weatherClient.update();
super.vfunc_map();
}
vfunc_clicked() {
this._weatherClient.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
}
_getInfos() {
let info = this._weatherClient.info;
let forecasts = info.get_forecast_list();
@@ -371,23 +386,27 @@ var WeatherSection = class WeatherSection {
}
_sync() {
this.actor.visible = this._weatherClient.available;
this.visible = this._weatherClient.available;
if (!this.actor.visible)
if (!this.visible)
return;
this._titleLocation.visible = this._weatherClient.hasLocation;
this._updateForecasts();
}
};
});
var MessagesIndicator = class MessagesIndicator {
constructor() {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false, y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
var MessagesIndicator = GObject.registerClass(
class MessagesIndicator extends St.Icon {
_init() {
super._init({
icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER
});
this._sources = [];
@@ -400,7 +419,7 @@ var MessagesIndicator = class MessagesIndicator {
}
_onSourceAdded(tray, source) {
source.connect('count-updated', this._updateCount.bind(this));
source.connect('notify::count', this._updateCount.bind(this));
this._sources.push(source);
this._updateCount();
}
@@ -412,12 +431,12 @@ var MessagesIndicator = class MessagesIndicator {
_updateCount() {
let count = 0;
this._sources.forEach(source => count += source.unseenCount);
this._sources.forEach(source => (count += source.unseenCount));
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);
this.visible = (count > 0);
}
};
});
var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
@@ -510,9 +529,9 @@ class DateMenuButton extends PanelMenu.Button {
this._indicator = new MessagesIndicator();
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._indicator.actor);
box.add_actor(this._indicator);
this.label_actor = this._clockDisplay;
this.add_actor(box);
@@ -528,11 +547,11 @@ class DateMenuButton extends PanelMenu.Button {
bin.add_actor(hbox);
this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed',
(calendar, date) => {
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
});
this._calendar.connect('selected-date-changed', (_calendar, datetime) => {
let date = _gDateTimeToDate(datetime);
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
});
this.menu.connect('open-state-changed', (menu, isOpen) => {
// Whenever the menu is opened, select today
@@ -546,19 +565,19 @@ class DateMenuButton extends PanelMenu.Button {
// Fill up the first column
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
let boxLayout = new CalendarColumnLayout(this._calendar.actor);
let boxLayout = new CalendarColumnLayout(this._calendar);
vbox = new St.Widget({ style_class: 'datemenu-calendar-column',
layout_manager: boxLayout });
boxLayout.hookup_style(vbox);
hbox.add(vbox);
this._date = new TodayButton(this._calendar);
vbox.add_actor(this._date.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',
x_expand: true, x_fill: true,
@@ -571,10 +590,10 @@ class DateMenuButton extends PanelMenu.Button {
this._displaysSection.add_actor(displaysBox);
this._clocksItem = new WorldClocksSection();
displaysBox.add(this._clocksItem.actor, { x_fill: true });
displaysBox.add(this._clocksItem, { x_fill: true });
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

View File

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

View File

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

View File

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

View File

@@ -286,7 +286,7 @@ var ExtensionManager = class {
reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
let { uuid, dir, type } = oldExtension;
// Then unload the old extension.
this.unloadExtension(oldExtension);

View File

@@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals;
const { Clutter, GObject, IBus, St } = imports.gi;
const BoxPointer = imports.ui.boxpointer;
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',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
var CandidateArea = class CandidateArea {
constructor() {
this.actor = new St.BoxLayout({ vertical: true,
reactive: true,
visible: false });
var CandidateArea = GObject.registerClass({
Signals: {
'candidate-clicked': { param_types: [GObject.TYPE_UINT,
GObject.TYPE_UINT,
Clutter.ModifierType.$gtype] },
'cursor-down': {},
'cursor-up': {},
'next-page': {},
'previous-page': {},
}
}, class CandidateArea extends St.BoxLayout {
_init() {
super._init({
vertical: true,
reactive: true,
visible: false
});
this._candidateBoxes = [];
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
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._candidateLabel, { y_fill: false });
this._candidateBoxes.push(box);
this.actor.add(box);
this.add(box);
let j = i;
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._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._buttonBox.add(this._nextButton, { expand: true });
this.actor.add(this._buttonBox);
this.add(this._buttonBox);
this._previousButton.connect('clicked', () => {
this.emit('previous-page');
@@ -72,6 +70,18 @@ var CandidateArea = class CandidateArea {
this._cursorPosition = 0;
}
vfunc_scroll_event(scrollEvent) {
switch (scrollEvent.direction) {
case Clutter.ScrollDirection.UP:
this.emit('cursor-up');
break;
case Clutter.ScrollDirection.DOWN:
this.emit('cursor-down');
break;
}
return Clutter.EVENT_PROPAGATE;
}
setOrientation(orientation) {
if (this._orientation == orientation)
return;
@@ -79,15 +89,15 @@ var CandidateArea = class CandidateArea {
this._orientation = orientation;
if (this._orientation == IBus.Orientation.HORIZONTAL) {
this.actor.vertical = false;
this.actor.remove_style_class_name('vertical');
this.actor.add_style_class_name('horizontal');
this.vertical = false;
this.remove_style_class_name('vertical');
this.add_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-previous-symbolic';
this._nextButton.child.icon_name = 'go-next-symbolic';
} else { // VERTICAL || SYSTEM
this.actor.vertical = true;
this.actor.add_style_class_name('vertical');
this.actor.remove_style_class_name('horizontal');
this.vertical = true;
this.add_style_class_name('vertical');
this.remove_style_class_name('horizontal');
this._previousButton.child.icon_name = 'go-up-symbolic';
this._nextButton.child.icon_name = 'go-down-symbolic';
}
@@ -121,19 +131,23 @@ var CandidateArea = class CandidateArea {
this._previousButton.reactive = wrapsAround || page > 0;
this._nextButton.reactive = wrapsAround || page < nPages - 1;
}
};
Signals.addSignalMethods(CandidateArea.prototype);
});
var CandidatePopup = class CandidatePopup {
constructor() {
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer';
Main.layoutManager.addChrome(this._boxPointer);
var CandidatePopup = GObject.registerClass(
class IbusCandidatePopup extends BoxPointer.BoxPointer {
_init() {
super._init(St.Side.TOP);
this.visible = false;
this.style_class = 'candidate-popup-boxpointer';
this._dummyCursor = new St.Widget({ opacity: 0 });
Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
Main.layoutManager.addChrome(this);
let box = new St.BoxLayout({ style_class: 'candidate-popup-content',
vertical: true });
this._boxPointer.bin.set_child(box);
this.bin.set_child(box);
this._preeditText = new St.Label({ style_class: 'candidate-popup-text',
visible: false });
@@ -144,7 +158,7 @@ var CandidatePopup = class CandidatePopup {
box.add(this._auxText);
this._candidateArea = new CandidateArea();
box.add(this._candidateArea.actor);
box.add(this._candidateArea);
this._candidateArea.connect('previous-page', () => {
this._panelService.page_up();
@@ -222,7 +236,7 @@ var CandidatePopup = class CandidatePopup {
this._updateVisibility();
});
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
this._candidateArea.actor.visible = visible;
this._candidateArea.visible = visible;
this._updateVisibility();
let nCandidates = lookupTable.get_number_of_candidates();
@@ -258,37 +272,39 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
});
panelService.connect('show-lookup-table', () => {
this._candidateArea.actor.show();
this._candidateArea.show();
this._updateVisibility();
});
panelService.connect('hide-lookup-table', () => {
this._candidateArea.actor.hide();
this._candidateArea.hide();
this._updateVisibility();
});
panelService.connect('focus-out', () => {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
this.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});
}
_setDummyCursorGeometry(x, y, w, h) {
Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
if (this._boxPointer.visible)
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._dummyCursor.set_position(Math.round(x), Math.round(y));
this._dummyCursor.set_size(Math.round(w), Math.round(h));
if (this.visible)
this.setPosition(this._dummyCursor, 0);
}
_updateVisibility() {
let isVisible = (!Main.keyboard.visible &&
(this._preeditText.visible ||
this._auxText.visible ||
this._candidateArea.actor.visible));
this._candidateArea.visible));
if (isVisible) {
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.raise_top();
this.setPosition(this._dummyCursor, 0);
this.open(BoxPointer.PopupAnimation.NONE);
this.raise_top();
} else {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
this.close(BoxPointer.PopupAnimation.NONE);
}
}
@@ -298,4 +314,4 @@ var CandidatePopup = class CandidatePopup {
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
}
};
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, PaginatedIconGrid */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
const Params = imports.misc.params;
const Main = imports.ui.main;
@@ -142,6 +142,10 @@ class BaseIcon extends St.Bin {
zoomOutActor(this.child);
}
animateZoomOutAtPos(x, y) {
zoomOutActorAtPos(this.child, x, y);
}
update() {
this._createIconTexture(this.iconSize);
}
@@ -152,10 +156,15 @@ function clamp(value, min, max) {
}
function zoomOutActor(actor) {
let [x, y] = actor.get_transformed_position();
zoomOutActorAtPos(actor, x, y);
}
function zoomOutActorAtPos(actor, x, y) {
let actorClone = new Clutter.Clone({ source: actor,
reactive: false });
let [width, height] = actor.get_transformed_size();
let [x, y] = actor.get_transformed_position();
actorClone.set_size(width, height);
actorClone.set_position(x, y);
actorClone.opacity = 255;
@@ -222,18 +231,18 @@ var IconGrid = GObject.registerClass({
this._fixedHItemSize = this._fixedVItemSize = undefined;
this.connect('style-changed', this._onStyleChanged.bind(this));
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
this.connect('notify::mapped', () => {
if (!this.mapped)
this._resetAnimationActors();
});
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
vfunc_unmap() {
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
this._resetAnimationActors();
super.vfunc_unmap();
}
_onDestroy() {
if (this._updateIconSizesLaterId) {
Meta.later_remove (this._updateIconSizesLaterId);
@@ -273,9 +282,9 @@ var IconGrid = GObject.registerClass({
return [0, 0];
let nChildren = this.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
let nColumns = this._colLimit
? Math.min(this._colLimit, nChildren)
: nChildren;
let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing();
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
@@ -393,7 +402,7 @@ var IconGrid = GObject.registerClass({
let allocationBox = this.get_allocation_box();
let paintBox = themeNode.get_paint_box(allocationBox);
let origin = new Clutter.Vertex();
let origin = new Graphene.Point3D();
origin.x = paintBox.x1 - allocationBox.x1;
origin.y = paintBox.y1 - allocationBox.y1;
origin.z = 0.0;
@@ -708,13 +717,13 @@ var IconGrid = GObject.registerClass({
this._items.push(item);
if (index !== undefined)
this.insert_child_at_index(item.actor, index);
this.insert_child_at_index(item, index);
else
this.add_actor(item.actor);
this.add_actor(item);
}
removeItem(item) {
this.remove_child(item.actor);
this.remove_child(item);
}
getItemAtIndex(index) {
@@ -787,8 +796,9 @@ var IconGrid = GObject.registerClass({
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
let neededSpacePerItem = (neededWidth > neededHeight)
? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
@@ -953,7 +963,7 @@ var PaginatedIconGrid = GObject.registerClass({
*/
openExtraSpace(sourceItem, side, nRows) {
let children = this._getVisibleChildren();
let index = children.indexOf(sourceItem.actor);
let index = children.indexOf(sourceItem);
if (index == -1)
throw new Error('Item not found.');
@@ -963,8 +973,7 @@ var PaginatedIconGrid = GObject.registerClass({
let childrenPerRow = this._childrenPerPage / this._rowsPerPage;
let sourceRow = Math.floor((index - pageOffset) / childrenPerRow);
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1
: sourceRow;
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 : sourceRow;
let nRowsBelow = this._rowsPerPage - nRowsAbove;
let nRowsUp, nRowsDown;

View File

@@ -76,8 +76,9 @@ var InhibitShortcutsDialog = GObject.registerClass({
let name = this._app ? this._app.get_name() : this._window.title;
/* Translators: %s is an application name like "Settings" */
let title = name ? _("%s wants to inhibit shortcuts").format(name)
: _("Application wants to inhibit shortcuts");
let title = name
? _("%s wants to inhibit shortcuts").format(name)
: _("Application wants to inhibit shortcuts");
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
let contentParams = { icon, title };

View File

@@ -28,23 +28,23 @@ class KbdA11yDialog extends GObject.Object {
if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
title = enabled
? _("Slow Keys Turned On")
: _("Slow Keys Turned Off");
body = _("You just held down the Shift key for 8 seconds. This is the shortcut " +
"for the Slow Keys feature, which affects the way your keyboard works.");
} else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");
body = enabled ?
_("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.") :
_("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
title = enabled
? _("Sticky Keys Turned On")
: _("Sticky Keys Turned Off");
body = enabled
? _("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.")
: _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
} else {
return;
}

View File

@@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Keyboard */
/* exported KeyboardManager */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals;
@@ -89,8 +89,11 @@ class KeyContainer extends St.Widget {
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
column_homogeneous: true,
row_homogeneous: true });
super._init({ layout_manager: gridLayout,
x_expand: true, y_expand: true });
super._init({
layout_manager: gridLayout,
x_expand: true,
y_expand: true
});
this._gridLayout = gridLayout;
this._currentRow = 0;
this._currentCol = 0;
@@ -104,9 +107,10 @@ class KeyContainer extends St.Widget {
this._currentRow++;
this._currentCol = 0;
let row = new Object();
row.keys = [];
row.width = 0;
let row = {
keys: [],
width: 0,
};
this._rows.push(row);
}
@@ -160,24 +164,23 @@ class KeyContainer extends St.Widget {
}
});
var Suggestions = class {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'word-suggestions',
vertical: false });
this.actor.show();
var Suggestions = GObject.registerClass(
class Suggestions extends St.BoxLayout {
_init() {
super._init({ style_class: 'word-suggestions', vertical: false });
this.show();
}
add(word, callback) {
let button = new St.Button({ label: word });
button.connect('clicked', callback);
this.actor.add(button);
this.add(button);
}
clear() {
this.actor.remove_all_children();
this.remove_all_children();
}
};
Signals.addSignalMethods(Suggestions.prototype);
});
var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
constructor(actor) {
@@ -242,17 +245,25 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
}
};
var Key = class Key {
constructor(key, extendedKeys) {
var Key = GObject.registerClass({
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.keyButton = this._makeKey(this.key);
/* Add the key in a container, so keys can be padded without losing
* logical proportions between those.
*/
this.actor = new St.BoxLayout ({ style_class: 'key-container' });
this.actor.add(this.keyButton, { expand: true, x_fill: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
this.add(this.keyButton, { expand: true, x_fill: true });
this.connect('destroy', this._onDestroy.bind(this));
this._extended_keys = extendedKeys;
this._extended_keyboard = null;
@@ -460,8 +471,7 @@ var Key = class Key {
else
this.keyButton.remove_style_pseudo_class('latched');
}
};
Signals.addSignalMethods(Key.prototype);
});
var KeyboardModel = class {
constructor(groupName) {
@@ -589,7 +599,6 @@ var EmojiPager = GObject.registerClass({
reactive: true,
clip_to_allocation: true
});
this._sections = sections;
this._nCols = nCols;
this._nRows = nRows;
@@ -800,7 +809,7 @@ var EmojiPager = GObject.registerClass({
this.emit('emoji', str);
});
gridLayout.attach(key.actor, col, row, 1, 1);
gridLayout.attach(key, col, row, 1, 1);
col++;
if (col >= this._nCols) {
@@ -842,7 +851,7 @@ var EmojiPager = GObject.registerClass({
}
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) {
@@ -857,8 +866,21 @@ var EmojiPager = GObject.registerClass({
}
});
var EmojiSelection = class EmojiSelection {
constructor() {
var EmojiSelection = GObject.registerClass({
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 = [
{ first: 'grinning face', label: '🙂️' },
{ first: 'selfie', label: '👍️' },
@@ -873,38 +895,44 @@ var EmojiSelection = class EmojiSelection {
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.connect('page-changed', (pager, section, page, nPages) => {
this._onPageChanged(section, page, nPages);
this._emojiPager.connect('page-changed', (pager, sectionLabel, page, nPages) => {
this._onPageChanged(sectionLabel, page, nPages);
});
this._emojiPager.connect('emoji', (pager, 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.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
this._pageIndicator = new PageIndicators.PageIndicators(
Clutter.Orientation.HORIZONTAL
);
this.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
this._pageIndicator.setReactive(false);
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);
}
_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.setCurrentPage(page);
for (let i = 0; i < this._sections.length; i++) {
let sect = this._sections[i];
sect.button.setLatched(section == sect);
sect.button.setLatched(sectionLabel == sect.label);
}
}
@@ -960,14 +988,14 @@ var EmojiSelection = class EmojiSelection {
key = new Key('ABC', []);
key.keyButton.add_style_class_name('default-key');
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++) {
let section = this._sections[i];
key = new Key(section.label, []);
key.connect('released', () => this._emojiPager.setCurrentSection(section, 0));
row.appendKey(key.actor);
row.appendKey(key);
section.button = key;
}
@@ -976,9 +1004,9 @@ var EmojiSelection = class EmojiSelection {
key.keyButton.add_style_class_name('default-key');
key.keyButton.add_style_class_name('hide-key');
key.connect('released', () => {
this.emit('hide');
this.emit('close-request');
});
row.appendKey(key.actor);
row.appendKey(key);
row.layoutButtons();
let actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
@@ -992,11 +1020,14 @@ var EmojiSelection = class EmojiSelection {
return actor;
}
};
Signals.addSignalMethods(EmojiSelection.prototype);
});
var Keypad = class Keypad {
constructor() {
var Keypad = GObject.registerClass({
Signals: {
'keyval': { param_types: [GObject.TYPE_UINT] },
}
}, class Keypad extends AspectContainer {
_init() {
let keys = [
{ label: '1', keyval: Clutter.KEY_1, left: 0, top: 0 },
{ label: '2', keyval: Clutter.KEY_2, left: 1, top: 0 },
@@ -1012,14 +1043,17 @@ var Keypad = class Keypad {
{ keyval: Clutter.KEY_Return, extraClassName: 'enter-key', left: 3, top: 1, height: 2 },
];
this.actor = new AspectContainer({ layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
super._init({
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true
});
let gridLayout = new Clutter.GridLayout({ orientation: Clutter.Orientation.HORIZONTAL,
column_homogeneous: true,
row_homogeneous: 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++) {
let cur = keys[i];
@@ -1031,86 +1065,32 @@ var Keypad = class Keypad {
let w, h;
w = cur.width || 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', () => {
this.emit('keyval', cur.keyval);
});
}
}
};
Signals.addSignalMethods(Keypad.prototype);
});
var Keyboard = class Keyboard {
var KeyboardManager = class KeyBoardManager {
constructor() {
this.actor = 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._keyboard = null;
this._a11yApplicationsSettings = new Gio.Settings({ schema_id: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', this._syncEnabled.bind(this));
this._lastDeviceId = null;
this._suggestions = null;
this._emojiKeyVisible = Meta.is_wayland_compositor();
Meta.get_backend().connect('last-device-changed', (backend, deviceId) => {
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId);
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;
if (device.get_device_name().indexOf('XTEST') < 0) {
this._lastDeviceId = deviceId;
this._syncEnabled();
}
});
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 device = manager.get_device(deviceId);
if (!device.get_device_name().includes('XTEST')) {
this._lastDeviceId = deviceId;
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() {
@@ -1127,38 +1107,143 @@ var Keyboard = class Keyboard {
}
_syncEnabled() {
let wasEnabled = this._enabled;
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
this._enabled = this._enableKeyboard || this._lastDeviceIsTouchscreen();
if (!this._enabled && !this._keyboardController)
let enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
let enabled = enableKeyboard || this._lastDeviceIsTouchscreen();
if (!enabled && !this._keyboard)
return;
if (this._enabled && !this._keyboardController)
this._setupKeyboard();
else if (!this._enabled)
this.setCursorLocation(null);
if (!this._enabled && wasEnabled)
if (enabled && !this._keyboard) {
this._keyboard = new Keyboard();
} else if (!enabled && this._keyboard) {
this._keyboard.setCursorLocation(null);
Main.layoutManager.hideKeyboard(true);
this._keyboard.destroy();
this._keyboard = null;
}
}
_destroyKeyboard() {
if (this._keyboardNotifyId)
this._keyboardController.disconnect(this._keyboardNotifyId);
if (this._keyboardGroupsChangedId)
this._keyboardController.disconnect(this._keyboardGroupsChangedId);
if (this._keyboardStateId)
this._keyboardController.disconnect(this._keyboardStateId);
if (this._emojiKeyVisibleId)
this._keyboardController.disconnect(this._emojiKeyVisibleId);
if (this._keypadVisibleId)
this._keyboardController.disconnect(this._keypadVisibleId);
if (this._focusNotifyId)
global.stage.disconnect(this._focusNotifyId);
get keyboardActor() {
return this._keyboard;
}
get visible() {
return this._keyboard && this._keyboard.visible;
}
open(monitor) {
if (this._keyboard)
this._keyboard.open(monitor);
}
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._keyboard = null;
this.actor.destroy();
this.actor = null;
this._keyboardController = 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) {
this._languagePopup.destroy();
@@ -1167,9 +1252,8 @@ var Keyboard = class Keyboard {
}
_setupKeyboard() {
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
Main.layoutManager.keyboardBox.add_actor(this);
Main.layoutManager.trackChrome(this);
this._keyboardController = new KeyboardController();
@@ -1177,30 +1261,28 @@ var Keyboard = class Keyboard {
this._currentPage = null;
this._suggestions = new Suggestions();
this.actor.add(this._suggestions.actor,
{ x_align: St.Align.MIDDLE,
x_fill: false });
this.add(this._suggestions, { x_align: St.Align.MIDDLE, x_fill: false });
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.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._keyboardController.commitString(emoji);
});
this._aspectContainer.add_child(this._emojiSelection.actor);
this._emojiSelection.actor.hide();
this._aspectContainer.add_child(this._emojiSelection);
this._emojiSelection.hide();
this._keypad = new Keypad();
this._keypad.connect('keyval', (keypad, keyval) => {
this._connectSignal(this._keypad, 'keyval', (_keypad, keyval) => {
this._keyboardController.keyvalPress(keyval);
this._keyboardController.keyvalRelease(keyval);
});
this._aspectContainer.add_child(this._keypad.actor);
this._keypad.actor.hide();
this._aspectContainer.add_child(this._keypad);
this._keypad.hide();
this._keypadVisible = false;
this._ensureKeysForGroup(this._keyboardController.getCurrentGroup());
@@ -1209,16 +1291,22 @@ var Keyboard = class Keyboard {
// Keyboard models are defined in LTR, we must override
// the locale setting in order to avoid flipping the
// 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._keyboardGroupsChangedId = this._keyboardController.connect('groups-changed', this._onKeyboardGroupsChanged.bind(this));
this._keyboardStateId = this._keyboardController.connect('panel-state', this._onKeyboardStateChanged.bind(this));
this._keypadVisibleId = this._keyboardController.connect('keypad-visible', this._onKeypadVisible.bind(this));
this._focusNotifyId = global.stage.connect('notify::key-focus', this._onKeyFocusChanged.bind(this));
this._connectSignal(this._keyboardController, 'active-group',
this._onGroupChanged.bind(this));
this._connectSignal(this._keyboardController, 'groups-changed',
this._onKeyboardGroupsChanged.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())
this._emojiKeyVisibleId = this._keyboardController.connect('emoji-visible', this._onEmojiKeyVisible.bind(this));
this._connectSignal(this._keyboardController, 'emoji-visible',
this._onEmojiKeyVisible.bind(this));
this._relayout();
}
@@ -1234,17 +1322,17 @@ var Keyboard = class Keyboard {
return;
if (!(focus instanceof Clutter.Text)) {
this.hide();
this.close();
return;
}
if (!this._showIdleId) {
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex);
this.open(Main.layoutManager.focusIndex);
this._showIdleId = 0;
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');
}
}
@@ -1308,7 +1396,7 @@ var Keyboard = class Keyboard {
this._setActiveLayer(0);
});
layout.appendKey(button.actor, button.keyButton.keyWidth);
layout.appendKey(button, button.keyButton.keyWidth);
}
}
@@ -1356,7 +1444,7 @@ var Keyboard = class Keyboard {
if (keyval != null)
this._keyboardController.keyvalRelease(keyval);
else if (action == 'hide')
this.hide();
this.close();
else if (action == 'languageMenu')
this._popupLanguageMenu(actor);
else if (action == 'emoji')
@@ -1379,7 +1467,7 @@ var Keyboard = class Keyboard {
/* Only hide the key actor, so the container still takes space */
extraButton.keyButton.hide();
} else {
extraButton.actor.hide();
extraButton.hide();
}
extraButton.setWidth(1.5);
} else if (key.right && numKeys > 8) {
@@ -1390,7 +1478,7 @@ var Keyboard = class Keyboard {
extraButton.setWidth(1.5);
}
layout.appendKey(extraButton.actor, extraButton.keyButton.keyWidth);
layout.appendKey(extraButton, extraButton.keyButton.keyWidth);
}
}
@@ -1401,7 +1489,7 @@ var Keyboard = class Keyboard {
_setEmojiActive(active) {
this._emojiActive = active;
this._emojiSelection.actor.visible = this._emojiActive;
this._emojiSelection.visible = this._emojiActive;
this._updateCurrentPageVisible();
}
@@ -1469,12 +1557,12 @@ var Keyboard = class Keyboard {
_relayout() {
let monitor = Main.layoutManager.keyboardMonitor;
if (this.actor == null || monitor == null)
if (!monitor)
return;
let maxHeight = monitor.height / 3;
this.actor.width = monitor.width;
this.actor.height = maxHeight;
this.width = monitor.width;
this.height = maxHeight;
}
_onGroupChanged() {
@@ -1483,7 +1571,7 @@ var Keyboard = class Keyboard {
}
_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 => {
c.destroy();
});
@@ -1497,7 +1585,7 @@ var Keyboard = class Keyboard {
return;
this._keypadVisible = visible;
this._keypad.actor.visible = this._keypadVisible;
this._keypad.visible = this._keypadVisible;
this._updateCurrentPageVisible();
}
@@ -1522,9 +1610,9 @@ var Keyboard = class Keyboard {
return;
if (enabled)
this.show(Main.layoutManager.focusIndex);
this.open(Main.layoutManager.focusIndex);
else
this.hide();
this.close();
}
_setActiveLayer(activeLevel) {
@@ -1551,12 +1639,6 @@ var Keyboard = class Keyboard {
this._updateCurrentPageVisible();
}
shouldTakeEvent(event) {
let actor = event.get_source();
return Main.layoutManager.keyboardBox.contains(actor) ||
!!actor._extended_keys || !!actor.extended_key;
}
_clearKeyboardRestTimer() {
if (!this._keyboardRestingId)
return;
@@ -1564,10 +1646,7 @@ var Keyboard = class Keyboard {
this._keyboardRestingId = 0;
}
show(monitor) {
if (!this._enabled)
return;
open(monitor) {
this._clearShowIdle();
this._keyboardRequested = true;
@@ -1584,13 +1663,13 @@ var Keyboard = class Keyboard {
KEYBOARD_REST_TIME,
() => {
this._clearKeyboardRestTimer();
this._show(monitor);
this._open(monitor);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
}
_show(monitor) {
_open(monitor) {
if (!this._keyboardRequested)
return;
@@ -1606,10 +1685,7 @@ var Keyboard = class Keyboard {
}
}
hide() {
if (!this._enabled)
return;
close() {
this._clearShowIdle();
this._keyboardRequested = false;
@@ -1621,13 +1697,13 @@ var Keyboard = class Keyboard {
KEYBOARD_REST_TIME,
() => {
this._clearKeyboardRestTimer();
this._hide();
this._close();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._keyboardRestingId, '[gnome-shell] this._clearKeyboardRestTimer');
}
_hide() {
_close() {
if (this._keyboardRequested)
return;
@@ -1644,7 +1720,7 @@ var Keyboard = class Keyboard {
if (!this._suggestions)
return;
this._suggestions.add(text, callback);
this._suggestions.actor.show();
this._suggestions.show();
}
_clearShowIdle() {
@@ -1721,7 +1797,7 @@ var Keyboard = class Keyboard {
this._oskFocusWindow = window;
}
};
});
var KeyboardController = class {
constructor() {

View File

@@ -606,17 +606,17 @@ var LayoutManager = GObject.registerClass({
return;
}
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,
coordinate: Clutter.BindCoordinate.ALL });
this._systemBackground.actor.add_constraint(constraint);
this._systemBackground.add_constraint(constraint);
let signalId = this._systemBackground.connect('loaded', () => {
this._systemBackground.disconnect(signalId);
this._systemBackground.actor.show();
this._systemBackground.show();
global.stage.show();
this._prepareStartupAnimation();
@@ -722,7 +722,7 @@ var LayoutManager = GObject.registerClass({
this._coverPane.destroy();
this._coverPane = null;
this._systemBackground.actor.destroy();
this._systemBackground.destroy();
this._systemBackground = null;
this._startingUp = false;
@@ -771,8 +771,7 @@ var LayoutManager = GObject.registerClass({
this.keyboardBox.ease({
anchor_y: 0,
opacity: 0,
duration: immediate ? 0
: KEYBOARD_ANIMATION_TIME,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._hideKeyboardComplete();
@@ -856,8 +855,9 @@ var LayoutManager = GObject.registerClass({
index = this._findActor(ancestor);
}
let ancestorData = ancestor ? this._trackedActors[index]
: defaultParams;
let ancestorData = ancestor
? this._trackedActors[index]
: defaultParams;
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
@@ -1015,11 +1015,6 @@ var LayoutManager = GObject.registerClass({
if (Main.modalCount > 0)
return GLib.SOURCE_REMOVE;
// Bug workaround - get_transformed_position()/get_transformed_size() don't work after
// a change in stage size until the first pick or paint.
// https://bugzilla.gnome.org/show_bug.cgi?id=761565
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0);
let rects = [], struts = [], i;
let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow);
let wantsInputRegion = !isPopupMenuVisible;
@@ -1075,16 +1070,17 @@ var LayoutManager = GObject.registerClass({
side = Meta.Side.RIGHT;
else
continue;
} else if (x1 <= monitor.x)
} else if (x1 <= monitor.x) {
side = Meta.Side.LEFT;
else if (y1 <= monitor.y)
} else if (y1 <= monitor.y) {
side = Meta.Side.TOP;
else if (x2 >= monitor.x + monitor.width)
} else if (x2 >= monitor.x + monitor.width) {
side = Meta.Side.RIGHT;
else if (y2 >= monitor.y + monitor.height)
} else if (y2 >= monitor.y + monitor.height) {
side = Meta.Side.BOTTOM;
else
} else {
continue;
}
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 });
let strut = new Meta.Strut({ rect: strutRect, side: side });
@@ -1116,8 +1112,11 @@ var LayoutManager = GObject.registerClass({
//
// This class manages a "hot corner" that can toggle switching to
// overview.
var HotCorner = class HotCorner {
constructor(layoutManager, monitor, x, y) {
var HotCorner = GObject.registerClass(
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
// hot corner and has not left both the hot corner and a surrounding
// guard area (the "environs"). This avoids triggering the hot corner
@@ -1146,6 +1145,8 @@ var HotCorner = class HotCorner {
this._ripples = new Ripples.Ripples(px, py, 'ripple-box');
this._ripples.addTo(layoutManager.uiGroup);
this.connect('destroy', this._onDestroy.bind(this));
}
setBarrierSize(size) {
@@ -1185,11 +1186,14 @@ var HotCorner = class HotCorner {
_setupFallbackCornerIfNeeded(layoutManager) {
if (!global.display.supports_extended_barriers()) {
this.actor = new Clutter.Actor({ name: 'hot-corner-environs',
x: this._x, y: this._y,
width: 3,
height: 3,
reactive: true });
this.set({
name: 'hot-corner-environs',
x: this._x,
y: this._y,
width: 3,
height: 3,
reactive: true
});
this._corner = new Clutter.Actor({ name: 'hot-corner',
width: 1,
@@ -1198,19 +1202,16 @@ var HotCorner = class HotCorner {
reactive: true });
this._corner._delegate = this;
this.actor.add_child(this._corner);
layoutManager.addChrome(this.actor);
this.add_child(this._corner);
layoutManager.addChrome(this);
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
this._corner.set_position(this.actor.width - this._corner.width, 0);
this.actor.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
this._corner.set_position(this.width - this._corner.width, 0);
this.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
} else {
this._corner.set_position(0, 0);
}
this.actor.connect('leave-event',
this._onEnvironsLeft.bind(this));
this._corner.connect('enter-event',
this._onCornerEntered.bind(this));
this._corner.connect('leave-event',
@@ -1218,14 +1219,11 @@ var HotCorner = class HotCorner {
}
}
destroy() {
_onDestroy() {
this.setBarrierSize(0);
this._pressureBarrier.destroy();
this._pressureBarrier = null;
if (this.actor)
this.actor.destroy();
this._ripples.destroy();
}
@@ -1257,18 +1255,18 @@ var HotCorner = class HotCorner {
}
_onCornerLeft(actor, event) {
if (event.get_related() != this.actor)
if (event.get_related() != this)
this._entered = false;
// Consume event, otherwise this will confuse onEnvironsLeft
return Clutter.EVENT_STOP;
}
_onEnvironsLeft(actor, event) {
if (event.get_related() != this._corner)
vfunc_leave_event(crossingEvent) {
if (crossingEvent.related != this._corner)
this._entered = false;
return Clutter.EVENT_PROPAGATE;
}
};
});
var PressureBarrier = class PressureBarrier {
constructor(threshold, timeout, actionMode) {

View File

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

View File

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

View File

@@ -264,7 +264,7 @@ var Magnifier = class Magnifier {
zoomRegion.setViewPort(viewPort);
// We ignore the redundant width/height on the ROI
let fixedROI = new Object(roi);
let fixedROI = Object.create(roi);
fixedROI.width = viewPort.width / xMagFactor;
fixedROI.height = viewPort.height / yMagFactor;
zoomRegion.setROI(fixedROI);
@@ -451,15 +451,11 @@ var Magnifier = class Magnifier {
* @clip: Flag to indicate whether to clip the crosshairs.
*/
setCrosshairsClip(clip) {
if (clip) {
if (this._crossHairs)
this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE);
} else {
// Setting no clipping on crosshairs means a zero sized clip
// rectangle.
if (this._crossHairs)
this._crossHairs.setClip([0, 0]);
}
if (!this._crossHairs)
return;
// Setting no clipping on crosshairs means a zero sized clip rectangle.
this._crossHairs.setClip(clip ? CROSSHAIRS_CLIP_SIZE : [0, 0]);
}
/**
@@ -1294,7 +1290,7 @@ var ZoomRegion = class ZoomRegion {
// Add a background for when the magnified uiGroup is scrolled
// out of view (don't want to see desktop showing through).
this._background = (new Background.SystemBackground()).actor;
this._background = new Background.SystemBackground();
mainGroup.add_actor(this._background);
// Clone the group that contains all of UI on the screen. This is the
@@ -1591,8 +1587,9 @@ var ZoomRegion = class ZoomRegion {
}
};
var Crosshairs = class Crosshairs {
constructor() {
var Crosshairs = GObject.registerClass(
class Crosshairs extends Clutter.Actor {
_init() {
// Set the group containing the crosshairs to three times the desktop
// size in case the crosshairs need to appear to be infinite in
@@ -1600,7 +1597,7 @@ var Crosshairs = class Crosshairs {
let groupWidth = global.screen_width * 3;
let groupHeight = global.screen_height * 3;
this._actor = new Clutter.Actor({
super._init({
clip_to_allocation: false,
width: groupWidth,
height: groupHeight
@@ -1609,10 +1606,10 @@ var Crosshairs = class Crosshairs {
this._horizRightHair = new Clutter.Actor();
this._vertTopHair = new Clutter.Actor();
this._vertBottomHair = new Clutter.Actor();
this._actor.add_actor(this._horizLeftHair);
this._actor.add_actor(this._horizRightHair);
this._actor.add_actor(this._vertTopHair);
this._actor.add_actor(this._vertBottomHair);
this.add_actor(this._horizLeftHair);
this.add_actor(this._horizRightHair);
this.add_actor(this._vertTopHair);
this.add_actor(this._vertBottomHair);
this._clipSize = [0, 0];
this._clones = [];
this.reCenter();
@@ -1622,7 +1619,7 @@ var Crosshairs = class Crosshairs {
}
_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();
}
@@ -1643,12 +1640,15 @@ var Crosshairs = class Crosshairs {
if (zoomRegion && magnifiedMouse) {
let container = magnifiedMouse.get_parent();
if (container) {
crosshairsActor = this._actor;
if (this._actor.get_parent() != null) {
crosshairsActor = new Clutter.Clone({ source: this._actor });
crosshairsActor = this;
if (this.get_parent() != null) {
crosshairsActor = new Clutter.Clone({ source: this });
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.raise_child(magnifiedMouse, crosshairsActor);
@@ -1667,7 +1667,7 @@ var Crosshairs = class Crosshairs {
* child actor if it was just a clone of the crosshairs actor.
*/
removeFromParent(childActor) {
if (childActor == this._actor)
if (childActor == this)
childActor.get_parent().remove_actor(childActor);
else
childActor.destroy();
@@ -1777,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:
* Reposition the horizontal and vertical hairs such that they cross at
@@ -1807,7 +1785,7 @@ var Crosshairs = class Crosshairs {
* @clipSize: Optional. If present, an array of the form [width, height].
*/
reCenter(clipSize) {
let [groupWidth, groupHeight] = this._actor.get_size();
let [groupWidth, groupHeight] = this.get_size();
let leftLength = this._horizLeftHair.get_width();
let topLength = this._vertTopHair.get_height();
let thickness = this._horizLeftHair.get_height();
@@ -1829,7 +1807,7 @@ var Crosshairs = class Crosshairs {
this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
}
};
});
var MagShaderEffects = class MagShaderEffects {
constructor(uiGroupClone) {

View File

@@ -189,7 +189,7 @@ function _initializeUI() {
messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel();
keyboard = new Keyboard.Keyboard();
keyboard = new Keyboard.KeyboardManager();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
componentManager = new Components.ComponentManager();
@@ -229,7 +229,11 @@ function _initializeUI() {
EndSessionDialog.init();
// We're ready for the session manager to move to the next phase
Meta.register_with_session();
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
Shell.util_sd_notify();
Meta.register_with_session();
return GLib.SOURCE_REMOVE;
});
_startDate = new Date();
@@ -258,6 +262,19 @@ function _initializeUI() {
});
}
let credentials = new Gio.Credentials();
if (credentials.get_unix_user() === 0) {
notify(_('Logged in as a privileged user'),
_('Running a session as a privileged user should be avoided for security reasons. If possible, you should log in as a normal user.'));
}
if (sessionMode.currentMode !== 'gdm' &&
sessionMode.currentMode !== 'initial-setup' &&
screenShield === null) {
notify(_('Screen Lock disabled'),
_('Screen Locking requires the GNOME display manager.'));
}
LoginManager.registerSessionWithGDM();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
@@ -386,7 +403,7 @@ function notify(msg, details) {
messageTray.add(source);
let notification = new MessageTray.Notification(source, msg, details);
notification.setTransient(true);
source.notify(notification);
source.showNotification(notification);
}
/**
@@ -705,7 +722,6 @@ function queueDeferredWork(workId) {
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => {
_runAllDeferredWork();

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

View File

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

View File

@@ -121,7 +121,7 @@ var ModalDialog = GObject.registerClass({
this.dialogLayout.opacity = 255;
if (this._lightbox)
this._lightbox.show();
this._lightbox.lightOn();
this.opacity = 0;
this.show();
this.ease({
@@ -253,7 +253,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.state = State.FADED_OUT
onComplete: () => (this.state = State.FADED_OUT)
});
}
});

View File

@@ -1,5 +1,5 @@
/* exported MediaSection */
const { Gio, Shell, St } = imports.gi;
const { Gio, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
@@ -19,9 +19,10 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
var MediaMessage = class MediaMessage extends MessageList.Message {
constructor(player) {
super('', '');
var MediaMessage = GObject.registerClass(
class MediaMessage extends MessageList.Message {
_init(player) {
super._init('', '');
this._player = player;
@@ -48,7 +49,7 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
this._update();
}
_onClicked() {
vfunc_clicked() {
this._player.raise();
Main.panel.closeCalendar();
}
@@ -71,14 +72,15 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
}
let isPlaying = this._player.status == 'Playing';
let iconName = isPlaying ? 'media-playback-pause-symbolic'
: 'media-playback-start-symbolic';
let iconName = isPlaying
? 'media-playback-pause-symbolic'
: 'media-playback-start-symbolic';
this._playPauseButton.child.icon_name = iconName;
this._updateNavButton(this._prevButton, this._player.canGoPrevious);
this._updateNavButton(this._nextButton, this._player.canGoNext);
}
};
});
var MprisPlayer = class MprisPlayer {
constructor(busName) {
@@ -193,9 +195,10 @@ var MprisPlayer = class MprisPlayer {
};
Signals.addSignalMethods(MprisPlayer.prototype);
var MediaSection = class MediaSection extends MessageList.MessageListSection {
constructor() {
super();
var MediaSection = GObject.registerClass(
class MediaSection extends MessageList.MessageListSection {
_init() {
super._init();
this._players = new Map();
@@ -246,4 +249,4 @@ var MediaSection = class MediaSection extends MessageList.MessageListSection {
if (newOwner && !oldOwner)
this._addPlayer(name);
}
};
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const { GdkPixbuf, Gio, GLib, GObject, Shell, St } = imports.gi;
const Config = imports.misc.config;
const Main = imports.ui.main;
@@ -346,8 +346,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
notification.setTransient(!!hints['transient']);
let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM
: MessageTray.PrivacyScope.USER);
notification.setPrivacyScope(privacyScope == 'system'
? MessageTray.PrivacyScope.SYSTEM
: MessageTray.PrivacyScope.USER);
let sourceGIcon = source.useNotificationIcon ? gicon : null;
source.processNotification(notification, sourceGIcon);
@@ -411,10 +412,10 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
};
var FdoNotificationDaemonSource =
var FdoNotificationDaemonSource = GObject.registerClass(
class FdoNotificationDaemonSource extends MessageTray.Source {
constructor(title, pid, sender, appId) {
super(title);
_init(title, pid, sender, appId) {
super._init(title);
this.pid = pid;
this.app = this._getApp(appId);
@@ -463,7 +464,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
if (notification.resident && this.app && tracker.focus_app == this.app)
this.pushNotification(notification);
else
this.notify(notification);
this.showNotification(notification);
}
_getApp(appId) {
@@ -525,7 +526,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
return null;
}
}
};
});
const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW,
@@ -534,28 +535,29 @@ const PRIORITY_URGENCY_MAP = {
urgent: MessageTray.Urgency.CRITICAL
};
var GtkNotificationDaemonNotification =
var GtkNotificationDaemonNotification = GObject.registerClass(
class GtkNotificationDaemonNotification extends MessageTray.Notification {
constructor(source, notification) {
super(source);
_init(source, notification) {
super._init(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { "title": title,
"body": body,
"icon": gicon,
"urgent": urgent,
"priority": priority,
"buttons": buttons,
let { title,
body,
icon: gicon,
urgent,
priority,
buttons,
"default-action": defaultAction,
"default-action-target": defaultActionTarget,
"timestamp": time } = notification;
timestamp: time } = notification;
if (priority) {
let urgency = PRIORITY_URGENCY_MAP[priority.unpack()];
this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL);
} else if (urgent) {
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
this.setUrgency(urgent.unpack()
? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
} else {
this.setUrgency(MessageTray.Urgency.NORMAL);
}
@@ -588,8 +590,8 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
}
_onButtonClicked(button) {
let { 'action': action, 'target': actionTarget } = button;
this._activateAction(action.unpack(), actionTarget);
let { action, target } = button;
this._activateAction(action.unpack(), target);
}
activate() {
@@ -600,7 +602,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
serialize() {
return this._serialized;
}
};
});
const FdoApplicationIface = loadInterfaceXML('org.freedesktop.Application');
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
@@ -616,9 +618,9 @@ function getPlatformData() {
function InvalidAppError() {}
var GtkNotificationDaemonAppSource =
var GtkNotificationDaemonAppSource = GObject.registerClass(
class GtkNotificationDaemonAppSource extends MessageTray.Source {
constructor(appId) {
_init(appId) {
let objectPath = objectPathFromAppId(appId);
if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError();
@@ -627,7 +629,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!app)
throw new InvalidAppError();
super(app.get_name());
super._init(app.get_name());
this._appId = appId;
this._app = app;
@@ -688,7 +690,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
this._notifications[notificationId] = notification;
if (showBanner)
this.notify(notification);
this.showNotification(notification);
else
this.pushNotification(notification);
@@ -714,7 +716,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
}
return [this._appId, notifications];
}
};
});
const GtkNotificationsIface = loadInterfaceXML('org.gtk.Notifications');
@@ -740,7 +742,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
delete this._sources[appId];
this._saveNotifications();
});
source.connect('count-updated', this._saveNotifications.bind(this));
source.connect('notify::count', this._saveNotifications.bind(this));
Main.messageTray.add(source);
this._sources[appId] = source;
return source;

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -72,36 +72,108 @@ var ShellInfo = class {
if (undoCallback)
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 {
constructor() {
this._overviewCreated = false;
this._initCalled = false;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
}
get dash() {
return this._overview.dash;
}
get dashIconSize() {
logError(new Error('Usage of Overview.\'dashIconSize\' is deprecated, ' +
'use \'dash.iconSize\' property instead'));
return this.dash.iconSize;
}
get viewSelector() {
return this._overview.viewSelector;
}
get animationInProgress() {
return this._animationInProgress;
}
get visible() {
return this._visible;
}
get visibleTarget() {
return this._visibleTarget;
}
_createOverview() {
if (this._overviewCreated)
if (this._overview)
return;
if (this.isDummy)
return;
this._overviewCreated = true;
this._overview = new St.BoxLayout({ name: 'overview',
/* Translators: This is the main view to select
activities. See also note for "Activities" string. */
accessible_name: _("Overview"),
vertical: true });
this._overview.add_constraint(new LayoutManager.MonitorConstraint({ primary: true }));
this._overview._delegate = this;
// The main Background actors are inside global.window_group which are
// hidden when displaying the overview, so we create a new
// one. Instances of this class share a single CoglTexture behind the
@@ -116,11 +188,11 @@ var Overview = class {
this._activationTime = 0;
this.visible = false; // animating to overview, in overview, animating out
this._visible = false; // animating to overview, in overview, animating out
this._shown = false; // show() and not hide()
this._modal = false; // have a modal grab
this.animationInProgress = false;
this.visibleTarget = false;
this._animationInProgress = false;
this._visibleTarget = false;
// During transitions, we raise this to the top to avoid having the overview
// area be reactive; it causes too many issues such as double clicks on
@@ -129,9 +201,6 @@ var Overview = class {
reactive: true });
Main.layoutManager.overviewGroup.add_child(this._coverPane);
this._coverPane.connect('event', () => Clutter.EVENT_STOP);
Main.layoutManager.overviewGroup.add_child(this._overview);
this._coverPane.hide();
// XDND
@@ -213,41 +282,12 @@ var Overview = class {
if (this.isDummy)
return;
this._overview = new OverviewActor();
this._overview._delegate = this;
Main.layoutManager.overviewGroup.add_child(this._overview);
this._shellInfo = new ShellInfo();
// Add a clone of the panel to the overview so spacing and such is
// automatic
this._panelGhost = new St.Bin({ child: new Clutter.Clone({ source: Main.panel }),
reactive: false,
opacity: 0 });
this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ style_class: 'search-entry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
characters. */
hint_text: _("Type to search…"),
track_hover: true,
can_focus: true });
this._searchEntryBin = new St.Bin({ child: this._searchEntry,
x_align: St.Align.MIDDLE });
this._overview.add_actor(this._searchEntryBin);
// Create controls
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
this._dash = this._controls.dash;
this.viewSelector = this._controls.viewSelector;
// Add our same-line elements after the search entry
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
// TODO - recalculate everything when desktop size changes
this.dashIconSize = this._dash.iconSize;
this._dash.connect('icon-size-changed', () => {
this.dashIconSize = this._dash.iconSize;
});
Main.layoutManager.connect('monitors-changed', this._relayout.bind(this));
this._relayout();
}
@@ -426,7 +466,7 @@ var Overview = class {
focusSearch() {
this.show();
this._searchEntry.grab_key_focus();
this._overview.searchEntry.grab_key_focus();
}
fadeInDesktop() {
@@ -452,7 +492,7 @@ var Overview = class {
this._desktopFade.show();
this._desktopFade.ease({
opacity: 0,
mode: Clutter.Animates.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME
});
}
@@ -464,11 +504,11 @@ var Overview = class {
// the overview if the user both triggered the hot corner and
// clicked the Activities button.
shouldToggleByCornerOrButton() {
if (this.animationInProgress)
if (this._animationInProgress)
return false;
if (this._inItemDrag || this._inWindowDrag)
return false;
if (this._activationTime == 0 ||
if (!this._activationTime ||
GLib.get_monotonic_time() / GLib.USEC_PER_SEC - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
return true;
return false;
@@ -478,7 +518,7 @@ var Overview = class {
// We delay grab changes during animation so that when removing the
// overview we don't have a problem with the release of a press/release
// going to an application.
if (this.animationInProgress)
if (this._animationInProgress)
return true;
if (this._shown) {
@@ -520,12 +560,12 @@ var Overview = class {
_animateVisible() {
if (this.visible || this.animationInProgress)
if (this._visible || this._animationInProgress)
return;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
this._visible = true;
this._animationInProgress = true;
this._visibleTarget = true;
this._activationTime = GLib.get_monotonic_time() / GLib.USEC_PER_SEC;
Meta.disable_unredirect_for_display(global.display);
@@ -546,7 +586,7 @@ var Overview = class {
}
_showDone() {
this.animationInProgress = false;
this._animationInProgress = false;
this._desktopFade.hide();
this._coverPane.hide();
@@ -586,11 +626,11 @@ var Overview = class {
}
_animateNotVisible() {
if (!this.visible || this.animationInProgress)
if (!this._visible || this._animationInProgress)
return;
this.animationInProgress = true;
this.visibleTarget = false;
this._animationInProgress = true;
this._visibleTarget = false;
this.viewSelector.animateFromOverview();
@@ -616,8 +656,8 @@ var Overview = class {
this._desktopFade.hide();
this._coverPane.hide();
this.visible = false;
this.animationInProgress = false;
this._visible = false;
this._animationInProgress = false;
this.emit('hidden');
// Handle any calls to show* while we were hiding
@@ -633,14 +673,17 @@ var Overview = class {
if (this.isDummy)
return;
if (this.visible)
if (this._visible)
this.hide();
else
this.show();
}
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);

View File

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

View File

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

View File

@@ -20,14 +20,17 @@ var ANIMATION_DELAY = 100;
var PageIndicators = GObject.registerClass({
Signals: { 'page-activated': { param_types: [GObject.TYPE_INT] } }
}, class PageIndicators extends St.BoxLayout {
_init(vertical = true) {
super._init({ style_class: 'page-indicators',
vertical,
x_expand: true, y_expand: true,
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
reactive: true,
clip_to_allocation: true });
_init(orientation = Clutter.Orientation.VERTICAL) {
let vertical = orientation == Clutter.Orientation.VERTICAL;
super._init({
style_class: 'page-indicators',
vertical,
x_expand: true, y_expand: true,
x_align: vertical ? Clutter.ActorAlign.END : Clutter.ActorAlign.CENTER,
y_align: vertical ? Clutter.ActorAlign.CENTER : Clutter.ActorAlign.END,
reactive: true,
clip_to_allocation: true
});
this._nPages = 0;
this._currentPage = undefined;
this._reactive = true;
@@ -93,18 +96,26 @@ var PageIndicators = GObject.registerClass({
var AnimatedPageIndicators = GObject.registerClass(
class AnimatedPageIndicators extends PageIndicators {
_init() {
super._init(true);
super._init();
this.connect('destroy', this._onDestroy.bind(this));
}
this.connect('notify::mapped', () => {
if (!this.mapped)
return;
_onDestroy() {
if (this.animateLater) {
Meta.later_remove(this.animateLater);
this.animateLater = 0;
}
}
// Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE;
});
vfunc_map() {
super.vfunc_map();
// Implicit animations are skipped for unmapped actors, and our
// children aren't mapped yet, so defer to a later handler
this.animateLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.animateLater = 0;
this.animateIndicators(AnimationDirection.IN);
return GLib.SOURCE_REMOVE;
});
}
@@ -126,12 +137,14 @@ class AnimatedPageIndicators extends PageIndicators {
offset = children[0].width;
let isAnimationIn = animationDirection == AnimationDirection.IN;
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
INDICATORS_ANIMATION_DELAY_OUT;
let delay = isAnimationIn
? INDICATORS_ANIMATION_DELAY
: INDICATORS_ANIMATION_DELAY_OUT;
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
let totalAnimationTime = baseTime + delay * this._nPages;
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
INDICATORS_ANIMATION_MAX_TIME_OUT;
let maxTime = isAnimationIn
? INDICATORS_ANIMATION_MAX_TIME
: INDICATORS_ANIMATION_MAX_TIME_OUT;
if (totalAnimationTime > maxTime)
delay -= (totalAnimationTime - maxTime) / this._nPages;

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
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 BoxPointer = imports.ui.boxpointer;
@@ -15,6 +15,7 @@ var Ornament = {
NONE: 0,
DOT: 1,
CHECK: 2,
HIDDEN: 3,
};
function isPopupMenuItemVisible(child) {
@@ -96,12 +97,6 @@ var PopupBaseMenuItem = GObject.registerClass({
if (params.style_class)
this.add_style_class_name(params.style_class);
if (this._activatable) {
this.connect('button-press-event', this._onButtonPressEvent.bind(this));
this.connect('button-release-event', this._onButtonReleaseEvent.bind(this));
this.connect('touch-event', this._onTouchEvent.bind(this));
this.connect('key-press-event', this._onKeyPressEvent.bind(this));
}
if (params.reactive && params.hover)
this.bind_property('hover', this, 'active', GObject.BindingFlags.SYNC_CREATE);
}
@@ -123,32 +118,44 @@ var PopupBaseMenuItem = GObject.registerClass({
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.add_style_pseudo_class('active');
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.activate(event);
this.activate(Clutter.get_current_event());
return Clutter.EVENT_STOP;
}
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
vfunc_touch_event(touchEvent) {
if (!this._activatable)
return super.vfunc_touch_event(touchEvent);
if (touchEvent.type == Clutter.EventType.TOUCH_END) {
this.remove_style_pseudo_class('active');
this.activate(event);
this.activate(Clutter.get_current_event());
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.add_style_pseudo_class('active');
}
return Clutter.EVENT_PROPAGATE;
}
_onKeyPressEvent(actor, event) {
let state = event.get_state();
vfunc_key_press_event(keyEvent) {
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)
// then don't handle the key press here
@@ -159,9 +166,9 @@ var PopupBaseMenuItem = GObject.registerClass({
if (state)
return Clutter.EVENT_PROPAGATE;
let symbol = event.get_key_symbol();
let symbol = keyEvent.keyval;
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_PROPAGATE;
@@ -248,10 +255,12 @@ var PopupBaseMenuItem = GObject.registerClass({
} else if (ornament == Ornament.CHECK) {
this._ornamentLabel.text = '\u2713';
this.add_accessible_state(Atk.StateType.CHECKED);
} else if (ornament == Ornament.NONE) {
} else if (ornament == Ornament.NONE || ornament == Ornament.HIDDEN) {
this._ornamentLabel.text = '';
this.remove_accessible_state(Atk.StateType.CHECKED);
}
this._ornamentLabel.visible = ornament != Ornament.HIDDEN;
}
});
@@ -425,6 +434,7 @@ var PopupMenuBase = class {
throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`);
this.sourceActor = sourceActor;
this.focusActor = sourceActor;
this._parent = null;
if (styleClass !== undefined) {
@@ -549,7 +559,7 @@ var PopupMenuBase = class {
}
_connectItemSignals(menuItem) {
menuItem._activeChangeId = menuItem.connect('notify::active', (menuItem) => {
menuItem._activeChangeId = menuItem.connect('notify::active', menuItem => {
let active = menuItem.active;
if (active && this._activeMenuItem != menuItem) {
if (this._activeMenuItem)
@@ -613,8 +623,8 @@ var PopupMenuBase = class {
while (childBeforeIndex >= 0 && !isPopupMenuItemVisible(children[childBeforeIndex]))
childBeforeIndex--;
if (childBeforeIndex < 0
|| children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) {
if (childBeforeIndex < 0 ||
children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) {
menuItem.actor.hide();
return;
}
@@ -624,8 +634,8 @@ var PopupMenuBase = class {
while (childAfterIndex < children.length && !isPopupMenuItemVisible(children[childAfterIndex]))
childAfterIndex++;
if (childAfterIndex >= children.length
|| children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) {
if (childAfterIndex >= children.length ||
children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) {
menuItem.actor.hide();
return;
}
@@ -718,10 +728,11 @@ var PopupMenuBase = class {
this.disconnect(openStateChangeId);
menuItem.disconnect(destroyId);
});
} else if (menuItem instanceof PopupBaseMenuItem)
} else if (menuItem instanceof PopupBaseMenuItem) {
this._connectItemSignals(menuItem);
else
} else {
throw TypeError("Invalid argument to PopupMenuBase.addMenuItem()");
}
menuItem._setParent(this);
@@ -1125,7 +1136,7 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
this.add(expander, { expand: true });
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,
y_align: Clutter.ActorAlign.CENTER });
@@ -1180,8 +1191,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return this.menu.isOpen;
}
_onKeyPressEvent(actor, event) {
let symbol = event.get_key_symbol();
vfunc_key_press_event(keyPressEvent) {
let symbol = keyPressEvent.keyval;
if (symbol == Clutter.KEY_Right) {
this._setOpenState(true);
@@ -1192,14 +1203,14 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_STOP;
}
return super._onKeyPressEvent(actor, event);
return super.vfunc_key_press_event(keyPressEvent);
}
activate(_event) {
this._setOpenState(true);
}
_onButtonReleaseEvent() {
vfunc_button_release_event() {
// Since we override the parent, we need to manage what the parent does
// with the active style class
this.remove_style_pseudo_class('active');
@@ -1207,8 +1218,8 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return Clutter.EVENT_PROPAGATE;
}
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
vfunc_touch_event(touchEvent) {
if (touchEvent.type == Clutter.EventType.TOUCH_END) {
// Since we override the parent, we need to manage what the parent does
// with the active style class
this.remove_style_pseudo_class('active');
@@ -1296,18 +1307,20 @@ var PopupMenuManager = class {
if (open) {
if (this.activeMenu)
this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
this._grabHelper.grab({ actor: menu.actor, focus: menu.sourceActor,
onUngrab: isUser => {
this._closeMenu(isUser, menu);
} });
this._grabHelper.grab({
actor: menu.actor,
focus: menu.focusActor,
onUngrab: isUser => this._closeMenu(isUser, menu),
});
} else {
this._grabHelper.ungrab({ actor: menu.actor });
}
}
_changeMenu(newMenu) {
newMenu.open(this.activeMenu ? BoxPointer.PopupAnimation.FADE
: BoxPointer.PopupAnimation.FULL);
newMenu.open(this.activeMenu
? BoxPointer.PopupAnimation.FADE
: BoxPointer.PopupAnimation.FULL);
}
_onMenuSourceEnter(menu) {

View File

@@ -67,7 +67,7 @@ var Ripples = class Ripples {
delay,
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => ripple.visible = false
onComplete: () => (ripple.visible = false)
});
}

View File

@@ -104,7 +104,7 @@ class RunDialog extends ModalDialog.ModalDialog {
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entryText });
this._entryText.connect('activate', (o) => {
this._entryText.connect('activate', o => {
this.popModal();
this._run(o.get_text(),
Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK);

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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 Signals = imports.signals;
@@ -17,6 +17,8 @@ const MessageTray = imports.ui.messageTray;
const ShellDBus = imports.ui.shellDBus;
const SmartcardManager = imports.misc.smartcardManager;
const { adjustAnimationTime } = imports.ui.environment;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
const LOCK_DELAY_KEY = 'lock-delay';
@@ -46,21 +48,23 @@ var STANDARD_FADE_TIME = 10000;
var MANUAL_FADE_TIME = 300;
var CURTAIN_SLIDE_TIME = 300;
var Clock = class {
constructor() {
this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock',
vertical: true });
var Clock = GObject.registerClass(
class ScreenShieldClock extends St.BoxLayout {
_init() {
super._init({ style_class: 'screen-shield-clock', vertical: true });
this._time = new St.Label({ style_class: 'screen-shield-clock-time' });
this._date = new St.Label({ style_class: 'screen-shield-clock-date' });
this.actor.add(this._time, { x_align: St.Align.MIDDLE });
this.actor.add(this._date, { x_align: St.Align.MIDDLE });
this.add(this._time, { x_align: St.Align.MIDDLE });
this.add(this._date, { x_align: St.Align.MIDDLE });
this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
this._wallClock.connect('notify::clock', this._updateClock.bind(this));
this._updateClock();
this.connect('destroy', this._onDestroy.bind(this));
}
_updateClock() {
@@ -73,17 +77,20 @@ var Clock = class {
this._date.text = date.toLocaleFormat(dateFormat);
}
destroy() {
this.actor.destroy();
_onDestroy() {
this._wallClock.run_dispose();
}
};
});
var NotificationsBox = class {
constructor() {
this.actor = new St.BoxLayout({ vertical: true,
name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-container' });
var NotificationsBox = GObject.registerClass({
Signals: { 'wake-up-screen': {} }
}, class NotificationsBox extends St.BoxLayout {
_init() {
super._init({
vertical: true,
name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-container'
});
this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
hscrollbar_policy: St.PolicyType.NEVER });
@@ -91,7 +98,7 @@ var NotificationsBox = class {
style_class: 'screen-shield-notifications-container' });
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();
Main.messageTray.getSources().forEach(source => {
@@ -100,9 +107,11 @@ var NotificationsBox = class {
this._updateVisibility();
this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
_onDestroy() {
if (this._sourceAddedId) {
Main.messageTray.disconnect(this._sourceAddedId);
this._sourceAddedId = 0;
@@ -112,15 +121,13 @@ var NotificationsBox = class {
for (let [source, obj] of items) {
this._removeSource(source, obj);
}
this.actor.destroy();
}
_updateVisibility() {
this._notificationBox.visible =
this._notificationBox.get_children().some(a => a.visible);
this.actor.visible = this._notificationBox.visible;
this.visible = this._notificationBox.visible;
}
_makeNotificationCountText(count, isChat) {
@@ -173,8 +180,9 @@ var NotificationsBox = class {
let body = '';
if (n.bannerBodyText) {
body = n.bannerBodyMarkup ? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
body = n.bannerBodyMarkup
? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
}
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
@@ -221,14 +229,14 @@ var NotificationsBox = class {
this._showSource(source, obj, obj.sourceBox);
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);
});
obj.sourceTitleChangedId = source.connect('title-changed', source => {
obj.sourceTitleChangedId = source.connect('notify::title', source => {
this._titleChanged(source, obj);
});
obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => {
if (key == 'show-in-lock-screen')
obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => {
if (pspec.name == 'show-in-lock-screen')
this._visibleChanged(source, obj);
else
this._detailedChanged(source, obj);
@@ -335,8 +343,7 @@ var NotificationsBox = class {
this._sources.delete(source);
}
};
Signals.addSignalMethods(NotificationsBox.prototype);
});
var Arrow = GObject.registerClass(
class ScreenShieldArrow extends St.Bin {
@@ -485,7 +492,7 @@ var ScreenShield = class {
this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: 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' });
this.actor.add_actor(this._lockDialogGroup);
@@ -556,11 +563,11 @@ var ScreenShield = class {
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true,
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,
{ inhibitEvents: true,
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._cursorTracker = Meta.CursorTracker.get_for_display(global.display);
@@ -806,7 +813,7 @@ var ScreenShield = class {
this._maybeCancelDialog();
if (this._longLightbox.actor.visible) {
if (this._longLightbox.visible) {
// We're in the process of showing.
return;
}
@@ -831,7 +838,7 @@ var ScreenShield = class {
if (shouldLock) {
let lockTimeout = Math.max(
STANDARD_FADE_TIME,
adjustAnimationTime(STANDARD_FADE_TIME),
this._settings.get_uint(LOCK_DELAY_KEY) * 1000);
this._lockTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
@@ -848,8 +855,8 @@ var ScreenShield = class {
}
_activateFade(lightbox, time) {
Main.uiGroup.set_child_above_sibling(lightbox.actor, null);
lightbox.show(time);
Main.uiGroup.set_child_above_sibling(lightbox, null);
lightbox.lightOn(time);
if (this._becameActiveId == 0)
this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this));
@@ -878,19 +885,21 @@ var ScreenShield = class {
this._becameActiveId = 0;
if (this._isActive || this._isLocked) {
this._longLightbox.hide();
this._shortLightbox.hide();
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
} else {
this.deactivate(false);
}
}
_onLongLightboxShown() {
this.activate(false);
_onLongLightbox(lightBox) {
if (lightBox.active)
this.activate(false);
}
_onShortLightboxShown() {
this._completeLockScreenShown();
_onShortLightbox(lightBox) {
if (lightBox.active)
this._completeLockScreenShown();
}
showDialog() {
@@ -915,8 +924,8 @@ var ScreenShield = class {
this._lockScreenGroup.hide();
if (this._dialog) {
this._dialog.actor.grab_key_focus();
this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
this._dialog.grab_key_focus();
this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
}
}
@@ -964,7 +973,6 @@ var ScreenShield = class {
this._dialog = new constructor(this._lockDialogGroup);
let time = global.get_current_time();
if (!this._dialog.open(time, onPrimary)) {
// This is kind of an impossible error: we're already modal
@@ -1130,16 +1138,20 @@ var ScreenShield = class {
vertical: true,
style_class: 'screen-shield-contents-box' });
this._clock = new Clock();
this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true,
y_fill: true });
this._lockScreenContentsBox.add(this._clock, {
x_fill: true,
y_fill: true
});
this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._notificationsBox = new NotificationsBox();
this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
y_fill: true,
expand: true });
this._lockScreenContentsBox.add(this._notificationsBox, {
x_fill: true,
y_fill: true,
expand: true
});
this._hasLockScreen = true;
}
@@ -1232,8 +1244,8 @@ var ScreenShield = class {
this._dialog = null;
}
this._longLightbox.hide();
this._shortLightbox.hide();
this._longLightbox.lightOff();
this._shortLightbox.lightOff();
this.actor.hide();
if (this._becameActiveId != 0) {

View File

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

View File

@@ -317,7 +317,7 @@ async function runPerfScript(scriptModule, outputFile) {
for (let step of scriptModule.run()) {
try {
await step;
await step; // eslint-disable-line no-await-in-loop
} catch (err) {
log(`Script failed: ${err}\n${err.stack}`);
Meta.exit(Meta.ExitCode.ERROR);

View File

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

View File

@@ -92,11 +92,11 @@ const _modes = {
isLocked: false,
isPrimary: true,
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: Config.HAVE_NETWORKMANAGER ?
['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'] :
['polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'],
components: Config.HAVE_NETWORKMANAGER
? ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager']
: ['polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'],
panel: {
left: ['activities', 'appMenu'],

View File

@@ -151,9 +151,13 @@ var GnomeShell = class {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
let params = { 'device-id': GLib.Variant.new('u', device.get_device_id()),
'device-node': GLib.Variant.new('s', device.get_device_node()),
'timestamp': GLib.Variant.new('u', timestamp),
'action-mode': GLib.Variant.new('u', Main.actionMode) };
let deviceNode = device.get_device_node();
if (deviceNode)
params['device-node'] = GLib.Variant.new('s', deviceNode);
connection.emit_signal(destination,
this._dbusImpl.get_object_path(),
info ? info.name : null,

View File

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

View File

@@ -22,12 +22,7 @@ var Slider = GObject.registerClass({
accessible_role: Atk.Role.SLIDER
});
this.connect('button-press-event', this._startDragging.bind(this));
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._releaseId = 0;
this._dragging = false;
this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this));
@@ -62,8 +57,8 @@ var Slider = GObject.registerClass({
cr.$dispose();
}
_startDragging(actor, event) {
return this.startDragging(event);
vfunc_button_press_event() {
return this.startDragging(Clutter.get_current_event());
}
startDragging(event) {
@@ -83,11 +78,6 @@ var Slider = GObject.registerClass({
this._grabbedDevice = device;
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
// sure that no 'notify::value' signal is emitted before this one.
this.emit('drag-begin');
@@ -100,10 +90,10 @@ var Slider = GObject.registerClass({
_endDragging() {
if (this._dragging) {
if (this._releaseId)
if (this._releaseId) {
this.disconnect(this._releaseId);
if (this._motionId)
this.disconnect(this._motionId);
this._releaseId = 0;
}
if (this._grabbedSequence != null)
this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
@@ -119,7 +109,15 @@ var Slider = GObject.registerClass({
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 sequence = event.get_event_sequence();
@@ -127,9 +125,9 @@ var Slider = GObject.registerClass({
event.type() == Clutter.EventType.TOUCH_BEGIN) {
this.startDragging(event);
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)
return this._motionEvent(actor, event);
return this._motionEvent(this, event);
else if (event.type() == Clutter.EventType.TOUCH_END)
return this._endDragging();
}
@@ -160,8 +158,15 @@ var Slider = GObject.registerClass({
return Clutter.EVENT_STOP;
}
_onScrollEvent(actor, event) {
return this.scroll(event);
vfunc_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) {
@@ -171,8 +176,8 @@ var Slider = GObject.registerClass({
return Clutter.EVENT_STOP;
}
onKeyPressEvent(actor, event) {
let key = event.get_key_symbol();
vfunc_key_press_event(keyPressEvent) {
let key = keyPressEvent.keyval;
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
this.emit('drag-begin');

View File

@@ -102,7 +102,7 @@ class ATIndicator extends PanelMenu.Button {
_buildItemExtended(string, initialValue, writable, onSet) {
let widget = new PopupMenu.PopupSwitchMenuItem(string, initialValue);
if (!writable)
widget.actor.reactive = false;
widget.reactive = false;
else
widget.connect('toggled', item => {
onSet(item.state);
@@ -179,8 +179,8 @@ class ATIndicator extends PanelMenu.Button {
settings.is_writable(KEY_TEXT_SCALING_FACTOR),
enabled => {
if (enabled)
settings.set_double(KEY_TEXT_SCALING_FACTOR,
DPI_FACTOR_LARGE);
settings.set_double(
KEY_TEXT_SCALING_FACTOR, DPI_FACTOR_LARGE);
else
settings.reset(KEY_TEXT_SCALING_FACTOR);
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Gio, GnomeBluetooth } = imports.gi;
const { Gio, GnomeBluetooth, GObject } = imports.gi;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@@ -17,9 +17,11 @@ const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface
const HAD_BLUETOOTH_DEVICES_SETUP = 'had-bluetooth-devices-setup';
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'Bluetooth_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator();
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");
}
};
});

View File

@@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const BrightnessInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Power.Screen');
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super('display-brightness-symbolic');
var Indicator = GObject.registerClass({
GTypeName: 'Brightness_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._proxy = new BrightnessProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
(proxy, error) => {
if (error) {
@@ -45,7 +47,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
return this._slider.startDragging(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)
this._changeSlider(this._proxy.Brightness / 100.0);
}
};
});

View File

@@ -923,7 +923,7 @@ class InputSourceIndicator extends PanelMenu.Button {
}
_buildPropSection(properties) {
this._propSeparator.actor.hide();
this._propSeparator.hide();
this._propSection.actor.hide();
this._propSection.removeAll();
@@ -931,7 +931,7 @@ class InputSourceIndicator extends PanelMenu.Button {
if (!this._propSection.isEmpty()) {
this._propSection.actor.show();
this._propSeparator.actor.show();
this._propSeparator.show();
}
}
@@ -976,8 +976,8 @@ class InputSourceIndicator extends PanelMenu.Button {
item.prop = prop;
radioGroup.push(item);
item.radioGroup = radioGroup;
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ?
PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED
? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
item.connect('activate', () => {
if (item.prop.get_state() == IBus.PropState.CHECKED)
return;

View File

@@ -42,9 +42,11 @@ const GeoclueManager = Gio.DBusProxy.makeProxyWrapper(GeoclueIface);
var AgentIface = loadInterfaceXML('org.freedesktop.GeoClue2.Agent');
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'Location_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA });
this._settings.connect(`changed::${ENABLED}`,
@@ -168,8 +170,9 @@ var Indicator = class extends PanelMenu.SystemIndicator {
_updateMenuLabels() {
if (this._settings.get_boolean(ENABLED)) {
this._item.label.text = this._indicator.visible ? _("Location In Use")
: _("Location Enabled");
this._item.label.text = this._indicator.visible
? _("Location In Use")
: _("Location Enabled");
this._onOffAction.label.text = _("Disable");
} else {
this._item.label.text = _("Location Disabled");
@@ -221,7 +224,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._permStoreProxy = proxy;
}
};
});
function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));

View File

@@ -630,7 +630,6 @@ var NMWirelessDialogItem = GObject.registerClass({
can_focus: true,
reactive: true });
this.connect('key-focus-in', () => this.emit('selected'));
let action = new Clutter.ClickAction();
action.connect('clicked', () => this.grab_key_focus());
this.add_action(action);
@@ -659,6 +658,10 @@ var NMWirelessDialogItem = GObject.registerClass({
this._sync();
}
vfunc_key_focus_in() {
this.emit('selected');
}
_sync() {
this._signalIcon.icon_name = this._getSignalIcon();
}
@@ -860,7 +863,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
y_align: Clutter.ActorAlign.CENTER });
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',
text: _("No Networks") }));
this._stack.add_child(this._noNetworksBox);
@@ -909,8 +912,8 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._client.activate_connection_async(connection, this._device, null, null, null);
} else {
let accessPoints = network.accessPoints;
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT) ||
(accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
// 802.1x-enabled APs require further configuration, so they're
// handled in gnome-control-center
Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi',
@@ -1588,9 +1591,11 @@ var DeviceCategory = class extends PopupMenu.PopupMenuSection {
}
};
var NMApplet = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var NMApplet = GObject.registerClass({
GTypeName: 'Network_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._primaryIndicator = this._addIndicator();
this._vpnIndicator = this._addIndicator();
@@ -1676,7 +1681,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
'network-transmit-receive');
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
this._source.connect('destroy', () => this._source = null);
this._source.connect('destroy', () => (this._source = null));
Main.messageTray.add(this._source);
}
}
@@ -1706,7 +1711,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
this._notification.connect('destroy', () => {
this._notification = null;
});
this._source.notify(this._notification);
this._source.showNotification(this._notification);
}
_onActivationFailed(_device, _reason) {
@@ -1939,7 +1944,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
}
_syncNMState() {
this.indicators.visible = this._client.nm_running;
this.visible = this._client.nm_running;
this.menu.actor.visible = this._client.networking_enabled;
this._updateIcon();
@@ -1976,7 +1981,6 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
// or we get to full connectivity through other means
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
return;
} else if (result == PortalHelperResult.RECHECK) {
this._client.check_connectivity_async(null, (client, result) => {
try {
@@ -2059,4 +2063,4 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon();
this._vpnIndicator.visible = (this._vpnIndicator.icon_name != '');
}
};
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const Gio = imports.gi.Gio;
const { Gio, GObject } = imports.gi;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
@@ -15,9 +15,11 @@ const OBJECT_PATH = '/org/gnome/SettingsDaemon/Color';
const ColorInterface = loadInterfaceXML('org.gnome.SettingsDaemon.Color');
const ColorProxy = Gio.DBusProxy.makeProxyWrapper(ColorInterface);
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'NightLight_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator();
this._indicator.icon_name = 'night-light-symbolic';
@@ -58,10 +60,12 @@ var Indicator = class extends PanelMenu.SystemIndicator {
let visible = this._proxy.NightLightActive;
let disabled = this._proxy.DisabledUntilTomorrow;
this._item.label.text = disabled ? _("Night Light Disabled")
: _("Night Light On");
this._disableItem.label.text = disabled ? _("Resume")
: _("Disable Until Tomorrow");
this._item.label.text = disabled
? _("Night Light Disabled")
: _("Night Light On");
this._disableItem.label.text = disabled
? _("Resume")
: _("Disable Until Tomorrow");
this._item.visible = this._indicator.visible = visible;
}
};
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* 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 PanelMenu = imports.ui.panelMenu;
@@ -17,9 +17,11 @@ const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface)
const SHOW_BATTERY_PERCENTAGE = 'show-battery-percentage';
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'Power_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect(`changed::${SHOW_BATTERY_PERCENTAGE}`,
@@ -28,8 +30,8 @@ var Indicator = class extends PanelMenu.SystemIndicator {
this._indicator = this._addIndicator();
this._percentageLabel = new St.Label({ y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.indicators.add(this._percentageLabel, { expand: true, y_fill: true });
this.indicators.add_style_class_name('power-status');
this.add(this._percentageLabel, { expand: true, y_fill: true });
this.add_style_class_name('power-status');
this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
(proxy, error) => {
@@ -110,7 +112,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
// The icons
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
? '-charging' : '';
let fillLevel = 10 * Math.ceil(this._proxy.Percentage / 10);
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
let icon = this._proxy.State == UPower.DeviceState.FULLY_CHARGED
? 'battery-level-100-charged-symbolic'
: `battery-level-${fillLevel}${chargingState}-symbolic`;
@@ -140,4 +142,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
// The status label
this._item.label.text = this._getStatus();
}
};
});

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
// 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 Main = imports.ui.main;
@@ -156,12 +156,12 @@ var AuthRobot = class {
/* check if authorization is enabled in the daemon. if not
* we won't even bother authorizing, because we will only
* get an error back. The exact contents of AuthMode might
* get an error back. The exact contents of AuthMode might
* change in the future, but must contain AuthMode.ENABLED
* if it is enabled. */
if (!cli.authMode.split('|').includes(AuthMode.ENABLED))
return;
/* check if we should enroll the device */
let res = [false];
this.emit('enroll-device', dev, res);
@@ -221,9 +221,11 @@ Signals.addSignalMethods(AuthRobot.prototype);
/* eof client.js */
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'Thunderbolt_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._indicator = this._addIndicator();
this._indicator.icon_name = 'thunderbolt-symbolic';
@@ -260,7 +262,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
if (!this._source) {
this._source = new MessageTray.Source(_("Thunderbolt"),
'thunderbolt-symbolic');
this._source.connect('destroy', () => this._source = null);
this._source.connect('destroy', () => (this._source = null));
Main.messageTray.add(this._source);
}
@@ -284,7 +286,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
if (app)
app.activate();
});
this._source.notify(this._notification);
this._source.showNotification(this._notification);
}
/* Session callbacks */
@@ -334,4 +336,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
const body = _("Could not authorize the Thunderbolt device: %s").format(error.message);
this._notify(title, body);
}
};
});

View File

@@ -47,7 +47,7 @@ var StreamSlider = class {
return this._slider.startDragging(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;
@@ -228,9 +228,9 @@ var OutputStreamSlider = class extends StreamSlider {
}
_updateSliderIcon() {
this._icon.icon_name = (this._hasHeadphones ?
'audio-headphones-symbolic' :
'audio-speakers-symbolic');
this._icon.icon_name = (this._hasHeadphones
? 'audio-headphones-symbolic'
: 'audio-speakers-symbolic');
}
_portChanged() {
@@ -259,18 +259,17 @@ var InputStreamSlider = class extends StreamSlider {
_maybeShowInput() {
// only show input widgets if any application is recording audio
let showInput = false;
let recordingApps = this._control.get_source_outputs();
if (this._stream && recordingApps) {
for (let i = 0; i < recordingApps.length; i++) {
let outputStream = recordingApps[i];
let id = outputStream.get_application_id();
// but skip gnome-volume-control and pavucontrol
// (that appear as recording because they show the input level)
if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
showInput = true;
break;
}
}
if (this._stream) {
// skip gnome-volume-control and pavucontrol which appear
// as recording because they show the input level
let skippedApps = [
'org.gnome.VolumeControl',
'org.PulseAudio.pavucontrol'
];
showInput = this._control.get_source_outputs().some(output => {
return !skippedApps.includes(output.get_application_id());
});
}
this._showInput = showInput;
@@ -300,6 +299,9 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
this.addMenuItem(this._output.item);
this._input = new InputStreamSlider(this._control);
this._input.item.connect('notify::visible', () => {
this.emit('input-visible-changed');
});
this.addMenuItem(this._input.item);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
@@ -339,34 +341,44 @@ var VolumeMenu = class extends PopupMenu.PopupMenuSection {
getMaxLevel() {
return this._output.getMaxLevel();
}
getInputVisible() {
return this._input.item.visible;
}
};
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
var Indicator = GObject.registerClass({
GTypeName: 'Volume_Indicator'
}, class Indicator extends PanelMenu.SystemIndicator {
_init() {
super._init();
this._primaryIndicator = this._addIndicator();
this._inputIndicator = this._addIndicator();
this._control = getMixerControl();
this._volumeMenu = new VolumeMenu(this._control);
this._volumeMenu.connect('icon-changed', () => {
let icon = this._volumeMenu.getIcon();
if (icon != null) {
this.indicators.show();
if (icon != null)
this._primaryIndicator.icon_name = icon;
} else {
this.indicators.hide();
}
this._primaryIndicator.visible = icon !== null;
});
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.indicators.connect('scroll-event', this._onScrollEvent.bind(this));
}
_onScrollEvent(actor, event) {
let result = this._volumeMenu.scroll(event);
vfunc_scroll_event() {
let result = this._volumeMenu.scroll(Clutter.get_current_event());
if (result == Clutter.EVENT_PROPAGATE || this.menu.actor.mapped)
return result;
@@ -376,4 +388,4 @@ var Indicator = class extends PanelMenu.SystemIndicator {
Main.osdWindowManager.show(-1, gicon, null, level, maxLevel);
return result;
}
};
});

View File

@@ -105,12 +105,6 @@ var SwitcherPopup = GObject.registerClass({
this._haveModal = true;
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._switcherList.connect('item-activated', this._itemActivated.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}`);
}
_keyPressEvent(actor, event) {
let keysym = event.get_key_symbol();
let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state());
vfunc_key_press_event(keyEvent) {
let keysym = keyEvent.keyval;
let action = global.display.get_keybinding_action(
keyEvent.hardware_keycode, keyEvent.modifier_state);
this._disableHover();
@@ -183,13 +178,13 @@ var SwitcherPopup = GObject.registerClass({
return Clutter.EVENT_STOP;
}
_keyReleaseEvent(actor, event) {
vfunc_key_release_event(keyEvent) {
if (this._modifierMask) {
let [x_, y_, mods] = global.get_pointer();
let state = mods & this._modifierMask;
if (state == 0)
this._finish(event.get_time());
this._finish(keyEvent.time);
} else {
this._resetNoModsTimeout();
}
@@ -197,7 +192,8 @@ var SwitcherPopup = GObject.registerClass({
return Clutter.EVENT_STOP;
}
_clickedOutside() {
vfunc_button_press_event() {
/* We clicked outside */
this.fadeAndDestroy();
return Clutter.EVENT_PROPAGATE;
}
@@ -209,8 +205,8 @@ var SwitcherPopup = GObject.registerClass({
this._select(this._next());
}
_scrollEvent(actor, event) {
this._scrollHandler(event.get_scroll_direction());
vfunc_scroll_event(scrollEvent) {
this._scrollHandler(scrollEvent.scroll_direction);
return Clutter.EVENT_PROPAGATE;
}

View File

@@ -2,8 +2,7 @@
/* exported UnlockDialog */
const { AccountsService, Atk, Clutter,
Gdm, Gio, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
@@ -13,15 +12,19 @@ const AuthPrompt = imports.gdm.authPrompt;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
var UnlockDialog = class {
constructor(parentActor) {
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
style_class: 'login-dialog',
layout_manager: new Clutter.BoxLayout(),
visible: false });
var UnlockDialog = GObject.registerClass({
Signals: { 'failed': {} },
}, class UnlockDialog extends St.Widget {
_init(parentActor) {
super._init({
accessible_role: Atk.Role.WINDOW,
style_class: 'login-dialog',
layout_manager: new Clutter.BoxLayout(),
visible: false,
});
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
parentActor.add_child(this.actor);
this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default();
this._userName = GLib.get_user_name();
@@ -32,7 +35,7 @@ var UnlockDialog = class {
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true });
this.actor.add_child(this._promptBox);
this.add_child(this._promptBox);
this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
this._authPrompt.connect('failed', this._fail.bind(this));
@@ -41,7 +44,7 @@ var UnlockDialog = class {
this._authPrompt.setPasswordChar('\u25cf');
this._authPrompt.nextButton.label = _("Unlock");
this._promptBox.add_child(this._authPrompt.actor);
this._promptBox.add_child(this._authPrompt);
this.allowCancel = false;
@@ -64,10 +67,12 @@ var UnlockDialog = class {
this._authPrompt.reset();
this._updateSensitivity(true);
Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic');
Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic');
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
_updateSensitivity(sensitive) {
@@ -106,9 +111,8 @@ var UnlockDialog = class {
this._authPrompt.cancel();
}
destroy() {
_onDestroy() {
this.popModal();
this.actor.destroy();
if (this._idleWatchId) {
this._idleMonitor.remove_watch(this._idleWatchId);
@@ -131,13 +135,16 @@ var UnlockDialog = class {
}
open(timestamp) {
this.actor.show();
this.show();
if (this._isModal)
return true;
if (!Main.pushModal(this.actor, { timestamp: timestamp,
actionMode: Shell.ActionMode.UNLOCK_SCREEN }))
let modalParams = {
timestamp,
actionMode: Shell.ActionMode.UNLOCK_SCREEN,
};
if (!Main.pushModal(this, modalParams))
return false;
this._isModal = true;
@@ -147,9 +154,8 @@ var UnlockDialog = class {
popModal(timestamp) {
if (this._isModal) {
Main.popModal(this.actor, timestamp);
Main.popModal(this, timestamp);
this._isModal = false;
}
}
};
Signals.addSignalMethods(UnlockDialog.prototype);
});

View File

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

View File

@@ -123,9 +123,14 @@ var ShowOverviewAction = GObject.registerClass({
}
});
var ViewSelector = class {
constructor(searchEntry, showAppsButton) {
this.actor = new Shell.Stack({ name: 'viewSelector' });
var ViewSelector = GObject.registerClass({
Signals: {
'page-changed': {},
'page-empty': {},
}
}, class ViewSelector extends Shell.Stack {
_init(searchEntry, showAppsButton) {
super._init({ name: 'viewSelector' });
this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', this._onShowAppsButtonToggled.bind(this));
@@ -165,15 +170,15 @@ var ViewSelector = class {
this._capturedEventId = 0;
this._workspacesDisplay = new WorkspacesView.WorkspacesDisplay();
this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
this._workspacesPage = this._addPage(this._workspacesDisplay,
_("Windows"), 'focus-windows-symbolic');
this.appDisplay = new AppDisplay.AppDisplay();
this._appsPage = this._addPage(this.appDisplay.actor,
this._appsPage = this._addPage(this.appDisplay,
_("Applications"), 'view-app-grid-symbolic');
this._searchResults = new Search.SearchResults();
this._searchPage = this._addPage(this._searchResults.actor,
this._searchResults = new Search.SearchResultsView();
this._searchPage = this._addPage(this._searchResults,
_("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry });
@@ -184,9 +189,9 @@ var ViewSelector = class {
this._focusTrap.connect('key-focus-in', () => {
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;
Main.overview.connect('showing', () => {
@@ -310,11 +315,11 @@ var ViewSelector = class {
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, {
proxy: this.actor,
proxy: this,
focusCallback: () => this._a11yFocusPage(page),
});
page.hide();
this.actor.add_actor(page);
this.add_actor(page);
return page;
}
@@ -389,8 +394,8 @@ var ViewSelector = class {
}
_onShowAppsButtonToggled() {
this._showPage(this._showAppsButton.checked ?
this._appsPage : this._workspacesPage);
this._showPage(this._showAppsButton.checked
? this._appsPage : this._workspacesPage);
}
_onStageKeyPress(actor, event) {
@@ -424,8 +429,9 @@ var ViewSelector = class {
}
_searchCancelled() {
this._showPage(this._showAppsButton.checked ? this._appsPage
: this._workspacesPage);
this._showPage(this._showAppsButton.checked
? this._appsPage
: this._workspacesPage);
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
@@ -453,7 +459,7 @@ var ViewSelector = class {
_onStageKeyFocusChanged() {
let focus = global.stage.get_key_focus();
let appearFocused = (this._entry.contains(focus) ||
this._searchResults.actor.contains(focus));
this._searchResults.contains(focus));
this._text.set_cursor_visible(appearFocused);
@@ -576,6 +582,7 @@ var ViewSelector = class {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
let source = event.get_source();
if (source != this._text &&
this._text.has_key_focus() &&
this._text.text == '' &&
!this._text.has_preedit () &&
!Main.layoutManager.keyboardBox.contains(source)) {
@@ -597,5 +604,4 @@ var ViewSelector = class {
else
return ViewPage.SEARCH;
}
};
Signals.addSignalMethods(ViewSelector.prototype);
});

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported WindowAttentionHandler */
const Shell = imports.gi.Shell;
const { GObject, Shell } = imports.gi;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
@@ -34,7 +34,7 @@ var WindowAttentionHandler = class {
return;
let app = this._tracker.get_window_app(window);
let source = new Source(app, window);
let source = new WindowAttentionSource(app, window);
Main.messageTray.add(source);
let [title, banner] = this._getTitleAndBanner(app, window);
@@ -45,7 +45,7 @@ var WindowAttentionHandler = class {
});
notification.setForFeedback(true);
source.notify(notification);
source.showNotification(notification);
source.signalIDs.push(window.connect('notify::title', () => {
let [title, banner] = this._getTitleAndBanner(app, window);
@@ -54,9 +54,10 @@ var WindowAttentionHandler = class {
}
};
var Source = class WindowAttentionSource extends MessageTray.Source {
constructor(app, window) {
super(app.get_name());
var WindowAttentionSource = GObject.registerClass(
class WindowAttentionSource extends MessageTray.Source {
_init(app, window) {
super._init(app.get_name());
this._window = window;
this._app = app;
@@ -102,4 +103,4 @@ var Source = class WindowAttentionSource extends MessageTray.Source {
open() {
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 GsdWacomProxy = Gio.DBusProxy.makeProxyWrapper(GsdWacomIface);
const WINDOW_DIMMER_EFFECT_NAME = "gnome-shell-window-dimmer";
var DisplayChangeDialog = GObject.registerClass(
class DisplayChangeDialog extends ModalDialog.ModalDialog {
_init(wm) {
@@ -114,21 +116,20 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
}
});
var WindowDimmer = class {
constructor(actor) {
this._brightnessEffect = new Clutter.BrightnessContrastEffect({
name: 'dim',
var WindowDimmer = GObject.registerClass(
class WindowDimmer extends Clutter.BrightnessContrastEffect {
_init() {
super._init({
name: WINDOW_DIMMER_EFFECT_NAME,
enabled: false
});
actor.add_effect(this._brightnessEffect);
this.actor = actor;
this._enabled = true;
}
_syncEnabled() {
let animating = this.actor.get_transition('@effects.dim.brightness') != null;
let dimmed = this._brightnessEffect.brightness.red != 127;
this._brightnessEffect.enabled = this._enabled && (animating || dimmed);
let animating = this.actor.get_transition(`@effects.${this.name}.brightness`) != null;
let dimmed = this.brightness.red != 127;
this.enabled = this._enabled && (animating || dimmed);
}
setEnabled(enabled) {
@@ -140,7 +141,7 @@ var WindowDimmer = class {
let val = 127 * (1 + (dimmed ? 1 : 0) * DIM_BRIGHTNESS);
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,
duration: (dimmed ? DIM_TIME : UNDIM_TIME) * (animate ? 1 : 0),
onComplete: () => this._syncEnabled()
@@ -148,20 +149,19 @@ var WindowDimmer = class {
this._syncEnabled();
}
};
});
function getWindowDimmer(actor) {
let enabled = Meta.prefs_get_attach_modal_dialogs();
if (actor._windowDimmer)
actor._windowDimmer.setEnabled(enabled);
let effect = actor.get_effect(WINDOW_DIMMER_EFFECT_NAME);
if (enabled) {
if (!actor._windowDimmer)
actor._windowDimmer = new WindowDimmer(actor);
return actor._windowDimmer;
} else {
return null;
if (effect) {
effect.setEnabled(enabled);
} else if (enabled) {
effect = new WindowDimmer();
actor.add_effect(effect);
}
return effect;
}
/*
@@ -187,6 +187,9 @@ var WorkspaceTracker = class {
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
this._nWorkspacesChanged.bind(this));
workspaceManager.connect('workspaces-reordered', () => {
this._workspaces.sort((a, b) => a.index() - b.index());
});
global.window_manager.connect('switch-workspace',
this._queueCheckWorkspaces.bind(this));
@@ -376,21 +379,22 @@ var WorkspaceTracker = class {
}
};
var TilePreview = class {
constructor() {
this.actor = new St.Widget();
global.window_group.add_actor(this.actor);
var TilePreview = GObject.registerClass(
class TilePreview extends St.Widget {
_init() {
super._init();
global.window_group.add_actor(this);
this._reset();
this._showing = false;
}
show(window, tileRect, monitorIndex) {
open(window, tileRect, monitorIndex) {
let windowActor = window.get_compositor_private();
if (!windowActor)
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))
return;
@@ -411,14 +415,14 @@ var TilePreview = class {
width: monitor.width,
height: monitor.height });
let [, rect] = window.get_frame_rect().intersect(monitorRect);
this.actor.set_size(rect.width, rect.height);
this.actor.set_position(rect.x, rect.y);
this.actor.opacity = 0;
this.set_size(rect.width, rect.height);
this.set_position(rect.x, rect.y);
this.opacity = 0;
}
this._showing = true;
this.actor.show();
this.actor.ease({
this.show();
this.ease({
x: tileRect.x,
y: tileRect.y,
width: tileRect.width,
@@ -429,12 +433,12 @@ var TilePreview = class {
});
}
hide() {
close() {
if (!this._showing)
return;
this._showing = false;
this.actor.ease({
this.ease({
opacity: 0,
duration: WINDOW_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@@ -443,7 +447,7 @@ var TilePreview = class {
}
_reset() {
this.actor.hide();
this.hide();
this._rect = null;
this._monitorIndex = -1;
}
@@ -457,9 +461,9 @@ var TilePreview = class {
if (this._rect.x + this._rect.width == monitor.x + monitor.width)
styles.push('tile-preview-right');
this.actor.style_class = styles.join(' ');
this.style_class = styles.join(' ');
}
};
});
var TouchpadWorkspaceSwitchAction = class {
constructor(actor, allowedModes) {
@@ -630,9 +634,9 @@ var AppSwitchAction = GObject.registerClass({
let nPoints = this.get_n_current_points();
let event = this.get_last_event (nPoints - 1);
if (nPoints == 3)
if (nPoints == 3) {
this._longPressStartTime = event.get_time();
else if (nPoints == 4) {
} else if (nPoints == 4) {
// Check whether the 4th finger press happens after a 3-finger long press,
// this only needs to be checked on the first 4th finger press
if (this._longPressStartTime != null &&
@@ -666,15 +670,16 @@ var AppSwitchAction = GObject.registerClass({
}
});
var ResizePopup = class {
constructor() {
this._widget = new St.Widget({ layout_manager: new Clutter.BinLayout() });
var ResizePopup = GObject.registerClass(
class ResizePopup extends St.Widget {
_init() {
super._init({ layout_manager: new Clutter.BinLayout() });
this._label = new St.Label({ style_class: 'resize-popup',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true, y_expand: true });
this._widget.add_child(this._label);
Main.uiGroup.add_actor(this._widget);
this.add_child(this._label);
Main.uiGroup.add_actor(this);
}
set(rect, displayW, displayH) {
@@ -683,15 +688,10 @@ var ResizePopup = class {
let text = _("%d × %d").format(displayW, displayH);
this._label.set_text(text);
this._widget.set_position(rect.x, rect.y);
this._widget.set_size(rect.width, rect.height);
this.set_position(rect.x, rect.y);
this.set_size(rect.width, rect.height);
}
destroy() {
this._widget.destroy();
this._widget = null;
}
};
});
var WindowManager = class {
constructor() {
@@ -713,7 +713,7 @@ var WindowManager = class {
this._isWorkspacePrepended = false;
this._switchData = null;
this._shellwm.connect('kill-switch-workspace', (shellwm) => {
this._shellwm.connect('kill-switch-workspace', shellwm => {
if (this._switchData) {
if (this._switchData.inProgress)
this._switchWorkspaceDone(shellwm);
@@ -1022,7 +1022,6 @@ var WindowManager = class {
(proxy, error) => {
if (error) {
log(error.message);
return;
}
});
@@ -1087,7 +1086,7 @@ var WindowManager = class {
let mode = Shell.ActionMode.ALL & ~Shell.ActionMode.LOCK_SCREEN;
let bottomDragAction = new EdgeDragAction.EdgeDragAction(St.Side.BOTTOM, mode);
bottomDragAction.connect('activated', () => {
Main.keyboard.show(Main.layoutManager.bottomIndex);
Main.keyboard.open(Main.layoutManager.bottomIndex);
});
Main.layoutManager.connect('keyboard-visible-changed', (manager, visible) => {
bottomDragAction.cancel();
@@ -1115,9 +1114,9 @@ var WindowManager = class {
_showPadOsd(display, 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) {
@@ -1210,9 +1209,41 @@ var WindowManager = class {
if (!Meta.prefs_get_dynamic_workspaces())
return;
let newWs = workspaceManager.append_new_workspace(
false, global.get_current_time());
workspaceManager.reorder_workspace(newWs, pos);
workspaceManager.append_new_workspace(false, global.get_current_time());
let windows = global.get_window_actors().map(a => a.meta_window);
// To create a new workspace, we slide all the windows on workspaces
// below us to the next workspace, leaving a blank workspace for us
// to recycle.
windows.forEach(window => {
// If the window is attached to an ancestor, we don't need/want
// to move it
if (window.get_transient_for() != null)
return;
// Same for OR windows
if (window.is_override_redirect())
return;
// Sticky windows don't need moving, in fact moving would
// unstick them
if (window.on_all_workspaces)
return;
// Windows on workspaces below pos don't need moving
let index = window.get_workspace().index();
if (index < pos)
return;
window.change_workspace_by_index(index + 1, true);
});
// If the new workspace was inserted before the active workspace,
// activate the workspace to which its windows went
let activeIndex = workspaceManager.get_active_workspace_index();
if (activeIndex >= pos) {
let newWs = workspaceManager.get_workspace_by_index(activeIndex + 1);
this._blockAnimations = true;
newWs.activate(global.get_current_time());
this._blockAnimations = false;
}
}
keepWorkspaceAlive(workspace, duration) {
@@ -1682,7 +1713,6 @@ var WindowManager = class {
break;
default:
shellwm.completed_map(actor);
return;
}
}
@@ -1763,7 +1793,6 @@ var WindowManager = class {
break;
default:
shellwm.completed_destroy(actor);
return;
}
}
@@ -2013,13 +2042,13 @@ var WindowManager = class {
_showTilePreview(shellwm, window, tileRect, monitorIndex) {
if (!this._tilePreview)
this._tilePreview = new TilePreview();
this._tilePreview.show(window, tileRect, monitorIndex);
this._tilePreview.open(window, tileRect, monitorIndex);
}
_hideTilePreview() {
if (!this._tilePreview)
return;
this._tilePreview.hide();
this._tilePreview.close();
}
_showWindowMenu(shellwm, window, menu, rect) {

View File

@@ -178,7 +178,7 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
}
let waitId = 0;
let id = global.display.connect('grab-op-end', (display) => {
let id = global.display.connect('grab-op-end', display => {
display.disconnect(id);
GLib.source_remove(waitId);

View File

@@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* 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 DND = imports.ui.dnd;
@@ -93,6 +94,7 @@ class WindowCloneLayout extends Clutter.LayoutManager {
});
var WindowClone = GObject.registerClass({
GTypeName: 'Workspace_WindowClone',
Signals: {
'drag-begin': {},
'drag-cancelled': {},
@@ -102,7 +104,7 @@ var WindowClone = GObject.registerClass({
'show-chrome': {},
'size-changed': {}
},
}, class WorkspaceWindowClone extends St.Widget {
}, class WindowClone extends St.Widget {
_init(realWindow, workspace) {
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
@@ -157,18 +159,13 @@ var WindowClone = GObject.registerClass({
this.x = this._boundingBox.x;
this.y = this._boundingBox.y;
this._computeWindowCenter();
let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', this._onClicked.bind(this));
clickAction.connect('long-press', this._onLongPress.bind(this));
this.add_action(clickAction);
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,
{ restoreOnSuccess: true,
@@ -299,6 +296,18 @@ var WindowClone = GObject.registerClass({
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
getActualStackAbove() {
if (this._stackAbove == null)
@@ -368,8 +377,28 @@ var WindowClone = GObject.registerClass({
this.emit('selected', global.get_current_time());
}
_onKeyPress(actor, event) {
let symbol = event.get_key_symbol();
vfunc_enter_event(crossingEvent) {
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);
if (isEnter) {
this._activate();
@@ -412,8 +441,6 @@ var WindowClone = GObject.registerClass({
_onDragBegin(_draggable, _time) {
this._dragSlot = this._slot;
[this.dragOrigX, this.dragOrigY] = this.get_position();
this.dragOrigScale = this.scale_x;
this.inDrag = true;
this.emit('drag-begin');
}
@@ -423,7 +450,7 @@ var WindowClone = GObject.registerClass({
}
acceptDrop(source, actor, x, y, time) {
this._workspace.acceptDrop(source, actor, x, y, time);
return this._workspace.acceptDrop(source, actor, x, y, time);
}
_onDragCancelled(_draggable, _time) {
@@ -468,7 +495,8 @@ var WindowOverlay = class {
this.border = new St.Bin({ style_class: 'window-clone-border' });
this.title = new St.Label({ style_class: 'window-caption',
text: this._getCaption() });
text: this._getCaption(),
reactive: true });
this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
windowClone.label_actor = this.title;
@@ -493,7 +521,6 @@ var WindowOverlay = class {
this.closeButton.hide();
// Don't block drop targets
Shell.util_set_hidden_from_pick(this.title, true);
Shell.util_set_hidden_from_pick(this.border, true);
parentActor.add_actor(this.border);
@@ -686,19 +713,22 @@ var WindowOverlay = class {
}
_onHideChrome() {
if (this._idleHideOverlayId == 0) {
this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
}
if (this._idleHideOverlayId > 0)
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
}
_idleHideOverlay() {
this._idleHideOverlayId = 0;
if (this.closeButton['has-pointer'] ||
this.title['has-pointer'])
return GLib.SOURCE_CONTINUE;
if (!this._windowClone['has-pointer'] &&
!this.closeButton['has-pointer'])
if (!this._windowClone['has-pointer'])
this._animateInvisible();
this._idleHideOverlayId = 0;
return GLib.SOURCE_REMOVE;
}
@@ -903,7 +933,7 @@ var LayoutStrategy = class {
computeWindowSlots(layout, area) {
this._computeRowSizes(layout);
let { rows: rows, scale: scale } = layout;
let { rows, scale } = layout;
let slots = [];
@@ -978,7 +1008,7 @@ var LayoutStrategy = class {
var UnalignedLayoutStrategy = class extends LayoutStrategy {
_computeRowSizes(layout) {
let { rows: rows, scale: scale } = layout;
let { rows, scale } = layout;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
row.width = row.fullWidth * scale + (row.windows.length - 1) * this._columnSpacing;
@@ -1002,11 +1032,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
_sortRow(row) {
// Sort windows horizontally to minimize travel distance.
// This affects in what order the windows end up in a row.
row.windows.sort((a, b) => {
let aCenter = a.realWindow.x + a.realWindow.width / 2;
let bCenter = b.realWindow.x + b.realWindow.width / 2;
return aCenter - bCenter;
});
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
}
computeLayout(windows, layout) {
@@ -1025,11 +1051,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
// Sort windows vertically to minimize travel distance.
// This affects what rows the windows get placed in.
let sortedWindows = windows.slice();
sortedWindows.sort((a, b) => {
let aCenter = a.realWindow.y + a.realWindow.height / 2;
let bCenter = b.realWindow.y + b.realWindow.height / 2;
return aCenter - bCenter;
});
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
let windowIdx = 0;
for (let i = 0; i < numRows; i++) {
@@ -1093,23 +1115,14 @@ function rectEqual(one, two) {
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
*/
var Workspace = class {
constructor(metaWorkspace, monitorIndex) {
var Workspace = GObject.registerClass(
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.
this._reservedSlot = null;
this._reservedSlotWindow = null;
@@ -1135,18 +1148,17 @@ var Workspace = class {
// Without this the drop area will be overlapped.
this._windowOverlaysGroup.set_size(0, 0);
this.actor = new WorkspaceActor({ style_class: 'window-picker' });
if (monitorIndex != Main.layoutManager.primaryIndex)
this.actor.add_style_class_name('external-monitor');
this.actor.set_size(0, 0);
this.add_style_class_name('external-monitor');
this.set_size(0, 0);
this._dropRect = new Clutter.Actor({ opacity: 0 });
this._dropRect._delegate = this;
this.actor.add_actor(this._dropRect);
this.actor.add_actor(this._windowOverlaysGroup);
this.add_actor(this._dropRect);
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);
@@ -1176,10 +1188,19 @@ var Workspace = class {
this._positionWindowsFlags = 0;
this._positionWindowsId = 0;
}
this.actor.connect('notify::mapped', () => {
if (this.actor.mapped)
this._syncActualGeometry();
vfunc_map() {
super.vfunc_map();
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;
});
}
@@ -1189,7 +1210,7 @@ var Workspace = class {
this._fullGeometry = geom;
if (this.actor.mapped)
if (this.mapped)
this._recalculateWindowPositions(WindowPositionFlags.NONE);
}
@@ -1200,7 +1221,7 @@ var Workspace = class {
this._actualGeometry = geom;
this._actualGeometryDirty = true;
if (this.actor.mapped)
if (this.mapped)
this._syncActualGeometry();
}
@@ -1212,7 +1233,7 @@ var Workspace = class {
this._actualGeometryLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._actualGeometryLater = 0;
if (!this.actor.mapped)
if (!this.mapped)
return false;
let geom = this._actualGeometry;
@@ -1503,8 +1524,7 @@ var Workspace = class {
// Newly-created windows are added to a workspace before
// the compositor finds out about them...
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (this.actor &&
metaWin.get_compositor_private() &&
if (metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace)
this._doAddWindow(metaWin);
return GLib.SOURCE_REMOVE;
@@ -1540,8 +1560,8 @@ var Workspace = class {
let [clone, overlay_] = this._addWindowClone(win, false);
if (win._overviewHint) {
let x = win._overviewHint.x - this.actor.x;
let y = win._overviewHint.y - this.actor.y;
let x = win._overviewHint.x - this.x;
let y = win._overviewHint.y - this.y;
let scale = win._overviewHint.scale;
delete win._overviewHint;
@@ -1776,10 +1796,6 @@ var Workspace = class {
}
}
destroy() {
this.actor.destroy();
}
_onDestroy() {
if (this._overviewHiddenId) {
Main.overview.disconnect(this._overviewHiddenId);
@@ -1860,11 +1876,11 @@ var Workspace = class {
this._removeWindowClone(clone.metaWindow);
});
this.actor.add_actor(clone);
this.add_actor(clone);
overlay.connect('chrome-visible', () => {
let focus = global.stage.key_focus;
if (focus == null || this.actor.contains(focus))
if (focus == null || this.contains(focus))
clone.grab_key_focus();
this._windowOverlays.forEach(o => {
@@ -1948,7 +1964,7 @@ var Workspace = class {
}
_getSpacingAndPadding() {
let node = this.actor.get_theme_node();
let node = this.get_theme_node();
// Window grid spacing
let columnSpacing = node.get_length('-horizontal-spacing');
@@ -1993,13 +2009,20 @@ var Workspace = class {
handleDragOver(source, _actor, _x, _y, _time) {
if (source.realWindow && !this._isMyWindow(source.realWindow))
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
if (source.app && source.app.can_open_new_window())
return DND.DragMotionResult.COPY_DROP;
if (!source.app && source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP;
return DND.DragMotionResult.CONTINUE;
}
acceptDrop(source, actor, x, y, time) {
let workspaceManager = global.workspace_manager;
let workspaceIndex = this.metaWorkspace
? this.metaWorkspace.index()
: workspaceManager.get_active_workspace_index();
if (source.realWindow) {
let win = source.realWindow;
if (this._isMyWindow(win))
@@ -2021,17 +2044,22 @@ var Workspace = class {
if (metaWindow.get_monitor() != this.monitorIndex)
metaWindow.move_to_monitor(this.monitorIndex);
let workspaceManager = global.workspace_manager;
let index = this.metaWorkspace ? this.metaWorkspace.index() : workspaceManager.get_active_workspace_index();
metaWindow.change_workspace_by_index(index, false);
metaWindow.change_workspace_by_index(workspaceIndex, false);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
} else if (source.app && source.app.can_open_new_window()) {
if (source.animateLaunchAtPos)
source.animateLaunchAtPos(actor.x, actor.y);
source.app.open_new_window(workspaceIndex);
return true;
} else if (!source.app && source.shellWorkspaceLaunch) {
// While unused in our own drag sources, shellWorkspaceLaunch allows
// extensions to define custom actions for their drag sources.
source.shellWorkspaceLaunch({ workspace: workspaceIndex,
timestamp: time });
return true;
}
return false;
}
};
Signals.addSignalMethods(Workspace.prototype);
});

View File

@@ -2,7 +2,6 @@
/* exported WorkspaceThumbnail, ThumbnailsBox */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
@@ -44,36 +43,40 @@ class PrimaryActorLayout extends Clutter.FixedLayout {
}
});
var WindowClone = class {
constructor(realWindow) {
this.clone = new Clutter.Clone({ source: realWindow });
var WindowClone = GObject.registerClass({
GTypeName: 'WorkspaceThumbnail_WindowClone',
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.actor = new Clutter.Actor({ layout_manager: new PrimaryActorLayout(this.clone),
reactive: true });
this.actor._delegate = this;
this.actor.add_child(this.clone);
this.add_child(clone);
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
this.clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this));
this.clone._destroyId = this.realWindow.connect('destroy', () => {
clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this));
clone._destroyId = this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything
// This will ensure that we never see it in the _disconnectSignals loop
this.clone.destroy();
clone.destroy();
this.destroy();
});
this._onPositionChanged();
this.actor.connect('button-release-event',
this._onButtonRelease.bind(this));
this.actor.connect('touch-event',
this._onTouchEvent.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._draggable = DND.makeDraggable(this.actor,
this._draggable = DND.makeDraggable(this,
{ restoreOnSuccess: true,
dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
@@ -124,13 +127,9 @@ var WindowClone = class {
let actualAbove = this.getActualStackAbove();
if (actualAbove == null)
this.actor.lower_bottom();
this.lower_bottom();
else
this.actor.raise(actualAbove);
}
destroy() {
this.actor.destroy();
this.raise(actualAbove);
}
addAttachedDialog(win) {
@@ -147,7 +146,7 @@ var WindowClone = class {
clone._destroyId = realDialog.connect('destroy', () => {
clone.destroy();
});
this.actor.add_child(clone);
this.add_child(clone);
}
_updateDialogPosition(realDialog, cloneDialog) {
@@ -159,11 +158,11 @@ var WindowClone = class {
}
_onPositionChanged() {
this.actor.set_position(this.realWindow.x, this.realWindow.y);
this.set_position(this.realWindow.x, this.realWindow.y);
}
_disconnectSignals() {
this.actor.get_children().forEach(child => {
this.get_children().forEach(child => {
let realWindow = child.source;
realWindow.disconnect(child._updateId);
@@ -174,28 +173,30 @@ var WindowClone = class {
_onDestroy() {
this._disconnectSignals();
this.actor._delegate = null;
this._delegate = null;
if (this.inDrag) {
this.emit('drag-end');
this.inDrag = false;
}
this.disconnectAll();
}
_onButtonRelease(actor, event) {
this.emit('selected', event.get_time());
vfunc_button_press_event() {
return Clutter.EVENT_STOP;
}
vfunc_button_release_event(buttonEvent) {
this.emit('selected', buttonEvent.time);
return Clutter.EVENT_STOP;
}
_onTouchEvent(actor, event) {
if (event.type() != Clutter.EventType.TOUCH_END ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
vfunc_touch_event(touchEvent) {
if (touchEvent.type != Clutter.EventType.TOUCH_END ||
!global.display.is_pointer_emulating_sequence(touchEvent.sequence))
return Clutter.EVENT_PROPAGATE;
this.emit('selected', event.get_time());
this.emit('selected', touchEvent.time);
return Clutter.EVENT_STOP;
}
@@ -214,18 +215,17 @@ var WindowClone = class {
// We may not have a parent if DnD completed successfully, in
// which case our clone will shortly be destroyed and replaced
// with a new one on the target workspace.
if (this.actor.get_parent() != null) {
if (this.get_parent() != null) {
if (this._stackAbove == null)
this.actor.lower_bottom();
this.lower_bottom();
else
this.actor.raise(this._stackAbove);
this.raise(this._stackAbove);
}
this.emit('drag-end');
}
};
Signals.addSignalMethods(WindowClone.prototype);
});
var ThumbnailState = {
@@ -340,7 +340,7 @@ var WorkspaceThumbnail = GObject.registerClass({
clone.setStackAbove(this._bgManager.backgroundActor);
} else {
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', () => {
Main.overview.endWindowDrag(clone.metaWindow);
});
clone.actor.connect('destroy', () => {
clone.connect('destroy', () => {
this._removeWindowClone(clone.metaWindow);
});
this._contents.add_actor(clone.actor);
this._contents.add_actor(clone);
if (this._windows.length == 0)
clone.setStackAbove(this._bgManager.backgroundActor);
else
clone.setStackAbove(this._windows[this._windows.length - 1].actor);
clone.setStackAbove(this._windows[this._windows.length - 1]);
this._windows.push(clone);
@@ -561,7 +561,7 @@ var WorkspaceThumbnail = GObject.registerClass({
}
// Draggable target interface used only by ThumbnailsBox
handleDragOverInternal(source, time) {
handleDragOverInternal(source, actor, time) {
if (source == Main.xdndHandler) {
this.metaWorkspace.activate(time);
return DND.DragMotionResult.CONTINUE;
@@ -572,13 +572,15 @@ var WorkspaceThumbnail = GObject.registerClass({
if (source.realWindow && !this._isMyWindow(source.realWindow))
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
if (source.app && source.app.can_open_new_window())
return DND.DragMotionResult.COPY_DROP;
if (!source.app && source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP;
return DND.DragMotionResult.CONTINUE;
}
acceptDropInternal(source, time) {
acceptDropInternal(source, actor, time) {
if (this.state > ThumbnailState.NORMAL)
return false;
@@ -597,8 +599,16 @@ var WorkspaceThumbnail = GObject.registerClass({
metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
} else if (source.app && source.app.can_open_new_window()) {
if (source.animateLaunchAtPos)
source.animateLaunchAtPos(actor.x, actor.y);
source.app.open_new_window(this.metaWorkspace.index());
return true;
} else if (!source.app && source.shellWorkspaceLaunch) {
// While unused in our own drag sources, shellWorkspaceLaunch allows
// extensions to define custom actions for their drag sources.
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace.index(),
timestamp: time });
return true;
}
@@ -658,10 +668,6 @@ var ThumbnailsBox = GObject.registerClass({
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',
this._createThumbnails.bind(this));
Main.overview.connect('hidden',
@@ -718,17 +724,17 @@ var ThumbnailsBox = GObject.registerClass({
thumbnail.activate(time);
}
_onButtonRelease(actor, event) {
let [stageX, stageY] = event.get_coords();
this._activateThumbnailAtPoint(stageX, stageY, event.get_time());
vfunc_button_release_event(buttonEvent) {
let { x, y } = buttonEvent;
this._activateThumbnailAtPoint(x, y, buttonEvent.time);
return Clutter.EVENT_STOP;
}
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END &&
global.display.is_pointer_emulating_sequence(event.get_event_sequence())) {
let [stageX, stageY] = event.get_coords();
this._activateThumbnailAtPoint(stageX, stageY, event.get_time());
vfunc_touch_event(touchEvent) {
if (touchEvent.type == Clutter.EventType.TOUCH_END &&
global.display.is_pointer_emulating_sequence(touchEvent.sequence)) {
let { x, y } = touchEvent;
this._activateThumbnailAtPoint(x, y, touchEvent.time);
}
return Clutter.EVENT_STOP;
@@ -779,7 +785,10 @@ var ThumbnailsBox = GObject.registerClass({
// Draggable target interface
handleDragOver(source, actor, x, y, time) {
if (!source.realWindow && !source.shellWorkspaceLaunch && source != Main.xdndHandler)
if (!source.realWindow &&
(!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch) &&
source != Main.xdndHandler)
return DND.DragMotionResult.CONTINUE;
let canCreateWorkspaces = Meta.prefs_get_dynamic_workspaces();
@@ -825,7 +834,7 @@ var ThumbnailsBox = GObject.registerClass({
}
if (this._dropWorkspace != -1)
return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, time);
return this._thumbnails[this._dropWorkspace].handleDragOverInternal(source, actor, time);
else if (this._dropPlaceholderPos != -1)
return source.realWindow ? DND.DragMotionResult.MOVE_DROP : DND.DragMotionResult.COPY_DROP;
else
@@ -834,9 +843,11 @@ var ThumbnailsBox = GObject.registerClass({
acceptDrop(source, actor, x, y, time) {
if (this._dropWorkspace != -1) {
return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, time);
return this._thumbnails[this._dropWorkspace].acceptDropInternal(source, actor, time);
} else if (this._dropPlaceholderPos != -1) {
if (!source.realWindow && !source.shellWorkspaceLaunch)
if (!source.realWindow &&
(!source.app || !source.app.can_open_new_window()) &&
(source.app || !source.shellWorkspaceLaunch))
return false;
let isWindow = !!source.realWindow;
@@ -853,9 +864,19 @@ var ThumbnailsBox = GObject.registerClass({
if (source.metaWindow.get_monitor() != thumbMonitor)
source.metaWindow.move_to_monitor(thumbMonitor);
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
} else if (source.shellWorkspaceLaunch) {
} else if (source.app && source.app.can_open_new_window()) {
if (source.animateLaunchAtPos)
source.animateLaunchAtPos(actor.x, actor.y);
source.app.open_new_window(newWorkspaceIndex);
} else if (!source.app && source.shellWorkspaceLaunch) {
// While unused in our own drag sources, shellWorkspaceLaunch allows
// extensions to define custom actions for their drag sources.
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time });
}
if (source.app || (!source.app && source.shellWorkspaceLaunch)) {
// This new workspace will be automatically removed if the application fails
// to open its first window within some time, as tracked by Shell.WindowTracker.
// Here, we only add a very brief timeout to avoid the _immediate_ removal of the

View File

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

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