Compare commits

..

82 Commits

Author SHA1 Message Date
Matej Urbančič
f6ace7a325 Updated Slovenian translation 2020-06-01 22:09:11 +02:00
Florian Müllner
c38196dd85 Bump version to 3.34.5
Update NEWS.
2020-03-31 01:28:47 +02:00
Florian Müllner
059af4c4cd a11y: Change HC icon theme first
There are two ways for applications to provide a high contrast icon:

 1. install an icon into the HighContrast theme
 2. install a symbolic icon into the default hicolor theme

The latter is preferred nowadays, and implemented in the high-contrast
CSS variant by enforcing the symbolic icon style.

However together with the way we currently enable/disable high-contrast,
this can lead to the following race:
 1. the GTK theme is changed from HighContrast
 2. we reload the default stylesheet
 3. the icon style changes to "regular", so we request a
    new icon from the HighContrast icon theme
 4. the icon theme is changed from HighContrast
 5. we evict existing icons from the cache
 6. we reload icons for the new icon theme; however as we
    find a pending request (from 3), we re-use it
 7. the request from 3 finishes, and we end up with a
    wrong icon in the cache

The simplest fix is to change the icon theme before the GTK theme: Unlike the
theme name, the icon style is encoded in the cache key, so we won't re-use
an old (and incorrect) request in that case.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2414
2020-03-31 01:12:34 +02:00
Jwtiyar Nariman
aba60dcac8 Add Kurdish Sorani translation 2020-03-28 15:39:04 +00:00
Florian Müllner
3d7ee7856f keyboard: Fix fallback layout when using variants
Commit c1ec7b2ff meant to fall back to the base layout in case
a variant like `fr+oss` is set up, but as we are checking for
'+' on the array rather than the layout name, the fallback only
"works" for a layout that is literally called '+', whoops.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2471


(cherry picked from commit d29e5765ba)
2020-03-23 15:28:03 +00:00
Florian Müllner
0a50b6ea01 networkAgent: Make searching VPN binaries asynchronous
Doing blocking IO in a graphical UI is bad, doing it in the compositor
is much much worse. So even if handling VPN requests is a relatively
rare event, doing it asynchronously is better.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:57 +01:00
Florian Müllner
c5dd9a9341 shell/network-agent: Wrap nm_plugin_info_new_search_file()
While we can use the libnm API directly from JS, the call will
synchronously load the VPN service descriptions from disk.
Previously we were lowering the impact by caching the result,
but as we stopped doing that, it becomes more important to address
the issue properly and move it off to a thread.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:57 +01:00
Florian Müllner
2756806f84 networkAgent: Drop VPN plugin cache
libnm doesn't only search for plugins in the regular VPN plugin directory,
but also in the legacy location and the directory pointed to by the
NM_VPN_PLUGIN_DIR environment variable (if set).

We don't monitor the additional directories, so it's possible for our cache
to become outdated.

Instead of trying to play catch-up with libnm's internals, do what nm-applet
does and use the appropriate API to look up the plugin on each request.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:54 +01:00
Christian Hergert
bb9c286e3f shell: fix typo in comment
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050
2020-02-27 15:13:15 +01:00
Christian Hergert
cf2ab505a0 global: force fsync() to worker thread when saving state
The g_file_replace_contents_async() API can potentially call fsync() from
the thread calling into it upon completion. This can have disasterous
effects when run from the compositor main thread such as complete stalls.

This is a followup to 86a00b6872 which
assumed (like the rest of us) that the fsync() would be performed on the
thread that was doing the I/O operations.

You can verify this with an strace -e fsync and cause terminal to display
a command completed notification (eg: from a backdrop window).

This also fixes a lifecycle bug for the variant, as
g_file_replace_contents_async() does not copy the data during the operation
as that is the responsibility of the caller. Instead, we just use a GBytes
variant and reference the variant there.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050
2020-02-27 15:13:15 +01:00
Jonas Dreßler
b7389b328c overview: Hide the overview on session mode hasOverview changes
If the sessionMode does not allow to show the overview, we should also
hide an already visible overview.

This fixes a bug where, if the lockscreen was shown while the overview
was visible, the Ctrl+Alt+Tab popup would allow navigating inside the
overview because the overview actor is still mapped.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1043
2020-02-25 20:14:15 +01:00
Jonas Ådahl
99d948559b closeDialog: Make dialog inactive while fading out
Otherwise the user might click Kill, which would crash if the fade-out
was triggered because a Wayland window was closed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1032


(cherry picked from commit 32fa060a62)
2020-02-21 08:19:35 +00:00
Florian Müllner
f21a0ff458 Bump version to 3.34.4
Update NEWS.
2020-02-16 15:51:30 +01:00
Dušan Kazik
ec852ab265 Update Slovak translation 2020-02-04 10:05:49 +00:00
Jor Teron
a8bb7c0a2a Update Karbi translation 2020-01-31 10:34:11 +00:00
Björn Daase
8a8c6e2f23 Revert "recorder: Switch to vp9"
This reverts commit d183f13456.
Switching to the vp9 encoder seemed like a good idea at the time but
unfortunately it also has the major drawback, that it leaks a serious
amount of memory every time it is used. See
https://gitlab.gnome.org/GNOME/gnome-shell/issues/256#note_692743
for more details.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/256


(cherry picked from commit c61685e617)
2020-01-24 19:51:36 +00:00
Florian Müllner
f7fe7bc676 Bump verion to 3.34.3
Update NEWS.
2020-01-05 13:10:47 +01:00
Jonas Dreßler
a35f9a5226 polkitAgent: Only set key focus to password entry after opening dialog
Set the key focus to the password field only after we got a request
(and therefore know that a password is requested) instead of using
`setInitialKeyFocus()`. This way we don't try to focus the password
field by default if we aren't showing it (e.g. in case the user has no
password or is using fingerprint login).

Also we have to move the call to `grab_key_focus()` to happen after
`_ensureOpen()`, because otherwise the ModalDialog will set the focus to
one of the buttons while opening itself.

Cherry-picked from commit 70203b58ca.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2066
2019-12-25 12:56:46 +01:00
Florian Müllner
fb74394d58 keyboard: Stop accessing deprecated actor property
Commit 3d3dca4aa2 turned EmojiPager into a Clutter.Actor subclass,
but one place slipped through that still accesses it through .actor.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2060
2019-12-20 14:37:31 +01:00
Florian Müllner
9f7b1bd677 Bump version to 3.34.2
Update NEWS.
2019-12-11 21:03:50 +01:00
Florian Müllner
afd2ce2353 popupMenu: Close when a system modal pops up
Just like switcher popups, popup menus don't play well together with
system modals, and generally have a lower priority. So just like
switcher popups, close popup menus when a system modal dialog pops
up.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1536
2019-12-11 20:35:13 +01:00
Florian Müllner
61fccf188a switcherPopup: Dismiss when a system modal dialog opens
As system modal dialogs may open without user interaction (for instance
polkit or network agent requests), it is possible for them to pop up
while the app/window switcher is up.

The current result of having both up simultaneously is clearly broken,
so we can either dismiss the popup or prevent the modal dialog from
opening. Assume that the dialog indicates a more important action and
should therefore take precedence, so go with the former.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1536
2019-12-11 20:35:13 +01:00
Florian Müllner
5043e6d6bd weather: Only require auto-location authorization if sandboxed
Since commit 87e60ed97843, geoclue no longer pretends that authorization
is useful for system-installed apps (as they can easily lie about their
ID). Unfortunately this broke our auto-location support in case Weather
is installed non-sandboxed, as we are waiting for an authorization that
will never happen.

Unbreak it by only requiring authorization when installed as Flatpak.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1823
2019-12-11 20:35:13 +01:00
Benjamin Berg
7be1729cde util: Place spawned processes into a systemd scope
This improves the separation from the shell for applications launched
with Alt+F2 and in a few other cases.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/863
(cherry picked from commit 4a6c2f1fe6)
2019-12-11 14:28:27 +01:00
Benjamin Berg
f92cb46b02 shell-global: Place launched applications into a systemd scope
This improves separation from the shells service scope for applications
launched using an XDG desktop file.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/863
(cherry picked from commit 086ba11621)
2019-12-11 14:28:27 +01:00
Umarzuki Bin Mochlis Moktar
56902542c7 Update Malay translation 2019-12-09 10:24:46 +00:00
Jonas Dreßler
523eea4527 closeDialog: Fix scale of dialog for x11 clients in Wayland sessions
We missed this case in b6e57a5ae8,
XWayland clients obviously don't use MetaWindowWayland and thus they
don't apply the double scaling that commit was meant to fix.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/884
2019-12-04 23:41:02 +01:00
Florian Müllner
a7b0e96304 switcherPopup: Fix scrollable check
When commit c6cea277e replaced Shell.GenericContainer, the check
whether the required width exceeds the avilable width was changed
from using the minimum widths of items to the natural width of the
scroll view.

That doesn't work correctly, as the *natural* width may well exceed
the actually used width: SwitcherList bases its width request on
children's minimum sizes to force labels to ellipsize.

Fix this by using the minimum width of the scroll view's child instead.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1834


(cherry picked from commit 867cffaf20)
2019-11-29 17:53:58 +00:00
Florian Müllner
bb24df2f9d calendar-server: Use correct timezone for all-day events
Since commit 28c535e34, we use the timezone associated with the ICalTime
instead of the default timezone when converting to time_t. However while
that is correct for most events, for ICalTimes that don't have a timezone
associated we still want to fall back to the default timezone instead of
UTC.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1895
2019-11-28 14:19:19 +01:00
Joonas Henriksson
9150cbca3e theme: Add light styling to message buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/865
2019-11-27 20:17:57 +01:00
Yi-Jyun Pan
35bb67bb2f Update Chinese (Taiwan) translation 2019-11-27 16:07:32 +00:00
Joonas Henriksson
d4c2f9d0ef appIcon: Draw running dot above the overview icon
Prevent the app-well-app-running dot from getting unintentionally
hidden behind the overview-icon background by initializing the
running-dot after its sibling overview-icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/866
2019-11-27 03:20:05 +01:00
Daniel García Moreno
e211c68a5c texture-cache: Remove also scaled keys from the cache
We're storing in the texture cache images and scaled images appending
the scaling factor to the key. When a file changes the cache key
corresponding to that file is removed, but not the keys for the scaled
ones so that images in the cache are never reloaded.

This patch removes all keys from the cache related to the file that
changes, including those with the scaling factor.

A new set (hash table) was added to keep track of scale used to be able
to remove all possible images in the cache.

When the KEY is removed from the cache, we can look now in the scale set
for and each scale we also remove the key "KEY1.000000", "KEY2.000000",
etc.

Assuming that the number of used scales is small (I would typically
expect one or two), the overhead should be negligible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/567
2019-11-26 14:21:46 +01:00
Benjamin Berg
af95883807 data: Enable clean session shutdown after gnome-shell failure
If the GNOME shell crashes, we run a service that may disable
extensions. This is important so that users will not be locked out of
their own session in case an extension is causing crashes.

As this is a very agressive action, we tried to only do this in the
first two minutes of the session. Unfortunately, the logic was broken
and would result in an unclean session shutdown.

Fix this by using the newly introduced gnome-shell-disable-extensions
file. This is created by the extension subsystem for a period of time to
indicate the extensions may be the cause of a gnome-shell failure.

See
  https://gitlab.gnome.org/GNOME/gnome-session/issues/43
for a log of the bug happening and the gnome-session part to fix this.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/858
2019-11-25 23:38:32 +01:00
Benjamin Berg
91f41105d5 extensionSystem: Create a file to flag that extensions are being loaded
When the extension system is loaded, create the
gnome-shell-disable-extensions file in the users runtime directory. This
file is automatically removed 60s later. The sole purpose of this file
is to be consumed by the systemd units. If the file exists, the systemd
units will disable extensions when the gnome-shell fails.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/858
2019-11-25 23:38:32 +01:00
Florian Müllner
45fa520cca extensions-tool: Fix removing from settings list
When removing a string from a settings list, we iterate over all
existing entries and copy all strings except the one that's being
removed to a new list, which is then written to GSettings.

However we currently always increment the index, so we end up with
a NULL entry in place of the removed entry, which is then interpreted
as the end of the list. In other words, we also remove all entries
that follow the removed string.

Fix this by looping over the list entries instead of the index, and
only increment the index for entries we copy.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1946
2019-11-25 21:05:32 +01:00
Florian Müllner
334762ee9e introspect: Fix whitelist check
The whitelist is a list of well-known D-Bus names, which we then search
for the unique name we get from the method invocation - unsuccesfully.

Fix this by watching the bus for any name in the whitelist in order
to maintain a map from wel-known to unique name that we can use for
matching.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1916


(cherry picked from commit eee1ab4890)
2019-11-25 19:20:01 +00:00
Joonas Henriksson
88e3dfa104 theme: Add :active styling to message-close and media control buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Joonas Henriksson
4b89314813 theme: Add message close button styling
Since the notification message close button had no border, or mouse
over effect, there was no way to determine whether the mouse cursor
were over the button.

Improve this by adding a message-close-button class for the close
button, and a styling for its hovered state, based on media control
button styling.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Joonas Henriksson
a9fa4cc49e theme: Darken hovered message-media-control button
Increases contrast between normal and hovered states in
message-media-control buttons. Previously there was very little
difference between the two states, making it hard to distinguish
whether the mouse cursor was over the button.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Jonas Dreßler
9476c9c4ca magnifier: Use new cursor tracker API to keep wayland focus while hidden
Since commit mutter/a2a8f0cda we force the focus surface of the
meta-wayland-pointer to NULL while the pointer is hidden. This
introduced an issue with the magnifier, where we use
`set_pointer_visible` to hide the real cursor and show our own cursor at
the correct position: Because the meta-wayland-pointer is still used to
communicate with Wayland clients, the UI of the windows will not respond
to mouse movement anymore as soon as the real cursor is hidden.

To fix this, use the newly added API of MetaCursorTracker to switch back
to the old behavior while the magnifier is hiding the system cursor.

In the future and as a more correct fix, we might want to rewrite the
magnifier so it doesn't have to hide the cursor and can simply show the
default one (eg. by scaling the actual view instead of a clone of the
view).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/754
2019-11-25 15:21:29 +00:00
Jonas Dreßler
24df43d579 magnifier: Use own showSystemCursor() instead of set_pointer_visible()
We already have our own function to show the system cursor, use it!

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/754
2019-11-25 15:21:29 +00:00
Ricardo Silva Veloso
363336e4a1 Update Brazilian Portuguese translation 2019-11-25 14:12:45 +00:00
Joaquim Rocha
070c784412 polkitAgent: Use dialog as confirmation when the user has no password
When a user has no password and a polkit authentication is started,
instead of blindly initiating the admin session, show the regular
"Authentication Requested" dialog (but without the password entry). This
makes sure that the user's admin session is only effectively started
after the user chooses to proceed with the authentication, which
provides an extra confirmation step that can be vital for critical
tasks.

To do this, we show the dialog inside `_onUserChanged()` right after the
dialog was created instead of calling `performAuthentication()` from
`_onInitiate()`. The bug mentioned in `_onInitiate()` is no longer an
issue since we show the dialog in all cases now anyway.

Ideally we should use a different wording than "authentication" when the
user has no password set, and use "confirmation" instead. However polkit
already sends the requests with such messages (e.g. "Authentication is
required to configure software repositories"), and it's important to
show those to the user, so this patch keeps the regular wording.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/829
2019-11-24 20:23:42 +01:00
Jonas Dreßler
455eb67a49 polkitAgent: Update user name on user changes
Right now we only update the user avatar on the user-changed signal, but
since we also display the users real name we should also update that if
the user changes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/788
2019-11-24 20:23:42 +01:00
Jonas Dreßler
23cc59f52a polkitAgent: Fix a typo of a signal name
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/788
2019-11-24 20:23:42 +01:00
Jonas Dreßler
19bb459a57 appDisplay: Add a timeout when switching pages during DnD
Currently when dragging an icon to the space above or below the appGrid
to switch pages, we do so very quickly without checking when the last
page-switch happened. This makes it hard to move icons to pages which
are not the first or the last one, since the other pages are skipped
very quickly.

To fix this, add a timeout of 1 second that blocks switching pages after
a page-switch using drag overshoot occured.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1693
2019-11-24 20:18:42 +01:00
Florian Müllner
48477443fa appDisplay: Add threshold after overshoot page switches
We currently always switch app pages when a dragged app icon
moves outside the grid boundaries, regardless of any previous
page switches. This makes it too easy to switch multiple pages
accidentally, so add a small threshold that the icon has to
move back towards the grid before allowing another page switch.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1693
2019-11-24 20:17:47 +01:00
Jonas Dreßler
40b2fbf465 appDisplay: Simplify event blocking while folder is opened
There's no need for a `inhibitEventBlocker` interface. Since we connect
to "open-state-changed" of our folders in the AllView anyway, we can
just make the event blocker visible while a folder is opened, and hide
the event blocker during DnD.

This allows keeping the eventBlocker reactive at all times and fixes an
issue where DnD to create a new folder is impossible if no folders are
present because the eventBlocker would not get inhibited.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1652
2019-11-23 18:51:44 +01:00
Jonas Dreßler
7800bd2158 appDisplay: Ensure we don't recreate existing AppIcons for folders
This was missed in 910037f014, make sure
we do the same thing for AppIcons that are created when reloading
folders.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/851
2019-11-23 15:30:03 +01:00
Jonas Dreßler
d4f07410a1 appDisplay: Add missing .actor
This was missed while cherry picking
b88f7d0655 to 3.34.

Thanks to Térence Clastres for finding the issue and testing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/852
2019-11-23 22:00:37 +01:00
Florian Müllner
64b62de5df keyboard: Try harder to find a matching layout
While we support a reasonable list of layouts nowadays, we don't
include many variants like `fr+oss`. Instead of directly falling
back to the `us` layout, try stripping the variant first, as the
base layout is likely closer to the expectation than `us`.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1907


(cherry picked from commit c1ec7b2ffa)
2019-11-23 00:38:53 +00:00
Florian Müllner
9b0d42309b screenShield: Replace child properties
It turns out https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/780
helped with some redrawing issues on the screen shield, so cherry-pick the
relevant bits to the stable branch.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1836
2019-11-23 00:19:26 +00:00
Florian Müllner
cf249ab870 switcherPopup: Fix last commit
The surrounding code has diverged on master, so the cherry-picked
commit doesn't work without adjustments, whoops.
2019-11-23 01:05:31 +01:00
Florian Müllner
c752682ab9 switcherPopup: Improve modifier-less keybinding navigation
Commit c899453800 lifted the requirement of switcher keybindings
to contain a modifier, however it is currently only possible to
finish it by letting it time out.

Improve that by also accepting space/enter key presses to confirm the
selection immediately.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1883
2019-11-23 01:00:21 +01:00
Jonas Dreßler
a6e4ef862c switcherPopup: Use roundtrip time when the popup is modifier-less
The noModsTimeout obviously finishes inside a timeout callback, which
means `global.get_current_time()` might return Clutter.CURRENT_TIME (ie.
0) when called inside it, because it's not called while handling an
event. This means when switching apps or activating a window, the
timestamp passed to `activate_window` may be 0, which is the reason why
the altTab switcher is currently broken when using modifier-less
keybindings.

Fix that by using `meta_display_get_current_time_roundtrip`, which
always return a valid timestamp, instead of
`shell_global_get_current_time`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/847
2019-11-23 00:59:57 +01:00
Philip Chimento
8d2365b7b9 appDisplay: Don't crash if app is missing categories
g_desktop_app_info_get_categories() may return null. In that case, the
previous code would fail to create a folder when dragging an app with
no categories onto another app. Instead, simply continue with the next
app info.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/782
2019-11-23 00:57:59 +01:00
Florian Müllner
03219f745d panel: Update window section items on title changes
We currently only update the windows section when either the focus
app changes, or when the app's windows change (that is, a window is
opened or closed). This allows the menu item labels to become stale
if the window title changes after one of those events (for example
when switching tabs).

Fix this by updating menu items when the corresponding window
title changes.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1830
2019-11-22 01:33:45 +01:00
Philip Chimento
7d34dee77f power: Handle "100% but charging" case
I've observed that UPower can occasionally report a charge level of 100%
while the state is still "charging". This usually doesn't last very long
but it is noticeable because the power icon changes to a "missing icon"
icon. This will handle that rare case correctly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/814
2019-11-22 00:33:23 +01:00
Jonas Dreßler
f0e59ea088 closeDialog: Fix dialog size when using geometry scaling
The close dialog is added as a child to MetaWindowActor, and, in Wayland
sessions, since commit [1] MetaWindowActor applies a transformation
matrix which scales all it's children using the geometry scale factor.
Now because the dialog actor is not a window (i.e. a MetaSurfaceActor),
but a subclass of StWidget, the scale factor is also applied to the
properties of the dialog by StThemeNode, so we end up applying the
geometry scale twice to the close dialog.

Fix this by applying the inverted scale to the dialog, which leaves the
scaling only to MetaWindowActor. This means we also can't apply a pivot
point other than 0 to the dialog actor, so apply the 0.5-pivot point to
the `_dialog` child of the Dialog class (the actual visible dialog box)
and also perform scaling animations on this child.

[1] https://gitlab.gnome.org/GNOME/mutter/commit/fb9e8768

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/783
2019-11-22 00:30:23 +01:00
Georges Basile Stavracas Neto
f8a90f6583 appIcon: Remove drag monitor on destroy
It may happen that the app icon is destroyed with a drag
monitor still around, in which case, a load of warnings
will be shown.

Make sure to remove any pending drag monitor on destroy.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:12 -03:00
Georges Basile Stavracas Neto
aa1d297bdf folderView: Reset schemas before removing the folder
When removing the last icon of a folder, FolderView first removes
the folder from org.gnome.desktop.app-folders.folder-children, then
proceeds to reset all its keys, which removes the relocatable schema.

That order of operations turns out to be problematic. Removing the
folder from 'folder-children' destroys the folder icon, which in turn
destroys the folder view, which throws a load of warnings in the
journal.

Fix that by removing the folder after resetting the schema keys. In
fact, what we're doing here is not using 'this' anymore.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:11 -03:00
Georges Basile Stavracas Neto
b88f7d0655 baseAppView: Destroy icon when removing
We cannot rely on the garbage collector to do that in a timely
manner, so destroy it explicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:08 -03:00
Georges Basile Stavracas Neto
59daa4192c allView: Rename variable
The variable that holds the list of application icons is
called 'newApps', but that technically was never true,
since we only create new app icons when necessary.

Rename it to 'appIcons'.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:06 -03:00
Georges Basile Stavracas Neto
d08cd1f523 allView, frequentView: Only create icons when necessary
The views (AllView and FrequentView) build a list of all applications
they contain. BaseView then diffs between what's currently added, and
what needs to be added, and removed.

This approach has a problem though: creating an AppIcon or a FolderIcon
connects to various signals, and we confuse the garbage collector.

When building the list of applications, instead of always creating new
icons, try to use already existing icons first.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1610
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1694
2019-11-21 20:13:04 -03:00
Florian Müllner
a85cddada0 polkitAgent: Fix spinner
Commit 6af25b282c accidentally changed the case of the property.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/840


(cherry picked from commit acaa9f7f77)
2019-11-21 21:57:55 +00:00
cunidev
ae8568a2e0 Increase .calendar-today visibility
Adds some needed contrast to the calendar widget current day, solving #1873.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/823
2019-11-20 13:45:58 +01:00
Joonas Henriksson
4a3ca40c48 appMenu: Hide stopped spinner actor
Get rid of leftover empty space from the application menu panel
button, that was used by the spinner actor, which remained visible
even after the spinner had stopped.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1679
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:34 +02:00
Joonas Henriksson
e257be64d0 animation: Add parameter for hiding stopped Spinner actor
Not hiding leaves the empty actor space visible, which may have an
undesirable effect on the parent element's size or spacing/padding.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:34 +02:00
Joonas Henriksson
96ac00b53c animation: Turn Spinner animate parameter into Params option
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:29 +02:00
Florian Müllner
7e8884a601 windowManager: Replace left-over calls to _removeEffect()
Those calls no longer exist on master, so the cherry-pick commit in
22b6a09cd7 missed them.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1884
2019-11-11 22:39:58 +01:00
Stas Solovey
ef726bf313 Update Russian translation 2019-11-11 19:27:16 +00:00
Florian Müllner
a43c22e3af windowManager: Complete interrupted size change effects
Resizing effects are more finicky as other effects, as the actual
animation is delayed until we receive the ::size-changed signal.

However that signal may never be emitted if the window is destroyed
just after starting the size-change effect, in which case the effect
is never completed, blocking mutter from destroying the corresponding
window actor.

Address this by tracking when a resize effect is pending, and complete
the effect when appropriate.

https://gitlab.gnome.org/GNOME/mutter/issues/655
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/815
2019-11-08 23:20:17 +01:00
Florian Müllner
22b6a09cd7 windowManager: Use Sets to track ongoing effects
We only care whether an effect is ongoing for an actor, not about
any particular order. Sets are more convenient than arrays in that
case, so use them instead.

https://gitlab.gnome.org/GNOME/mutter/issues/655
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/815
2019-11-08 23:20:17 +01:00
Florian Müllner
65110968c5 ci: Fix checking out mutter on stable branches
For stable branches, we currently only check out the correct mutter
branch for merge requests. For the regular pipeline, our code to
determine the current shell branch fails because CI runs on a
temporary "pipeline/12345" branch that doesn't exist for mutter.

Switching to the correct gitlab environment variable fixes that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/811


(cherry picked from commit fd5989e99a)
2019-11-06 22:59:50 +00:00
monday
d142f59478 theme: Adjust system-menu-action buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/802
2019-11-05 14:16:09 +01:00
Milan Crha
c1ecd304e7 calendar-server: Uses wrong timezone for event times
The conversion to UTC/time_t time was not using correct timezone.

Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1714
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/806


(cherry picked from commit 28c535e341)
2019-11-05 11:58:17 +00:00
Philip Chimento
750c5acd30 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


(cherry picked from commit 055c007ac2)
2019-10-24 23:08:08 +00:00
Robert Mader
246150d8b6 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


(cherry picked from commit 20f4fc7c87)
2019-10-21 09:46:37 +00:00
Andrew Watson
072a9a4842 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


(cherry picked from commit d91927674d)
2019-10-17 08:07:22 +00:00
Marco Trevisan (Treviño)
7149da3f4f 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


(cherry picked from commit ab6a629955)
2019-10-16 23:57:24 +00:00
Florian Müllner
6c2a82258e 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


(cherry picked from commit 38ad1d7c13)
2019-10-14 08:54:20 +00:00
259 changed files with 16702 additions and 36950 deletions

6
.eslintrc.json Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

111
NEWS
View File

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

View File

@@ -30,3 +30,6 @@
/* Define if fdwalk is available in libc */ /* Define if fdwalk is available in libc */
#mesondefine HAVE_FDWALK #mesondefine HAVE_FDWALK
/* Define if we have gnome-desktop systemd utils */
#mesondefine HAVE_GNOME_SYSTEMD

View File

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

View File

@@ -36,8 +36,10 @@ $_hover_bg_color: lighten($bg_color,if($variant=='light', 5%, 3%));
$_active_bg_color: if($variant == 'light', darken($bg_color, 14%), darken($bg_color, 9%)); $_active_bg_color: if($variant == 'light', darken($bg_color, 14%), darken($bg_color, 9%));
$font-size: 11; $font-size: 11;
$font-family: Cantarell, Sans-Serif;
stage { stage {
font-family: $font-family;
@include fontsize($font-size); @include fontsize($font-size);
color: $fg_color; color: $fg_color;
} }
@@ -977,7 +979,6 @@ StScrollBar {
spacing-columns: 0.8em; spacing-columns: 0.8em;
} }
.weather-header-box,
.weather-box { .weather-box {
spacing: 0.4em; spacing: 0.4em;
} }
@@ -1196,8 +1197,7 @@ StScrollBar {
.aggregate-menu { .aggregate-menu {
min-width: 21em; min-width: 21em;
.popup-menu-icon { padding: 0 4px; .popup-menu-icon { padding: 0 4px; }
-st-icon-style: symbolic; }
.popup-sub-menu .popup-menu-item > :first-child { .popup-sub-menu .popup-menu-item > :first-child {
&:ltr { /* 12px spacing + 2*4px padding */ &:ltr { /* 12px spacing + 2*4px padding */
padding-left: 20px; margin-left: 1.09em; } padding-left: 20px; margin-left: 1.09em; }
@@ -1206,6 +1206,26 @@ StScrollBar {
} }
} }
.system-menu-action {
-st-icon-style: symbolic;
color: $fg_color;
border-radius: 32px; /* wish we could do 50% */
padding: 13px;
border: 1px solid $_bubble_borders_color;
&:hover, &:focus {
background-color: $_hover_bg_color;
color: $fg_color;
}
&:active {
background-color: $selected_bg_color;
color: $selected_fg_color;
border-color: $selected_borders_color;
}
& > StIcon { icon-size: 16px; }
}
// Activities Ripples // Activities Ripples
.ripple-box { .ripple-box {
width: 52px; width: 52px;
@@ -1557,14 +1577,20 @@ StScrollBar {
} }
.page-indicator { .page-indicator {
padding: 7px 16px; padding: 15px 20px;
.page-indicator-icon { .page-indicator-icon {
width: 12px; width: 12px;
height: 12px; height: 12px;
background-color: white; background-color: transparent;
border-radius: 6px; border: 2px solid rgba(255, 255, 255, 0.4);
border-radius: 12px;
} }
&:hover .page-indicator-icon { border-color: white; }
&:active .page-indicator-icon { border: none; margin: 2px; background-color: white; }
&:checked .page-indicator-icon,
&:checked:active .page-indicator-icon { background-color: white;}
} }
.no-frequent-applications-label { @extend %status_text; } .no-frequent-applications-label { @extend %status_text; }
@@ -1764,8 +1790,8 @@ StScrollBar {
padding: 4px 4px; padding: 4px 4px;
.page-indicator-icon { .page-indicator-icon {
width: 8px; width: 6px;
height: 8px; height: 6px
} }
} }
} }

View File

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

View File

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

View File

@@ -1,12 +1,11 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AuthPrompt */
const { Clutter, GObject, Pango, Shell, St } = imports.gi; const { Clutter, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Animation = imports.ui.animation; const Animation = imports.ui.animation;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util; const GdmUtil = imports.gdm.util;
const Util = imports.misc.util;
const Params = imports.misc.params; const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget; const UserWidget = imports.ui.userWidget;
@@ -17,42 +16,25 @@ var DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300;
var MESSAGE_FADE_OUT_ANIMATION_TIME = 500; var MESSAGE_FADE_OUT_ANIMATION_TIME = 500;
const WIGGLE_OFFSET = 6;
const WIGGLE_DURATION = 65;
const N_WIGGLES = 3;
var AuthPromptMode = { var AuthPromptMode = {
UNLOCK_ONLY: 0, UNLOCK_ONLY: 0,
UNLOCK_OR_LOG_IN: 1, UNLOCK_OR_LOG_IN: 1
}; };
var AuthPromptStatus = { var AuthPromptStatus = {
NOT_VERIFYING: 0, NOT_VERIFYING: 0,
VERIFYING: 1, VERIFYING: 1,
VERIFICATION_FAILED: 2, VERIFICATION_FAILED: 2,
VERIFICATION_SUCCEEDED: 3, VERIFICATION_SUCCEEDED: 3
}; };
var BeginRequestType = { var BeginRequestType = {
PROVIDE_USERNAME: 0, PROVIDE_USERNAME: 0,
DONT_PROVIDE_USERNAME: 1, DONT_PROVIDE_USERNAME: 1
}; };
var AuthPrompt = GObject.registerClass({ var AuthPrompt = class {
Signals: { constructor(gdmClient, mode) {
'cancelled': {},
'failed': {},
'next': {},
'prompted': {},
'reset': { param_types: [GObject.TYPE_UINT] },
},
}, class AuthPrompt extends St.BoxLayout {
_init(gdmClient, mode) {
super._init({
style_class: 'login-dialog-prompt-layout',
vertical: true,
});
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient; this._gdmClient = gdmClient;
@@ -64,7 +46,7 @@ var AuthPrompt = GObject.registerClass({
else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN) else if (this._mode == AuthPromptMode.UNLOCK_OR_LOG_IN)
reauthenticationOnly = false; reauthenticationOnly = false;
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly }); this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: reauthenticationOnly });
this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this)); this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this));
this._userVerifier.connect('show-message', this._onShowMessage.bind(this)); this._userVerifier.connect('show-message', this._onShowMessage.bind(this));
@@ -78,68 +60,70 @@ var AuthPrompt = GObject.registerClass({
this.connect('next', () => { this.connect('next', () => {
this.updateSensitivity(false); this.updateSensitivity(false);
this.startSpinning(); this.startSpinning();
if (this._queryingService) if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text); this._userVerifier.answerQuery(this._queryingService, this._entry.text);
else } else {
this._preemptiveAnswer = this._entry.text; this._preemptiveAnswer = this._entry.text;
}
}); });
this.connect('destroy', this._onDestroy.bind(this)); this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this._userWell = new St.Bin({ this.actor.connect('destroy', this._onDestroy.bind(this));
x_expand: true, this.actor.connect('key-press-event', (actor, event) => {
y_expand: true, if (event.get_key_symbol() == Clutter.KEY_Escape)
}); this.cancel();
this.add_child(this._userWell); return Clutter.EVENT_PROPAGATE;
this._label = new St.Label({
style_class: 'login-dialog-prompt-label',
x_expand: false,
y_expand: true,
}); });
this.add_child(this._label); this._userWell = new St.Bin({ x_fill: true,
this._entry = new St.Entry({ x_align: St.Align.START });
style_class: 'login-dialog-prompt-entry', this.actor.add(this._userWell,
can_focus: true, { x_align: St.Align.START,
x_expand: false, x_fill: true,
y_expand: 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._entry = new St.Entry({ style_class: 'login-dialog-prompt-entry',
can_focus: true });
ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE }); ShellEntry.addContextMenu(this._entry, { isPassword: true, actionMode: Shell.ActionMode.NONE });
this.add_child(this._entry); this.actor.add(this._entry,
{ expand: true,
x_fill: true,
y_fill: false,
x_align: St.Align.START });
this._entry.grab_key_focus(); this._entry.grab_key_focus();
this._message = new St.Label({ this._message = new St.Label({ opacity: 0,
opacity: 0, styleClass: 'login-dialog-message' });
styleClass: 'login-dialog-message',
x_expand: false,
y_expand: true,
y_align: Clutter.ActorAlign.START,
});
this._message.clutter_text.line_wrap = true; this._message.clutter_text.line_wrap = true;
this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._message.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this.add_child(this._message); this.actor.add(this._message, { x_fill: false, x_align: St.Align.START, y_align: St.Align.START });
this._buttonBox = new St.BoxLayout({ this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
style_class: 'login-dialog-button-box', vertical: false });
vertical: false, this.actor.add(this._buttonBox,
y_align: Clutter.ActorAlign.END, { expand: true,
}); x_align: St.Align.MIDDLE,
this.add_child(this._buttonBox); y_align: St.Align.END });
this._defaultButtonWell = new St.Widget({ this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
layout_manager: new Clutter.BinLayout(), this._defaultButtonWellActor = null;
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
});
this._initButtons(); this._initButtons();
this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE); this._spinner = new Animation.Spinner(DEFAULT_BUTTON_WELL_ICON_SIZE);
this._spinner.opacity = 0; this._spinner.actor.opacity = 0;
this._spinner.show(); this._spinner.actor.show();
this._defaultButtonWell.add_child(this._spinner); this._defaultButtonWell.add_child(this._spinner.actor);
} }
_onDestroy() { _onDestroy() {
@@ -147,39 +131,39 @@ var AuthPrompt = GObject.registerClass({
this._userVerifier = null; this._userVerifier = null;
} }
vfunc_key_press_event(keyPressEvent) {
if (keyPressEvent.keyval == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
}
_initButtons() { _initButtons() {
this.cancelButton = new St.Button({ this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Cancel"), label: _("Cancel") });
x_expand: true,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END,
});
this.cancelButton.connect('clicked', () => this.cancel()); this.cancelButton.connect('clicked', () => this.cancel());
this._buttonBox.add_child(this.cancelButton); this._buttonBox.add(this.cancelButton,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
this._buttonBox.add_child(this._defaultButtonWell); this._buttonBox.add(this._defaultButtonWell,
this.nextButton = new St.Button({ { expand: true,
style_class: 'modal-dialog-button button', x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
this.nextButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true, reactive: true,
can_focus: true, can_focus: true,
label: _("Next"), label: _("Next") });
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
});
this.nextButton.connect('clicked', () => this.emit('next')); this.nextButton.connect('clicked', () => this.emit('next'));
this.nextButton.add_style_pseudo_class('default'); this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add_child(this.nextButton); this._buttonBox.add(this.nextButton,
{ expand: false,
x_fill: false,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.END });
this._updateNextButtonSensitivity(this._entry.text.length > 0); this._updateNextButtonSensitivity(this._entry.text.length > 0);
@@ -257,12 +241,6 @@ var AuthPrompt = GObject.registerClass({
this.updateSensitivity(canRetry); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
Util.wiggle(this._entry, {
offset: WIGGLE_OFFSET,
duration: WIGGLE_DURATION,
wiggleCount: N_WIGGLES,
});
} }
_onVerificationComplete() { _onVerificationComplete() {
@@ -291,13 +269,13 @@ var AuthPrompt = GObject.registerClass({
oldActor.remove_all_transitions(); oldActor.remove_all_transitions();
let wasSpinner; let wasSpinner;
if (oldActor == this._spinner) if (oldActor == this._spinner.actor)
wasSpinner = true; wasSpinner = true;
else else
wasSpinner = false; wasSpinner = false;
let isSpinner; let isSpinner;
if (actor == this._spinner) if (actor == this._spinner.actor)
isSpinner = true; isSpinner = true;
else else
isSpinner = false; isSpinner = false;
@@ -321,7 +299,7 @@ var AuthPrompt = GObject.registerClass({
if (this._spinner) if (this._spinner)
this._spinner.stop(); this._spinner.stop();
} }
}, }
}); });
} }
} }
@@ -330,23 +308,22 @@ var AuthPrompt = GObject.registerClass({
if (isSpinner) if (isSpinner)
this._spinner.play(); this._spinner.play();
if (!animate) { if (!animate)
actor.opacity = 255; actor.opacity = 255;
} else { else
actor.ease({ actor.ease({
opacity: 255, opacity: 255,
duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY, delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR
}); });
} }
}
this._defaultButtonWellActor = actor; this._defaultButtonWellActor = actor;
} }
startSpinning() { startSpinning() {
this.setActorInDefaultButtonWell(this._spinner, true); this.setActorInDefaultButtonWell(this._spinner.actor, true);
} }
stopSpinning() { stopSpinning() {
@@ -392,7 +369,7 @@ var AuthPrompt = GObject.registerClass({
this._message.ease({ this._message.ease({
opacity: 0, opacity: 0,
duration: MESSAGE_FADE_OUT_ANIMATION_TIME, duration: MESSAGE_FADE_OUT_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD
}); });
} }
@@ -427,9 +404,9 @@ var AuthPrompt = GObject.registerClass({
this._entry.clutter_text.editable = sensitive; this._entry.clutter_text.editable = sensitive;
} }
vfunc_hide() { hide() {
this.setActorInDefaultButtonWell(null, true); this.setActorInDefaultButtonWell(null, true);
super.vfunc_hide(); this.actor.hide();
this._message.opacity = 0; this._message.opacity = 0;
this.setUser(null); this.setUser(null);
@@ -445,8 +422,7 @@ var AuthPrompt = GObject.registerClass({
if (user) { if (user) {
let userWidget = new UserWidget.UserWidget(user); let userWidget = new UserWidget.UserWidget(user);
userWidget.x_align = Clutter.ActorAlign.START; this._userWell.set_child(userWidget.actor);
this._userWell.set_child(userWidget);
} }
} }
@@ -525,10 +501,11 @@ var AuthPrompt = GObject.registerClass({
} }
cancel() { cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return; return;
}
this.reset(); this.reset();
this.emit('cancelled'); this.emit('cancelled');
} }
}); };
Signals.addSignalMethods(AuthPrompt.prototype);

View File

@@ -112,12 +112,13 @@ var Batch = class extends Task {
for (let i = 0; i < tasks.length; i++) { for (let i = 0; i < tasks.length; i++) {
let task; let task;
if (tasks[i] instanceof Task) if (tasks[i] instanceof Task) {
task = tasks[i]; task = tasks[i];
else if (typeof tasks[i] == 'function') } else if (typeof tasks[i] == 'function') {
task = new Task(scope, tasks[i]); task = new Task(scope, tasks[i]);
else } else {
throw new Error('Batch tasks must be functions or Task, Hold or Batch objects'); throw new Error('Batch tasks must be functions or Task, Hold or Batch objects');
}
this.tasks.push(task); this.tasks.push(task);
} }
@@ -128,8 +129,9 @@ var Batch = class extends Task {
} }
runTask() { runTask() {
if (!(this._currentTaskIndex in this.tasks)) if (!(this._currentTaskIndex in this.tasks)) {
return null; return null;
}
return this.tasks[this._currentTaskIndex].run(); return this.tasks[this._currentTaskIndex].run();
} }
@@ -177,8 +179,9 @@ var ConcurrentBatch = class extends Batch {
process() { process() {
let hold = this.runTask(); let hold = this.runTask();
if (hold) if (hold) {
this.hold.acquireUntilAfter(hold); this.hold.acquireUntilAfter(hold);
}
// Regardless of the state of the just run task, // Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run // fire off the next one, so all the tasks can run

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,6 +15,5 @@ var LOCALEDIR = '@datadir@/locale';
/* other standard directories */ /* other standard directories */
var LIBEXECDIR = '@libexecdir@'; var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@'; var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
var VPNDIR = '@vpndir@';
/* g-i package versions */ /* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@' var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

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

View File

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

View File

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

View File

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

View File

@@ -157,10 +157,10 @@ var IBusManager = class {
} catch (e) { } catch (e) {
} }
// If an engine is already active we need to get its properties // If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, res) => { this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => {
let engine; let engine;
try { try {
engine = this._ibus.get_global_engine_async_finish(res); engine = this._ibus.get_global_engine_async_finish(result);
if (!engine) if (!engine)
return; return;
} catch (e) { } catch (e) {

View File

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

View File

@@ -79,7 +79,7 @@ var IntrospectService = class {
for (let app of apps) { for (let app of apps) {
let appInfo = {}; let appInfo = {};
let isAppActive = focusedApp == app; let isAppActive = (focusedApp == app);
if (!this._isStandaloneApp(app)) if (!this._isStandaloneApp(app))
continue; continue;
@@ -113,10 +113,10 @@ var IntrospectService = class {
return false; return false;
let type = window.get_window_type(); let type = window.get_window_type();
return type == Meta.WindowType.NORMAL || return (type == Meta.WindowType.NORMAL ||
type == Meta.WindowType.DIALOG || type == Meta.WindowType.DIALOG ||
type == Meta.WindowType.MODAL_DIALOG || type == Meta.WindowType.MODAL_DIALOG ||
type == Meta.WindowType.UTILITY; type == Meta.WindowType.UTILITY);
} }
GetRunningApplicationsAsync(params, invocation) { GetRunningApplicationsAsync(params, invocation) {
@@ -161,9 +161,9 @@ var IntrospectService = class {
'app-id': GLib.Variant.new('s', app.get_id()), 'app-id': GLib.Variant.new('s', app.get_id()),
'client-type': GLib.Variant.new('u', window.get_client_type()), 'client-type': GLib.Variant.new('u', window.get_client_type()),
'is-hidden': GLib.Variant.new('b', window.is_hidden()), 'is-hidden': GLib.Variant.new('b', window.is_hidden()),
'has-focus': GLib.Variant.new('b', window == focusWindow), 'has-focus': GLib.Variant.new('b', (window == focusWindow)),
'width': GLib.Variant.new('u', frameRect.width), 'width': GLib.Variant.new('u', frameRect.width),
'height': GLib.Variant.new('u', frameRect.height), 'height': GLib.Variant.new('u', frameRect.height)
}; };
// These properties may not be available for all windows: // These properties may not be available for all windows:
@@ -173,12 +173,11 @@ var IntrospectService = class {
if (wmClass != null) if (wmClass != null)
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass); windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
if (sandboxedAppId != null) { if (sandboxedAppId != null)
windowsList[windowId]['sandboxed-app-id'] = windowsList[windowId]['sandboxed-app-id'] =
GLib.Variant.new('s', sandboxedAppId); GLib.Variant.new('s', sandboxedAppId);
} }
} }
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList])); invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
} }
}; };

View File

@@ -11,8 +11,9 @@ function getCompletions(text, commandHeader, globalCompletionList) {
let methods = []; let methods = [];
let expr_, base; let expr_, base;
let attrHead = ''; let attrHead = '';
if (globalCompletionList == null) if (globalCompletionList == null) {
globalCompletionList = []; globalCompletionList = [];
}
let offset = getExpressionOffset(text, text.length - 1); let offset = getExpressionOffset(text, text.length - 1);
if (offset >= 0) { if (offset >= 0) {
@@ -58,18 +59,20 @@ function isStopChar(c) {
function findMatchingQuote(expr, offset) { function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset); let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) { for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') {
return i; return i;
} }
}
return -1; return -1;
} }
// Given the ending position of a regex, find where it starts // Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) { function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) { for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') {
return i; return i;
} }
}
return -1; return -1;
} }
@@ -79,30 +82,31 @@ function findMatchingSlash(expr, offset) {
// findMatchingBrace("[(])", 3) returns 1. // findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) { function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset); let closeBrace = expr.charAt(offset);
let openBrace = { ')': '(', ']': '[' }[closeBrace]; let openBrace = ({ ')': '(', ']': '[' })[closeBrace];
return findTheBrace(expr, offset - 1, openBrace, closeBrace); function findTheBrace(expr, offset) {
if (offset < 0) {
return -1;
} }
function findTheBrace(expr, offset, ...braces) { if (expr.charAt(offset) == openBrace) {
let [openBrace, closeBrace] = braces;
if (offset < 0)
return -1;
if (expr.charAt(offset) == openBrace)
return offset; return offset;
}
if (expr.charAt(offset).match(/['"]/)) {
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
}
if (expr.charAt(offset) == '/') {
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
}
if (expr.charAt(offset) == closeBrace) {
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
}
if (expr.charAt(offset).match(/['"]/)) return findTheBrace(expr, offset - 1);
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == '/') }
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1, ...braces);
if (expr.charAt(offset) == closeBrace) return findTheBrace(expr, offset - 1);
return findTheBrace(expr, findTheBrace(expr, offset - 1, ...braces) - 1, ...braces);
return findTheBrace(expr, offset - 1, ...braces);
} }
// Walk expr backwards from offset looking for the beginning of an // Walk expr backwards from offset looking for the beginning of an
@@ -114,11 +118,13 @@ function getExpressionOffset(expr, offset) {
while (offset >= 0) { while (offset >= 0) {
let currChar = expr.charAt(offset); let currChar = expr.charAt(offset);
if (isStopChar(currChar)) if (isStopChar(currChar)) {
return offset + 1; return offset + 1;
}
if (currChar.match(/[)\]]/)) if (currChar.match(/[)\]]/)) {
offset = findMatchingBrace(expr, offset); offset = findMatchingBrace(expr, offset);
}
--offset; --offset;
} }
@@ -135,9 +141,9 @@ function isValidPropertyName(w) {
// To get all properties (enumerable and not), we need to walk // To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves // the prototype chain ourselves
function getAllProps(obj) { function getAllProps(obj) {
if (obj === null || obj === undefined) if (obj === null || obj === undefined) {
return []; return [];
}
return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) ); return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
} }
@@ -183,27 +189,25 @@ function getCommonPrefix(words) {
return word; return word;
} }
// Returns true if there is reason to think that eval(str)
// will modify the global scope
function isUnsafeExpression(str) {
// Remove any blocks that are quoted or are in a regex // Remove any blocks that are quoted or are in a regex
function removeLiterals(str) { function removeLiterals(str) {
if (str.length == 0) if (str.length == 0) {
return ''; return '';
}
let currChar = str.charAt(str.length - 1); let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') { if (currChar == '"' || currChar == '\'') {
return removeLiterals( return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') { } else if (currChar == '/') {
return removeLiterals( return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
str.slice(0, findMatchingSlash(str, str.length - 1)));
} }
return removeLiterals(str.slice(0, str.length - 1)) + currChar; return removeLiterals(str.slice(0, str.length - 1)) + currChar;
} }
// Returns true if there is reason to think that eval(str)
// will modify the global scope
function isUnsafeExpression(str) {
// Check for any sort of assignment // Check for any sort of assignment
// The strategy used is dumb: remove any quotes // The strategy used is dumb: remove any quotes
// or regexs and comparison operators and see if there is an '=' character. // or regexs and comparison operators and see if there is an '=' character.

View File

@@ -74,9 +74,8 @@ function registerSessionWithGDM() {
let _loginManager = null; let _loginManager = null;
/** /**
* getLoginManager: * LoginManager:
* An abstraction over systemd/logind and ConsoleKit. * An abstraction over systemd/logind and ConsoleKit.
* @returns {object} - the LoginManager singleton
* *
*/ */
function getLoginManager() { function getLoginManager() {
@@ -111,14 +110,14 @@ var LoginManagerSystemd = class {
let sessionId = GLib.getenv('XDG_SESSION_ID'); let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) { if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.'); log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.');
let [session, objectPath] = this._userProxy.Display; let [session, objectPath_] = this._userProxy.Display;
if (session) { if (session) {
log(`Will monitor session ${session}`); log(`Will monitor session ${session}`);
sessionId = session; sessionId = session;
} else { } else {
log('Failed to find "Display" session; are we the greeter?'); log('Failed to find "Display" session; are we the greeter?');
for ([session, objectPath] of this._userProxy.Sessions) { for (let [session, objectPath] of this._userProxy.Sessions) {
let sessionProxy = new SystemdLoginSession(Gio.DBus.system, let sessionProxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1', 'org.freedesktop.login1',
objectPath); objectPath);
@@ -186,7 +185,7 @@ var LoginManagerSystemd = class {
try { try {
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result); let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0]; fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd })); callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) { } catch (e) {
logError(e, "Error getting systemd inhibitor"); logError(e, "Error getting systemd inhibitor");
callback(null); callback(null);

View File

@@ -7,7 +7,6 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager) jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir) jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir) jsconf.set('libexecdir', libexecdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file( config_js = configure_file(
input: 'config.js.in', input: 'config.js.in',

View File

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

View File

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

View File

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

View File

@@ -72,11 +72,12 @@ var SmartcardManager = class {
if ('IsInserted' in properties.deep_unpack()) { if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token); this._updateToken(token);
if (token.IsInserted) if (token.IsInserted) {
this.emit('smartcard-inserted', token); this.emit('smartcard-inserted', token);
else } else {
this.emit('smartcard-removed', token); this.emit('smartcard-removed', token);
} }
}
}); });
// Emit a smartcard-inserted at startup if it's already plugged in // Emit a smartcard-inserted at startup if it's already plugged in

View File

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

View File

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

View File

@@ -48,11 +48,11 @@ var WeatherClient = class {
return; return;
} }
this._permStore.LookupRemote('gnome', 'geolocation', (res, err) => { this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (err) if (error)
log(`Error looking up permission: ${err.message}`); log(`Error looking up permission: ${error.message}`);
let [perms, data] = err ? [{}, null] : res; let [perms, data] = error ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms]; let params = ['gnome', 'geolocation', false, data, perms];
this._onPermStoreChanged(this._permStore, '', params); this._onPermStoreChanged(this._permStore, '', params);
}); });
@@ -91,7 +91,7 @@ var WeatherClient = class {
this._onWeatherProxyReady.bind(this)); this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({ this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather', schema_id: 'org.gnome.shell.weather'
}); });
this._settings.connect('changed::automatic-location', this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this)); this._onAutomaticLocationChanged.bind(this));
@@ -170,9 +170,9 @@ var WeatherClient = class {
} }
_onInstalledChanged() { _onInstalledChanged() {
let hadApp = this._weatherApp != null; let hadApp = (this._weatherApp != null);
this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID); this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
let haveApp = this._weatherApp != null; let haveApp = (this._weatherApp != null);
if (hadApp !== haveApp) if (hadApp !== haveApp)
this.emit('changed'); this.emit('changed');
@@ -213,7 +213,7 @@ var WeatherClient = class {
this._weatherInfo.abort(); this._weatherInfo.abort();
this._weatherInfo.set_location(location); this._weatherInfo.set_location(location);
this._locationValid = location != null; this._locationValid = (location != null);
this._weatherInfo.set_enabled_providers(location ? this._providers : 0); this._weatherInfo.set_enabled_providers(location ? this._providers : 0);

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ const AccessIface = loadInterfaceXML('org.freedesktop.impl.portal.Access');
var DialogResponse = { var DialogResponse = {
OK: 0, OK: 0,
CANCEL: 1, CANCEL: 1,
CLOSED: 2, CLOSED: 2
}; };
var AccessDialog = GObject.registerClass( var AccessDialog = GObject.registerClass(
@@ -56,8 +56,8 @@ class AccessDialog extends ModalDialog.ModalDialog {
let check = new CheckBox.CheckBox(); let check = new CheckBox.CheckBox();
check.getLabelActor().text = name; check.getLabelActor().text = name;
check.checked = selected == "true"; check.actor.checked = selected == "true";
content.insertBeforeBody(check); content.insertBeforeBody(check.actor);
this._choices.set(id, check); this._choices.set(id, check);
} }
@@ -99,7 +99,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
let results = {}; let results = {};
if (response == DialogResponse.OK) { if (response == DialogResponse.OK) {
for (let [id, check] of this._choices) { for (let [id, check] of this._choices) {
let checked = check.checked ? 'true' : 'false'; let checked = check.actor.checked ? 'true' : 'false';
results[id] = new GLib.Variant('s', checked); results[id] = new GLib.Variant('s', checked);
} }
} }

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,8 +16,8 @@ var BarLevel = GObject.registerClass({
'overdrive-start': GObject.ParamSpec.double( 'overdrive-start': GObject.ParamSpec.double(
'overdrive-start', 'overdrive-start', 'overdrive-start', 'overdrive-start', 'overdrive-start', 'overdrive-start',
GObject.ParamFlags.READWRITE, GObject.ParamFlags.READWRITE,
1, 2, 1), 1, 2, 1)
}, }
}, class BarLevel extends St.DrawingArea { }, class BarLevel extends St.DrawingArea {
_init(params) { _init(params) {
this._maxValue = 1; this._maxValue = 1;
@@ -27,7 +27,7 @@ var BarLevel = GObject.registerClass({
let defaultParams = { let defaultParams = {
style_class: 'barlevel', style_class: 'barlevel',
accessible_role: Atk.Role.LEVEL_BAR, accessible_role: Atk.Role.LEVEL_BAR
}; };
super._init(Object.assign(defaultParams, params)); super._init(Object.assign(defaultParams, params));
this.connect('allocation-changed', (actor, box) => { this.connect('allocation-changed', (actor, box) => {
@@ -88,10 +88,9 @@ var BarLevel = GObject.registerClass({
if (this._overdriveStart == value) if (this._overdriveStart == value)
return; return;
if (value > this._maxValue) { if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` + throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`); `which is a number greater than the maximum allowed value ${this._maxValue}`);
}
this._overdriveStart = value; this._overdriveStart = value;
this.notify('overdrive-start'); this.notify('overdrive-start');

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({ var CloseDialog = GObject.registerClass({
Implements: [Meta.CloseDialog], Implements: [Meta.CloseDialog],
Properties: { Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog), 'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
}, },
}, class CloseDialog extends GObject.Object { }, class CloseDialog extends GObject.Object {
_init(window) { _init(window) {
@@ -73,7 +73,7 @@ var CloseDialog = GObject.registerClass({
default: true }); default: true });
this._dialog.addButton({ label: _('Wait'), this._dialog.addButton({ label: _('Wait'),
action: this._onWait.bind(this), action: this._onWait.bind(this),
key: Clutter.KEY_Escape }); key: Clutter.Escape });
global.focus_manager.add_group(this._dialog); global.focus_manager.add_group(this._dialog);
@@ -124,12 +124,11 @@ var CloseDialog = GObject.registerClass({
if (this._tracked === shouldTrack) if (this._tracked === shouldTrack)
return; return;
if (shouldTrack) { if (shouldTrack)
Main.layoutManager.trackChrome(this._dialog, Main.layoutManager.trackChrome(this._dialog,
{ affectsInputRegion: true }); { affectsInputRegion: true });
} else { else
Main.layoutManager.untrackChrome(this._dialog); Main.layoutManager.untrackChrome(this._dialog);
}
// The buttons are broken when they aren't added to the input region, // The buttons are broken when they aren't added to the input region,
// so disable them properly in that case // so disable them properly in that case
@@ -170,7 +169,7 @@ var CloseDialog = GObject.registerClass({
scale_y: 1, scale_y: 1,
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME, duration: DIALOG_TRANSITION_TIME,
onComplete: this._onFocusChanged.bind(this), onComplete: this._onFocusChanged.bind(this)
}); });
} }
@@ -193,11 +192,12 @@ var CloseDialog = GObject.registerClass({
this._dialog = null; this._dialog = null;
this._removeWindowEffect(); this._removeWindowEffect();
dialog.makeInactive();
dialog._dialog.ease({ dialog._dialog.ease({
scale_y: 0, scale_y: 0,
mode: Clutter.AnimationMode.LINEAR, mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME, duration: DIALOG_TRANSITION_TIME,
onComplete: () => dialog.destroy(), onComplete: () => dialog.destroy()
}); });
} }

View File

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

View File

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

View File

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

View File

@@ -4,13 +4,15 @@
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi; const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog; const Dialog = imports.ui.dialog;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog; const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
const VPN_UI_GROUP = 'VPN Plugin UI'; const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = GObject.registerClass( var NetworkSecretDialog = GObject.registerClass(
@@ -56,7 +58,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry', secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive, text: secret.value, can_focus: reactive,
reactive, reactive: reactive,
x_expand: true }); x_expand: true });
ShellEntry.addContextMenu(secret.entry, ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password }); { isPassword: secret.password });
@@ -106,7 +108,10 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
descriptionLabel.clutter_text.line_wrap = true; descriptionLabel.clutter_text.line_wrap = true;
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add_child(descriptionLabel); contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
} }
this._okButton = { this._okButton = {
@@ -169,7 +174,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
return true; return true;
} }
return value.length >= 8 && value.length <= 63; return (value.length >= 8 && value.length <= 63);
} }
_validateStaticWep(secret) { _validateStaticWep(secret) {
@@ -222,12 +227,11 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
validate: this._validateStaticWep, password: true }); validate: this._validateStaticWep, password: true });
break; break;
case 'ieee8021x': case 'ieee8021x':
if (wirelessSecuritySetting.auth_alg == 'leap') { // Cisco LEAP if (wirelessSecuritySetting.auth_alg == 'leap') // Cisco LEAP
secrets.push({ label: _("Password: "), key: 'leap-password', secrets.push({ label: _("Password: "), key: 'leap-password',
value: wirelessSecuritySetting.leap_password || '', password: true }); value: wirelessSecuritySetting.leap_password || '', password: true });
} else { // Dynamic (IEEE 802.1x) WEP else // Dynamic (IEEE 802.1x) WEP
this._get8021xSecrets(secrets); this._get8021xSecrets(secrets);
}
break; break;
case 'wpa-eap': case 'wpa-eap':
this._get8021xSecrets(secrets); this._get8021xSecrets(secrets);
@@ -242,18 +246,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
/* If hints were given we know exactly what we need to ask */ /* If hints were given we know exactly what we need to ask */
if (this._settingName == "802-1x" && this._hints.length) { if (this._settingName == "802-1x" && this._hints.length) {
if (this._hints.includes('identity')) { if (this._hints.includes('identity'))
secrets.push({ label: _("Username: "), key: 'identity', secrets.push({ label: _("Username: "), key: 'identity',
value: ieee8021xSetting.identity || '', password: false }); value: ieee8021xSetting.identity || '', password: false });
} if (this._hints.includes('password'))
if (this._hints.includes('password')) {
secrets.push({ label: _("Password: "), key: 'password', secrets.push({ label: _("Password: "), key: 'password',
value: ieee8021xSetting.password || '', password: true }); value: ieee8021xSetting.password || '', password: true });
} if (this._hints.includes('private-key-password'))
if (this._hints.includes('private-key-password')) {
secrets.push({ label: _("Private key password: "), key: 'private-key-password', secrets.push({ label: _("Private key password: "), key: 'private-key-password',
value: ieee8021xSetting.private_key_password || '', password: true }); value: ieee8021xSetting.private_key_password || '', password: true });
}
return; return;
} }
@@ -557,7 +558,7 @@ var VPNRequestHandler = class {
contentOverride.secrets.push({ contentOverride.secrets.push({
label: keyfile.get_string(groups[i], 'Label'), label: keyfile.get_string(groups[i], 'Label'),
key: groups[i], key: groups[i],
value, value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret'), password: keyfile.get_boolean(groups[i], 'IsSecret'),
}); });
} else { } else {
@@ -623,14 +624,6 @@ var NetworkAgent = class {
this._vpnRequests = { }; this._vpnRequests = { };
this._notifications = { }; this._notifications = { };
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => (this._vpnCacheBuilt = false));
} catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
}
this._native.connect('new-request', this._newRequest.bind(this)); this._native.connect('new-request', this._newRequest.bind(this));
this._native.connect('cancel-request', this._cancelRequest.bind(this)); this._native.connect('cancel-request', this._cancelRequest.bind(this));
@@ -735,7 +728,7 @@ var NetworkAgent = class {
}); });
Main.messageTray.add(source); Main.messageTray.add(source);
source.showNotification(notification); source.notify(notification);
} }
_newRequest(agent, requestId, connection, settingName, hints, flags) { _newRequest(agent, requestId, connection, settingName, hints, flags) {
@@ -770,13 +763,11 @@ var NetworkAgent = class {
} }
} }
_vpnRequest(requestId, connection, hints, flags) { async _vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn(); let vpnSetting = connection.get_setting_vpn();
let serviceType = vpnSetting.service_type; let serviceType = vpnSetting.service_type;
this._buildVPNServiceCache(); let binary = await this._findAuthBinary(serviceType);
let binary = this._vpnBinaries[serviceType];
if (!binary) { if (!binary) {
log('Invalid VPN service type (cannot find authentication binary)'); log('Invalid VPN service type (cannot find authentication binary)');
@@ -792,36 +783,30 @@ var NetworkAgent = class {
this._vpnRequests[requestId] = vpnRequest; this._vpnRequests[requestId] = vpnRequest;
} }
_buildVPNServiceCache() { async _findAuthBinary(serviceType) {
if (this._vpnCacheBuilt) let plugin;
return;
this._vpnCacheBuilt = true; try {
this._vpnBinaries = { }; plugin = await this._native.search_vpn_plugin(serviceType);
} catch (e) {
NM.VpnPluginInfo.list_load().forEach(plugin => { logError(e);
let service = plugin.get_service(); return null;
let fileName = plugin.get_auth_dialog();
let supportsHints = plugin.supports_hints();
let externalUIMode = false;
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
if (prop) {
prop = prop.trim().toLowerCase();
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
} }
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) { const fileName = plugin.get_auth_dialog();
let binary = { fileName, externalUIMode, supportsHints }; if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
this._vpnBinaries[service] = binary;
plugin.get_aliases().forEach(alias => {
this._vpnBinaries[alias] = binary;
});
} else {
log('VPN plugin at %s is not executable'.format(fileName)); log('VPN plugin at %s is not executable'.format(fileName));
return null;
} }
});
const prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
const trimmedProp = prop ? prop.trim().toLowerCase() : '';
return {
fileName,
supportsHints: plugin.supports_hints(),
externalUIMode: ['true', 'yes', 'on', '1'].includes(trimmedProp),
};
} }
}; };
var Component = NetworkAgent; var Component = NetworkAgent;

View File

@@ -20,10 +20,8 @@ var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16; var WORK_SPINNER_ICON_SIZE = 16;
const DELAYED_RESET_TIMEOUT = 200;
var AuthenticationDialog = GObject.registerClass({ var AuthenticationDialog = GObject.registerClass({
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }, Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }
}, class AuthenticationDialog extends ModalDialog.ModalDialog { }, class AuthenticationDialog extends ModalDialog.ModalDialog {
_init(actionId, body, cookie, userNames) { _init(actionId, body, cookie, userNames) {
super._init({ styleClass: 'prompt-dialog' }); super._init({ styleClass: 'prompt-dialog' });
@@ -31,6 +29,7 @@ var AuthenticationDialog = GObject.registerClass({
this.actionId = actionId; this.actionId = actionId;
this.message = body; this.message = body;
this.userNames = userNames; this.userNames = userNames;
this._wasDismissed = false;
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => { this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
this.visible = !Main.sessionMode.isLocked; this.visible = !Main.sessionMode.isLocked;
@@ -68,7 +67,8 @@ var AuthenticationDialog = GObject.registerClass({
iconSize: DIALOG_ICON_SIZE, iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon', styleClass: 'polkit-dialog-user-icon',
}); });
userBox.add_child(this._userAvatar); this._userAvatar.actor.hide();
userBox.add_child(this._userAvatar.actor);
this._userLabel = new St.Label({ this._userLabel = new St.Label({
style_class: userName === 'root' style_class: userName === 'root'
@@ -85,35 +85,27 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' }); this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
content.messageBox.add(this._passwordBox); content.messageBox.add(this._passwordBox);
this._passwordLabel = new St.Label({ this._passwordLabel = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
style_class: 'prompt-dialog-password-label', this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
y_align: Clutter.ActorAlign.CENTER, this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
});
this._passwordBox.add_child(this._passwordLabel);
this._passwordEntry = new St.Entry({
style_class: 'prompt-dialog-password-entry',
text: "", text: "",
can_focus: true, can_focus: true });
x_expand: true,
});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true }); ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this)); this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordEntry.bind_property('reactive', this._passwordBox.add(this._passwordEntry,
this._passwordEntry.clutter_text, 'editable', { expand: true });
GObject.BindingFlags.SYNC_CREATE);
this._passwordBox.add_child(this._passwordEntry);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, { this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true, animate: true,
}); });
this._passwordBox.add(this._workSpinner); this._passwordBox.add(this._workSpinner.actor);
this._passwordBox.hide(); this._passwordBox.hide();
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' }); this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; this._errorMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._errorMessageLabel.clutter_text.line_wrap = true; this._errorMessageLabel.clutter_text.line_wrap = true;
content.messageBox.add_child(this._errorMessageLabel); content.messageBox.add(this._errorMessageLabel, { x_fill: false, x_align: St.Align.START });
this._errorMessageLabel.hide(); this._errorMessageLabel.hide();
this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' }); this._infoMessageLabel = new St.Label({ style_class: 'prompt-dialog-info-label' });
@@ -136,17 +128,10 @@ var AuthenticationDialog = GObject.registerClass({
this._cancelButton = this.addButton({ label: _("Cancel"), this._cancelButton = this.addButton({ label: _("Cancel"),
action: this.cancel.bind(this), action: this.cancel.bind(this),
key: Clutter.KEY_Escape }); key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"), this._okButton = this.addButton({ label: _("Authenticate"),
action: this._onAuthenticateButtonPressed.bind(this), action: this._onAuthenticateButtonPressed.bind(this),
reactive: false }); default: true });
this._okButton.bind_property('reactive',
this._okButton, 'can-focus',
GObject.BindingFlags.SYNC_CREATE);
this._passwordEntry.clutter_text.connect('text-changed', text => {
this._okButton.reactive = text.get_text().length > 0;
});
this._doneEmitted = false; this._doneEmitted = false;
@@ -170,7 +155,7 @@ var AuthenticationDialog = GObject.registerClass({
} }
_initiateSession() { _initiateSession() {
this._destroySession(DELAYED_RESET_TIMEOUT); this._destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth, this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie }); cookie: this._cookie });
@@ -210,15 +195,18 @@ var AuthenticationDialog = GObject.registerClass({
} }
} }
_updateSensitivity(sensitive) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
this._okButton.can_focus = sensitive;
this._okButton.reactive = sensitive;
this._setWorking(!sensitive);
}
_onEntryActivate() { _onEntryActivate() {
let response = this._passwordEntry.get_text(); let response = this._passwordEntry.get_text();
if (response.length === 0) this._updateSensitivity(false);
return;
this._passwordEntry.reactive = false;
this._okButton.reactive = false;
this._setWorking(true);
this._session.response(response); this._session.response(response);
// When the user responds, dismiss already shown info and // When the user responds, dismiss already shown info and
// error texts (if any) // error texts (if any)
@@ -250,7 +238,7 @@ var AuthenticationDialog = GObject.registerClass({
* error providing authentication-method specific information), * error providing authentication-method specific information),
* show "Sorry, that didn't work. Please try again." * show "Sorry, that didn't work. Please try again."
*/ */
if (!this._errorMessageLabel.visible) { if (!this._errorMessageLabel.visible && !this._wasDismissed) {
/* Translators: "that didn't work" refers to the fact that the /* Translators: "that didn't work" refers to the fact that the
* requested authentication was not gained; this can happen * requested authentication was not gained; this can happen
* because of an authentication error (like invalid password), * because of an authentication error (like invalid password),
@@ -267,11 +255,6 @@ var AuthenticationDialog = GObject.registerClass({
} }
_onSessionRequest(session, request, echoOn) { _onSessionRequest(session, request, echoOn) {
if (this._sessionRequestTimeoutId) {
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
}
// Cheap localization trick // Cheap localization trick
if (request == 'Password:' || request == 'Password: ') if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:")); this._passwordLabel.set_text(_("Password:"));
@@ -285,9 +268,7 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.show(); this._passwordBox.show();
this._passwordEntry.set_text(''); this._passwordEntry.set_text('');
this._passwordEntry.reactive = true; this._updateSensitivity(true);
this._okButton.reactive = false;
this._setWorking(false);
this._ensureOpen(); this._ensureOpen();
this._passwordEntry.grab_key_focus(); this._passwordEntry.grab_key_focus();
@@ -311,40 +292,18 @@ var AuthenticationDialog = GObject.registerClass({
this._ensureOpen(); this._ensureOpen();
} }
_destroySession(delay = 0) { _destroySession() {
if (this._session) { if (this._session) {
if (!this._completed)
this._session.cancel();
this._completed = false;
this._session.disconnect(this._sessionCompletedId); this._session.disconnect(this._sessionCompletedId);
this._session.disconnect(this._sessionRequestId); this._session.disconnect(this._sessionRequestId);
this._session.disconnect(this._sessionShowErrorId); this._session.disconnect(this._sessionShowErrorId);
this._session.disconnect(this._sessionShowInfoId); this._session.disconnect(this._sessionShowInfoId);
if (!this._completed)
this._session.cancel();
this._completed = false;
this._session = null; this._session = null;
} }
if (this._sessionRequestTimeoutId) {
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
}
let resetDialog = () => {
if (this.state != ModalDialog.State.OPENED)
return;
this._passwordBox.hide();
this._cancelButton.grab_key_focus();
this._okButton.reactive = false;
};
if (delay) {
this._sessionRequestTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, delay, resetDialog);
GLib.Source.set_name_by_id(this._sessionRequestTimeoutId, '[gnome-shell] this._sessionRequestTimeoutId');
} else {
resetDialog();
}
} }
_onUserChanged() { _onUserChanged() {
@@ -354,10 +313,12 @@ var AuthenticationDialog = GObject.registerClass({
let userName = this._user.get_user_name(); let userName = this._user.get_user_name();
let realName = this._user.get_real_name(); let realName = this._user.get_real_name();
if (userName !== 'root') if (userName !== 'root') {
this._userLabel.set_text(realName); this._userLabel.set_text(realName);
this._userAvatar.update(); this._userAvatar.update();
this._userAvatar.actor.show();
}
if (this._user.get_password_mode() === AccountsService.UserPasswordMode.NONE) { if (this._user.get_password_mode() === AccountsService.UserPasswordMode.NONE) {
if (this._mode === DialogMode.CONFIRM) if (this._mode === DialogMode.CONFIRM)
@@ -383,6 +344,7 @@ var AuthenticationDialog = GObject.registerClass({
} }
cancel() { cancel() {
this._wasDismissed = true;
this.close(global.get_current_time()); this.close(global.get_current_time());
this._emitDone(true); this._emitDone(true);
} }
@@ -390,10 +352,7 @@ var AuthenticationDialog = GObject.registerClass({
_onDialogClosed() { _onDialogClosed() {
if (this._sessionUpdatedId) if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId); Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
if (this._sessionRequestTimeoutId)
GLib.source_remove(this._sessionRequestTimeoutId);
this._sessionRequestTimeoutId = 0;
if (this._user) { if (this._user) {
this._user.disconnect(this._userLoadedId); this._user.disconnect(this._userLoadedId);
@@ -405,20 +364,19 @@ var AuthenticationDialog = GObject.registerClass({
} }
}); });
var AuthenticationAgent = GObject.registerClass( var AuthenticationAgent = class {
class AuthenticationAgent extends Shell.PolkitAuthenticationAgent { constructor() {
_init() {
super._init();
this._currentDialog = null; this._currentDialog = null;
this.connect('initiate', this._onInitiate.bind(this)); this._handle = null;
this.connect('cancel', this._onCancel.bind(this)); this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', this._onInitiate.bind(this));
this._native.connect('cancel', this._onCancel.bind(this));
this._sessionUpdatedId = 0; this._sessionUpdatedId = 0;
} }
enable() { enable() {
try { try {
this.register(); this._native.register();
} catch (e) { } catch (e) {
log('Failed to register AuthenticationAgent'); log('Failed to register AuthenticationAgent');
} }
@@ -426,7 +384,7 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
disable() { disable() {
try { try {
this.unregister(); this._native.unregister();
} catch (e) { } catch (e) {
log('Failed to unregister AuthenticationAgent'); log('Failed to unregister AuthenticationAgent');
} }
@@ -464,8 +422,8 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent {
Main.sessionMode.disconnect(this._sessionUpdatedId); Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0; this._sessionUpdatedId = 0;
this.complete(dismissed); this._native.complete(dismissed);
} }
}); };
var Component = AuthenticationAgent; var Component = AuthenticationAgent;

View File

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

View File

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

View File

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

View File

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

View File

@@ -36,21 +36,31 @@ class Dialog extends St.Widget {
this._dialog.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH; this._dialog.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
this._dialog.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS); this._dialog.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this.contentLayout = new St.BoxLayout({ this.contentLayout = new St.BoxLayout({ vertical: true,
vertical: true, style_class: "modal-dialog-content-box" });
style_class: 'modal-dialog-content-box', this._dialog.add(this.contentLayout,
y_expand: true, { expand: true,
}); x_fill: true,
this._dialog.add_child(this.contentLayout); y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) }); this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
this._dialog.add_child(this.buttonLayout); this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE,
y_align: St.Align.START });
} }
_onDestroy() { makeInactive() {
if (this._eventId != 0) if (this._eventId != 0)
this._parentActor.disconnect(this._eventId); this._parentActor.disconnect(this._eventId);
this._eventId = 0; this._eventId = 0;
this.buttonLayout.get_children().forEach(c => c.set_reactive(false));
}
_onDestroy() {
this.makeInactive();
} }
_modalEventHandler(actor, event) { _modalEventHandler(actor, event) {
@@ -117,7 +127,7 @@ class Dialog extends St.Widget {
can_focus: true, can_focus: true,
x_expand: true, x_expand: true,
y_expand: true, y_expand: true,
label }); label: label });
button.connect('clicked', action); button.connect('clicked', action);
buttonInfo['button'] = button; buttonInfo['button'] = button;
@@ -159,8 +169,8 @@ var MessageDialogContent = GObject.registerClass({
'body': GObject.ParamSpec.string('body', 'body', 'body', 'body': GObject.ParamSpec.string('body', 'body', 'body',
GObject.ParamFlags.READWRITE | GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT, GObject.ParamFlags.CONSTRUCT,
null), null)
}, }
}, class MessageDialogContent extends St.BoxLayout { }, class MessageDialogContent extends St.BoxLayout {
_init(params) { _init(params) {
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START }); this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
@@ -211,7 +221,7 @@ var MessageDialogContent = GObject.registerClass({
set icon(icon) { set icon(icon) {
this._icon.set({ this._icon.set({
gicon: icon, gicon: icon,
visible: icon != null, visible: icon != null
}); });
this.notify('icon'); this.notify('icon');
} }
@@ -231,7 +241,7 @@ var MessageDialogContent = GObject.registerClass({
_setLabel(label, prop, value) { _setLabel(label, prop, value) {
label.set({ label.set({
text: value || '', text: value || '',
visible: value != null, visible: value != null
}); });
this.notify(prop); this.notify(prop);
} }

View File

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

View File

@@ -37,10 +37,10 @@ var EdgeDragAction = GObject.registerClass({
let [x, y] = this.get_press_coords(0); let [x, y] = this.get_press_coords(0);
let monitorRect = this._getMonitorRect(x, y); let monitorRect = this._getMonitorRect(x, y);
return (this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) || return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) || (this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) || (this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD); (this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
} }
vfunc_gesture_progress(_actor) { vfunc_gesture_progress(_actor) {

View File

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

View File

@@ -10,7 +10,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12'; imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2'; imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi; const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext; const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have // We can't import shell JS modules yet, because they may have
@@ -40,7 +40,7 @@ function _patchContainerClass(containerClass) {
} }
function _patchLayoutClass(layoutClass, styleProps) { function _patchLayoutClass(layoutClass, styleProps) {
if (styleProps) { if (styleProps)
layoutClass.prototype.hookup_style = function(container) { layoutClass.prototype.hookup_style = function(container) {
container.connect('style-changed', () => { container.connect('style-changed', () => {
let node = container.get_theme_node(); let node = container.get_theme_node();
@@ -51,7 +51,11 @@ function _patchLayoutClass(layoutClass, styleProps) {
} }
}); });
}; };
} layoutClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor.get_parent(), actor);
for (let prop in props)
meta[prop] = props[prop];
};
} }
function _makeEaseCallback(params, cleanup) { function _makeEaseCallback(params, cleanup) {
@@ -101,16 +105,6 @@ function _easeActor(actor, params) {
actor.set_easing_delay(params.delay); actor.set_easing_delay(params.delay);
delete params.delay; delete params.delay;
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
if (params.mode != undefined) if (params.mode != undefined)
actor.set_easing_mode(params.mode); actor.set_easing_mode(params.mode);
delete params.mode; delete params.mode;
@@ -133,13 +127,11 @@ function _easeActor(actor, params) {
else else
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
if (transition) { if (transition)
transition.set({ repeatCount, autoReverse });
transition.connect('stopped', (t, finished) => callback(finished)); transition.connect('stopped', (t, finished) => callback(finished));
} else { else
callback(true); callback(true);
} }
}
function _easeActorProperty(actor, propName, target, params) { function _easeActorProperty(actor, propName, target, params) {
// Avoid pointless difference with ease() // Avoid pointless difference with ease()
@@ -151,16 +143,6 @@ function _easeActorProperty(actor, propName, target, params) {
params.duration = adjustAnimationTime(params.duration); params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0); let duration = Math.floor(params.duration || 0);
let repeatCount = 0;
if (params.repeatCount != undefined)
repeatCount = params.repeatCount;
delete params.repeatCount;
let autoReverse = false;
if (params.autoReverse != undefined)
autoReverse = params.autoReverse;
delete params.autoReverse;
// Copy Clutter's behavior for implicit animations, see // Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition() // should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped) if (actor instanceof Clutter.Actor && !actor.mapped)
@@ -186,9 +168,7 @@ function _easeActorProperty(actor, propName, target, params) {
let transition = new Clutter.PropertyTransition(Object.assign({ let transition = new Clutter.PropertyTransition(Object.assign({
property_name: propName, property_name: propName,
interval: new Clutter.Interval({ value_type: pspec.value_type }), interval: new Clutter.Interval({ value_type: pspec.value_type }),
remove_on_complete: true, remove_on_complete: true
repeat_count: repeatCount,
auto_reverse: autoReverse,
}, params)); }, params));
actor.add_transition(propName, transition); actor.add_transition(propName, transition);
@@ -229,11 +209,11 @@ function init() {
window.ngettext = Gettext.ngettext; window.ngettext = Gettext.ngettext;
window.N_ = s => s; window.N_ = s => s;
GObject.gtypeNameBasedOnJSPath = true;
// Miscellaneous monkeypatching // Miscellaneous monkeypatching
_patchContainerClass(St.BoxLayout); _patchContainerClass(St.BoxLayout);
_patchLayoutClass(Clutter.TableLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows', _patchLayoutClass(Clutter.GridLayout, { row_spacing: 'spacing-rows',
column_spacing: 'spacing-columns' }); column_spacing: 'spacing-columns' });
_patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' }); _patchLayoutClass(Clutter.BoxLayout, { spacing: 'spacing' });
@@ -269,7 +249,7 @@ function init() {
let { stack } = new Error(); let { stack } = new Error();
log(`Usage of object.actor is deprecated for ${klass}\n${stack}`); log(`Usage of object.actor is deprecated for ${klass}\n${stack}`);
return this; return this;
}, }
}); });
St.set_slow_down_factor = function(factor) { St.set_slow_down_factor = function(factor) {
@@ -293,8 +273,7 @@ function init() {
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
Date.prototype.toLocaleFormat = function(format) { Date.prototype.toLocaleFormat = function(format) {
let dt = GLib.DateTime.new_from_unix_local(this.getTime() / 1000); return Shell.util_format_date(format, this.getTime());
return dt ? dt.format(format) : '';
}; };
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR'); let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');

View File

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

View File

@@ -41,7 +41,7 @@ var ExtensionManager = class {
} }
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => { GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
disableFile.delete(null); FileUtils.deleteGFile(disableFile);
return GLib.SOURCE_REMOVE; return GLib.SOURCE_REMOVE;
}); });
@@ -77,11 +77,11 @@ var ExtensionManager = class {
let orderReversed = order.slice().reverse(); let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) { for (let i = 0; i < orderReversed.length; i++) {
let otherUuid = orderReversed[i]; let uuid = orderReversed[i];
try { try {
this.lookup(otherUuid).stateObj.disable(); this.lookup(uuid).stateObj.disable();
} catch (e) { } catch (e) {
this.logExtensionError(otherUuid, e); this.logExtensionError(uuid, e);
} }
} }
@@ -98,11 +98,11 @@ var ExtensionManager = class {
} }
for (let i = 0; i < order.length; i++) { for (let i = 0; i < order.length; i++) {
let otherUuid = order[i]; let uuid = order[i];
try { try {
this.lookup(otherUuid).stateObj.enable(); this.lookup(uuid).stateObj.enable();
} catch (e) { } catch (e) {
this.logExtensionError(otherUuid, e); this.logExtensionError(uuid, e);
} }
} }
@@ -217,8 +217,9 @@ var ExtensionManager = class {
createExtensionObject(uuid, dir, type) { createExtensionObject(uuid, dir, type) {
let metadataFile = dir.get_child('metadata.json'); let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json'); throw new Error('Missing metadata.json');
}
let metadataContents, success_; let metadataContents, success_;
try { try {
@@ -238,12 +239,14 @@ var ExtensionManager = class {
let requiredProperties = ['uuid', 'name', 'description', 'shell-version']; let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) { for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i]; let prop = requiredProperties[i];
if (!meta[prop]) if (!meta[prop]) {
throw new Error(`missing "${prop}" property in metadata.json`); throw new Error(`missing "${prop}" property in metadata.json`);
} }
}
if (uuid != meta.uuid) if (uuid != meta.uuid) {
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`); throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
}
let extension = { let extension = {
metadata: meta, metadata: meta,
@@ -253,7 +256,7 @@ var ExtensionManager = class {
path: dir.get_path(), path: dir.get_path(),
error: '', error: '',
hasPrefs: dir.get_child('prefs.js').query_exists(null), hasPrefs: dir.get_child('prefs.js').query_exists(null),
canChange: false, canChange: false
}; };
this._extensions.set(uuid, extension); this._extensions.set(uuid, extension);

View File

@@ -195,7 +195,7 @@ var GrabHelper = class GrabHelper {
} }
_takeModalGrab() { _takeModalGrab() {
let firstGrab = this._modalCount == 0; let firstGrab = (this._modalCount == 0);
if (firstGrab) { if (firstGrab) {
if (!Main.pushModal(this._owner, this._modalParams)) if (!Main.pushModal(this._owner, this._modalParams))
return false; return false;

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -17,7 +17,7 @@ var State = {
CLOSED: 1, CLOSED: 1,
OPENING: 2, OPENING: 2,
CLOSING: 3, CLOSING: 3,
FADED_OUT: 4, FADED_OUT: 4
}; };
var ModalDialog = GObject.registerClass({ var ModalDialog = GObject.registerClass({
@@ -26,9 +26,9 @@ var ModalDialog = GObject.registerClass({
GObject.ParamFlags.READABLE, GObject.ParamFlags.READABLE,
Math.min(...Object.values(State)), Math.min(...Object.values(State)),
Math.max(...Object.values(State)), Math.max(...Object.values(State)),
State.CLOSED), State.CLOSED)
}, },
Signals: { 'opened': {}, 'closed': {} }, Signals: { 'opened': {}, 'closed': {} }
}, class ModalDialog extends St.Widget { }, class ModalDialog extends St.Widget {
_init(params) { _init(params) {
super._init({ visible: false, super._init({ visible: false,
@@ -57,12 +57,9 @@ var ModalDialog = GObject.registerClass({
coordinate: Clutter.BindCoordinate.ALL }); coordinate: Clutter.BindCoordinate.ALL });
this.add_constraint(constraint); this.add_constraint(constraint);
this.backgroundStack = new St.Widget({ this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
layout_manager: new Clutter.BinLayout(), this._backgroundBin = new St.Bin({ child: this.backgroundStack,
x_expand: true, x_fill: true, y_fill: true });
y_expand: true,
});
this._backgroundBin = new St.Bin({ child: this.backgroundStack });
this._monitorConstraint = new Layout.MonitorConstraint(); this._monitorConstraint = new Layout.MonitorConstraint();
this._backgroundBin.add_constraint(this._monitorConstraint); this._backgroundBin.add_constraint(this._monitorConstraint);
this.add_actor(this._backgroundBin); this.add_actor(this._backgroundBin);
@@ -124,7 +121,7 @@ var ModalDialog = GObject.registerClass({
this.dialogLayout.opacity = 255; this.dialogLayout.opacity = 255;
if (this._lightbox) if (this._lightbox)
this._lightbox.lightOn(); this._lightbox.show();
this.opacity = 0; this.opacity = 0;
this.show(); this.show();
this.ease({ this.ease({
@@ -134,7 +131,7 @@ var ModalDialog = GObject.registerClass({
onComplete: () => { onComplete: () => {
this._setState(State.OPENED); this._setState(State.OPENED);
this.emit('opened'); this.emit('opened');
}, }
}); });
} }
@@ -183,7 +180,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0, opacity: 0,
duration: OPEN_AND_CLOSE_TIME, duration: OPEN_AND_CLOSE_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._closeComplete(), onComplete: () => this._closeComplete()
}); });
} else { } else {
this._closeComplete(); this._closeComplete();
@@ -206,7 +203,7 @@ var ModalDialog = GObject.registerClass({
this._hasModal = false; this._hasModal = false;
if (!this._shellReactive) if (!this._shellReactive)
this.backgroundStack.set_child_above_sibling(this._eventBlocker, null); this._eventBlocker.raise_top();
} }
pushModal(timestamp) { pushModal(timestamp) {
@@ -231,7 +228,7 @@ var ModalDialog = GObject.registerClass({
} }
if (!this._shellReactive) if (!this._shellReactive)
this.backgroundStack.set_child_below_sibling(this._eventBlocker, null); this._eventBlocker.lower_bottom();
return true; return true;
} }
@@ -258,7 +255,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0, opacity: 0,
duration: FADE_OUT_DIALOG_TIME, duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, 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 */ /* exported MediaSection */
const { Gio, GObject, Shell, St } = imports.gi; const { Gio, Shell, St } = imports.gi;
const Signals = imports.signals; const Signals = imports.signals;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
@@ -19,10 +19,9 @@ const MprisPlayerProxy = Gio.DBusProxy.makeProxyWrapper(MprisPlayerIface);
const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.'; const MPRIS_PLAYER_PREFIX = 'org.mpris.MediaPlayer2.';
var MediaMessage = GObject.registerClass( var MediaMessage = class MediaMessage extends MessageList.Message {
class MediaMessage extends MessageList.Message { constructor(player) {
_init(player) { super('', '');
super._init('', '');
this._player = player; this._player = player;
@@ -44,20 +43,12 @@ class MediaMessage extends MessageList.Message {
this._player.next(); this._player.next();
}); });
this._updateHandlerId =
this._player.connect('changed', this._update.bind(this)); this._player.connect('changed', this._update.bind(this));
this._closedHandlerId =
this._player.connect('closed', this.close.bind(this)); this._player.connect('closed', this.close.bind(this));
this._update(); this._update();
} }
_onDestroy() { _onClicked() {
super._onDestroy();
this._player.disconnect(this._updateHandlerId);
this._player.disconnect(this._closedHandlerId);
}
vfunc_clicked() {
this._player.raise(); this._player.raise();
Main.panel.closeCalendar(); Main.panel.closeCalendar();
} }
@@ -72,7 +63,7 @@ class MediaMessage extends MessageList.Message {
if (this._player.trackCoverUrl) { if (this._player.trackCoverUrl) {
let file = Gio.File.new_for_uri(this._player.trackCoverUrl); let file = Gio.File.new_for_uri(this._player.trackCoverUrl);
this._icon.gicon = new Gio.FileIcon({ file }); this._icon.gicon = new Gio.FileIcon({ file: file });
this._icon.remove_style_class_name('fallback'); this._icon.remove_style_class_name('fallback');
} else { } else {
this._icon.icon_name = 'audio-x-generic-symbolic'; this._icon.icon_name = 'audio-x-generic-symbolic';
@@ -88,7 +79,7 @@ class MediaMessage extends MessageList.Message {
this._updateNavButton(this._prevButton, this._player.canGoPrevious); this._updateNavButton(this._prevButton, this._player.canGoPrevious);
this._updateNavButton(this._nextButton, this._player.canGoNext); this._updateNavButton(this._nextButton, this._player.canGoNext);
} }
}); };
var MprisPlayer = class MprisPlayer { var MprisPlayer = class MprisPlayer {
constructor(busName) { constructor(busName) {
@@ -103,7 +94,6 @@ var MprisPlayer = class MprisPlayer {
this._trackArtists = []; this._trackArtists = [];
this._trackTitle = ''; this._trackTitle = '';
this._trackCoverUrl = ''; this._trackCoverUrl = '';
this._busName = busName;
} }
get status() { get status() {
@@ -186,39 +176,9 @@ var MprisPlayer = class MprisPlayer {
for (let prop in this._playerProxy.Metadata) for (let prop in this._playerProxy.Metadata)
metadata[prop] = this._playerProxy.Metadata[prop].deep_unpack(); metadata[prop] = this._playerProxy.Metadata[prop].deep_unpack();
// Validate according to the spec; some clients send buggy metadata: this._trackArtists = metadata['xesam:artist'] || [_("Unknown artist")];
// https://www.freedesktop.org/wiki/Specifications/mpris-spec/metadata this._trackTitle = metadata['xesam:title'] || _("Unknown title");
this._trackArtists = metadata['xesam:artist']; this._trackCoverUrl = metadata['mpris:artUrl'] || '';
if (!Array.isArray(this._trackArtists) ||
!this._trackArtists.every(artist => typeof artist === 'string')) {
if (typeof this._trackArtists !== 'undefined') {
log(`Received faulty track artist metadata from ${
this._busName}; expected an array of strings, got ${
this._trackArtists} (${typeof this._trackArtists})`);
}
this._trackArtists = [_("Unknown artist")];
}
this._trackTitle = metadata['xesam:title'];
if (typeof this._trackTitle !== 'string') {
if (typeof this._trackTitle !== 'undefined') {
log(`Received faulty track title metadata from ${
this._busName}; expected a string, got ${
this._trackTitle} (${typeof this._trackTitle})`);
}
this._trackTitle = _("Unknown title");
}
this._trackCoverUrl = metadata['mpris:artUrl'];
if (typeof this._trackCoverUrl !== 'string') {
if (typeof this._trackCoverUrl !== 'undefined') {
log(`Received faulty track cover art metadata from ${
this._busName}; expected a string, got ${
this._trackCoverUrl} (${typeof this._trackCoverUrl})`);
}
this._trackCoverUrl = '';
}
this.emit('changed'); this.emit('changed');
let visible = this._playerProxy.CanPlay; let visible = this._playerProxy.CanPlay;
@@ -228,16 +188,15 @@ var MprisPlayer = class MprisPlayer {
if (visible) if (visible)
this.emit('show'); this.emit('show');
else else
this.emit('hide'); this._close();
} }
} }
}; };
Signals.addSignalMethods(MprisPlayer.prototype); Signals.addSignalMethods(MprisPlayer.prototype);
var MediaSection = GObject.registerClass( var MediaSection = class MediaSection extends MessageList.MessageListSection {
class MediaSection extends MessageList.MessageListSection { constructor() {
_init() { super();
super._init();
this._players = new Map(); this._players = new Map();
@@ -256,20 +215,15 @@ class MediaSection extends MessageList.MessageListSection {
return; return;
let player = new MprisPlayer(busName); let player = new MprisPlayer(busName);
let message = null;
player.connect('closed', player.connect('closed',
() => { () => {
this._players.delete(busName); this._players.delete(busName);
}); });
player.connect('show', () => { player.connect('show',
message = new MediaMessage(player); () => {
let message = new MediaMessage(player);
this.addMessage(message, true); this.addMessage(message, true);
}); });
player.connect('hide', () => {
this.removeMessage(message, true);
message = null;
});
this._players.set(busName, player); this._players.set(busName, player);
} }
@@ -293,4 +247,4 @@ class MediaSection extends MessageList.MessageListSection {
if (newOwner && !oldOwner) if (newOwner && !oldOwner)
this._addPlayer(name); this._addPlayer(name);
} }
}); };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { AccountsService, Clutter, Gio, GLib, const { AccountsService, Clutter, Cogl, Gio, GLib,
GnomeDesktop, GObject, Graphene, Meta, Shell, St } = imports.gi; GnomeDesktop, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo; const Cairo = imports.cairo;
const Signals = imports.signals; const Signals = imports.signals;
@@ -48,10 +48,10 @@ var STANDARD_FADE_TIME = 10000;
var MANUAL_FADE_TIME = 300; var MANUAL_FADE_TIME = 300;
var CURTAIN_SLIDE_TIME = 300; var CURTAIN_SLIDE_TIME = 300;
var Clock = GObject.registerClass( var Clock = class {
class ScreenShieldClock extends St.BoxLayout { constructor() {
_init() { this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock',
super._init({ style_class: 'screen-shield-clock', vertical: true }); vertical: true });
this._time = new St.Label({ this._time = new St.Label({
style_class: 'screen-shield-clock-time', style_class: 'screen-shield-clock-time',
@@ -62,15 +62,13 @@ class ScreenShieldClock extends St.BoxLayout {
x_align: Clutter.ActorAlign.CENTER, x_align: Clutter.ActorAlign.CENTER,
}); });
this.add_child(this._time); this.actor.add_child(this._time);
this.add_child(this._date); this.actor.add_child(this._date);
this._wallClock = new GnomeDesktop.WallClock({ time_only: true }); this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
this._wallClock.connect('notify::clock', this._updateClock.bind(this)); this._wallClock.connect('notify::clock', this._updateClock.bind(this));
this._updateClock(); this._updateClock();
this.connect('destroy', this._onDestroy.bind(this));
} }
_updateClock() { _updateClock() {
@@ -83,27 +81,25 @@ class ScreenShieldClock extends St.BoxLayout {
this._date.text = date.toLocaleFormat(dateFormat); this._date.text = date.toLocaleFormat(dateFormat);
} }
_onDestroy() { destroy() {
this.actor.destroy();
this._wallClock.run_dispose(); this._wallClock.run_dispose();
} }
}); };
var NotificationsBox = GObject.registerClass({ var NotificationsBox = class {
Signals: { 'wake-up-screen': {} }, constructor() {
}, class NotificationsBox extends St.BoxLayout { this.actor = new St.BoxLayout({ vertical: true,
_init() {
super._init({
vertical: true,
name: 'screenShieldNotifications', name: 'screenShieldNotifications',
style_class: 'screen-shield-notifications-container', style_class: 'screen-shield-notifications-container' });
});
this._scrollView = new St.ScrollView({ hscrollbar_policy: St.PolicyType.NEVER }); this._scrollView = new St.ScrollView({ x_fill: false, x_align: St.Align.START,
hscrollbar_policy: St.PolicyType.NEVER });
this._notificationBox = new St.BoxLayout({ vertical: true, this._notificationBox = new St.BoxLayout({ vertical: true,
style_class: 'screen-shield-notifications-container' }); style_class: 'screen-shield-notifications-container' });
this._scrollView.add_actor(this._notificationBox); this._scrollView.add_actor(this._notificationBox);
this.add_child(this._scrollView); this.actor.add_child(this._scrollView);
this._sources = new Map(); this._sources = new Map();
Main.messageTray.getSources().forEach(source => { Main.messageTray.getSources().forEach(source => {
@@ -112,26 +108,27 @@ var NotificationsBox = GObject.registerClass({
this._updateVisibility(); this._updateVisibility();
this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this)); this._sourceAddedId = Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
} }
_onDestroy() { destroy() {
if (this._sourceAddedId) { if (this._sourceAddedId) {
Main.messageTray.disconnect(this._sourceAddedId); Main.messageTray.disconnect(this._sourceAddedId);
this._sourceAddedId = 0; this._sourceAddedId = 0;
} }
let items = this._sources.entries(); let items = this._sources.entries();
for (let [source, obj] of items) for (let [source, obj] of items) {
this._removeSource(source, obj); this._removeSource(source, obj);
} }
this.actor.destroy();
}
_updateVisibility() { _updateVisibility() {
this._notificationBox.visible = this._notificationBox.visible =
this._notificationBox.get_children().some(a => a.visible); this._notificationBox.get_children().some(a => a.visible);
this.visible = this._notificationBox.visible; this.actor.visible = this._notificationBox.visible;
} }
_makeNotificationCountText(count, isChat) { _makeNotificationCountText(count, isChat) {
@@ -163,7 +160,9 @@ var NotificationsBox = GObject.registerClass({
_makeNotificationDetailedSource(source, box) { _makeNotificationDetailedSource(source, box) {
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE); let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
let sourceBin = new St.Bin({ child: sourceActor }); let sourceBin = new St.Bin({ y_align: St.Align.START,
x_align: St.Align.START,
child: sourceActor });
box.add(sourceBin); box.add(sourceBin);
let textBox = new St.BoxLayout({ vertical: true }); let textBox = new St.BoxLayout({ vertical: true });
@@ -188,7 +187,7 @@ var NotificationsBox = GObject.registerClass({
} }
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' }); let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
label.clutter_text.set_markup(`<b>${n.title}</b> ${body}`); label.clutter_text.set_markup('<b>' + n.title + '</b> ' + body);
textBox.add(label); textBox.add(label);
visible = true; visible = true;
@@ -204,10 +203,11 @@ var NotificationsBox = GObject.registerClass({
} }
_showSource(source, obj, box) { _showSource(source, obj, box) {
if (obj.detailed) if (obj.detailed) {
[obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box); [obj.titleLabel, obj.countLabel] = this._makeNotificationDetailedSource(source, box);
else } else {
[obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box); [obj.titleLabel, obj.countLabel] = this._makeNotificationSource(source, box);
}
box.visible = obj.visible && (source.unseenCount > 0); box.visible = obj.visible && (source.unseenCount > 0);
} }
@@ -230,19 +230,19 @@ var NotificationsBox = GObject.registerClass({
this._showSource(source, obj, obj.sourceBox); this._showSource(source, obj, obj.sourceBox);
this._notificationBox.add_child(obj.sourceBox); this._notificationBox.add_child(obj.sourceBox);
obj.sourceCountChangedId = source.connect('notify::count', () => { obj.sourceCountChangedId = source.connect('count-updated', source => {
this._countChanged(source, obj); this._countChanged(source, obj);
}); });
obj.sourceTitleChangedId = source.connect('notify::title', () => { obj.sourceTitleChangedId = source.connect('title-changed', source => {
this._titleChanged(source, obj); this._titleChanged(source, obj);
}); });
obj.policyChangedId = source.policy.connect('notify', (policy, pspec) => { obj.policyChangedId = source.policy.connect('policy-changed', (policy, key) => {
if (pspec.name == 'show-in-lock-screen') if (key == 'show-in-lock-screen')
this._visibleChanged(source, obj); this._visibleChanged(source, obj);
else else
this._detailedChanged(source, obj); this._detailedChanged(source, obj);
}); });
obj.sourceDestroyId = source.connect('destroy', () => { obj.sourceDestroyId = source.connect('destroy', source => {
this._onSourceDestroy(source, obj); this._onSourceDestroy(source, obj);
}); });
@@ -264,7 +264,7 @@ var NotificationsBox = GObject.registerClass({
onComplete: () => { onComplete: () => {
this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC; this._scrollView.vscrollbar_policy = St.PolicyType.AUTOMATIC;
widget.set_height(-1); widget.set_height(-1);
}, }
}); });
this._updateVisibility(); this._updateVisibility();
@@ -344,17 +344,16 @@ var NotificationsBox = GObject.registerClass({
this._sources.delete(source); this._sources.delete(source);
} }
}); };
Signals.addSignalMethods(NotificationsBox.prototype);
var Arrow = GObject.registerClass( var Arrow = GObject.registerClass(
class ScreenShieldArrow extends St.Bin { class ScreenShieldArrow extends St.Bin {
_init(params) { _init(params) {
super._init(params); super._init(params);
this.x_fill = this.y_fill = true;
this._drawingArea = new St.DrawingArea({ this._drawingArea = new St.DrawingArea();
x_expand: true,
y_expand: true,
});
this._drawingArea.connect('repaint', this._drawArrow.bind(this)); this._drawingArea.connect('repaint', this._drawArrow.bind(this));
this.child = this._drawingArea; this.child = this._drawingArea;
@@ -407,18 +406,18 @@ class ScreenShieldArrow extends St.Bin {
super.vfunc_style_changed(); super.vfunc_style_changed();
} }
vfunc_paint(paintContext) { vfunc_paint() {
if (this._shadowHelper) { if (this._shadowHelper) {
this._shadowHelper.update(this._drawingArea); this._shadowHelper.update(this._drawingArea);
let allocation = this._drawingArea.get_allocation_box(); let allocation = this._drawingArea.get_allocation_box();
let paintOpacity = this._drawingArea.get_paint_opacity(); let paintOpacity = this._drawingArea.get_paint_opacity();
let framebuffer = paintContext.get_framebuffer(); let framebuffer = Cogl.get_draw_framebuffer();
this._shadowHelper.paint(framebuffer, allocation, paintOpacity); this._shadowHelper.paint(framebuffer, allocation, paintOpacity);
} }
this._drawingArea.paint(paintContext); this._drawingArea.paint();
} }
}); });
@@ -462,7 +461,7 @@ var ScreenShield = class {
this._backgroundGroup = new Clutter.Actor(); this._backgroundGroup = new Clutter.Actor();
this._lockScreenGroup.add_actor(this._backgroundGroup); this._lockScreenGroup.add_actor(this._backgroundGroup);
this._lockScreenGroup.set_child_below_sibling(this._backgroundGroup, null); this._backgroundGroup.lower_bottom();
this._bgManagers = []; this._bgManagers = [];
this._updateBackgrounds(); this._updateBackgrounds();
@@ -495,7 +494,7 @@ var ScreenShield = class {
this._lockDialogGroup = new St.Widget({ x_expand: true, this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true, y_expand: true,
reactive: true, reactive: true,
pivot_point: new Graphene.Point({ x: 0.5, y: 0.5 }), pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
name: 'lockDialogGroup' }); name: 'lockDialogGroup' });
this.actor.add_actor(this._lockDialogGroup); this.actor.add_actor(this._lockDialogGroup);
@@ -566,11 +565,11 @@ var ScreenShield = class {
this._longLightbox = new Lightbox.Lightbox(Main.uiGroup, this._longLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true, { inhibitEvents: true,
fadeFactor: 1 }); fadeFactor: 1 });
this._longLightbox.connect('notify::active', this._onLongLightbox.bind(this)); this._longLightbox.connect('shown', this._onLongLightboxShown.bind(this));
this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup, this._shortLightbox = new Lightbox.Lightbox(Main.uiGroup,
{ inhibitEvents: true, { inhibitEvents: true,
fadeFactor: 1 }); fadeFactor: 1 });
this._shortLightbox.connect('notify::active', this._onShortLightbox.bind(this)); this._shortLightbox.connect('shown', this._onShortLightboxShown.bind(this));
this.idleMonitor = Meta.IdleMonitor.get_core(); this.idleMonitor = Meta.IdleMonitor.get_core();
this._cursorTracker = Meta.CursorTracker.get_for_display(global.display); this._cursorTracker = Meta.CursorTracker.get_for_display(global.display);
@@ -600,7 +599,7 @@ var ScreenShield = class {
height: monitor.height }); height: monitor.height });
let bgManager = new Background.BackgroundManager({ container: widget, let bgManager = new Background.BackgroundManager({ container: widget,
monitorIndex, monitorIndex: monitorIndex,
controlPosition: false, controlPosition: false,
settingsSchema: SCREENSAVER_SCHEMA }); settingsSchema: SCREENSAVER_SCHEMA });
@@ -671,12 +670,12 @@ var ScreenShield = class {
if (this._lockScreenState != MessageTray.State.SHOWN) if (this._lockScreenState != MessageTray.State.SHOWN)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
let isEnter = symbol == Clutter.KEY_Return || let isEnter = (symbol == Clutter.KEY_Return ||
symbol == Clutter.KEY_KP_Enter || symbol == Clutter.KEY_KP_Enter ||
symbol == Clutter.KEY_ISO_Enter; symbol == Clutter.KEY_ISO_Enter);
let isEscape = symbol == Clutter.KEY_Escape; let isEscape = (symbol == Clutter.KEY_Escape);
let isLiftChar = GLib.unichar_isprint(unichar) && let isLiftChar = (GLib.unichar_isprint(unichar) &&
(this._isLocked || !GLib.unichar_isgraph(unichar)); (this._isLocked || !GLib.unichar_isgraph(unichar)));
if (!isEnter && !isEscape && !isLiftChar) if (!isEnter && !isEscape && !isLiftChar)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
@@ -702,8 +701,9 @@ var ScreenShield = class {
this._lockScreenScrollCounter += delta; this._lockScreenScrollCounter += delta;
// 7 standard scrolls to lift up // 7 standard scrolls to lift up
if (this._lockScreenScrollCounter > 35) if (this._lockScreenScrollCounter > 35) {
this._liftShield(true, 0); this._liftShield(true, 0);
}
return Clutter.EVENT_STOP; return Clutter.EVENT_STOP;
} }
@@ -711,8 +711,8 @@ var ScreenShield = class {
_syncInhibitor() { _syncInhibitor() {
let lockEnabled = this._settings.get_boolean(LOCK_ENABLED_KEY); let lockEnabled = this._settings.get_boolean(LOCK_ENABLED_KEY);
let lockLocked = this._lockSettings.get_boolean(DISABLE_LOCK_KEY); let lockLocked = this._lockSettings.get_boolean(DISABLE_LOCK_KEY);
let inhibit = this._loginSession && this._loginSession.Active && let inhibit = (this._loginSession && this._loginSession.Active &&
!this._isActive && lockEnabled && !lockLocked; !this._isActive && lockEnabled && !lockLocked);
if (inhibit) { if (inhibit) {
this._loginManager.inhibit(_("GNOME needs to lock the screen"), this._loginManager.inhibit(_("GNOME needs to lock the screen"),
inhibitor => { inhibitor => {
@@ -751,9 +751,9 @@ var ScreenShield = class {
arrows[i].ease({ arrows[i].ease({
opacity: 0, opacity: 0,
duration: ARROW_ANIMATION_TIME / 2, duration: ARROW_ANIMATION_TIME / 2,
mode: Clutter.AnimationMode.EASE_IN_QUAD, mode: Clutter.AnimationMode.EASE_IN_QUAD
}); });
}, }
}); });
} }
@@ -793,7 +793,7 @@ var ScreenShield = class {
// restore the lock screen to its original place // restore the lock screen to its original place
// try to use the same speed as the normal animation // try to use the same speed as the normal animation
let h = global.stage.height; let h = global.stage.height;
let duration = MANUAL_FADE_TIME * -this._lockScreenGroup.y / h; let duration = MANUAL_FADE_TIME * (-this._lockScreenGroup.y) / h;
this._lockScreenGroup.remove_all_transitions(); this._lockScreenGroup.remove_all_transitions();
this._lockScreenGroup.ease({ this._lockScreenGroup.ease({
y: 0, y: 0,
@@ -802,7 +802,7 @@ var ScreenShield = class {
onComplete: () => { onComplete: () => {
this._lockScreenGroup.fixed_position_set = false; this._lockScreenGroup.fixed_position_set = false;
this._lockScreenState = MessageTray.State.SHOWN; this._lockScreenState = MessageTray.State.SHOWN;
}, }
}); });
this._maybeCancelDialog(); this._maybeCancelDialog();
@@ -815,7 +815,7 @@ var ScreenShield = class {
this._maybeCancelDialog(); this._maybeCancelDialog();
if (this._longLightbox.visible) { if (this._longLightbox.actor.visible) {
// We're in the process of showing. // We're in the process of showing.
return; return;
} }
@@ -857,8 +857,8 @@ var ScreenShield = class {
} }
_activateFade(lightbox, time) { _activateFade(lightbox, time) {
Main.uiGroup.set_child_above_sibling(lightbox, null); Main.uiGroup.set_child_above_sibling(lightbox.actor, null);
lightbox.lightOn(time); lightbox.show(time);
if (this._becameActiveId == 0) if (this._becameActiveId == 0)
this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this)); this._becameActiveId = this.idleMonitor.add_user_active_watch(this._onUserBecameActive.bind(this));
@@ -887,20 +887,18 @@ var ScreenShield = class {
this._becameActiveId = 0; this._becameActiveId = 0;
if (this._isActive || this._isLocked) { if (this._isActive || this._isLocked) {
this._longLightbox.lightOff(); this._longLightbox.hide();
this._shortLightbox.lightOff(); this._shortLightbox.hide();
} else { } else {
this.deactivate(false); this.deactivate(false);
} }
} }
_onLongLightbox(lightBox) { _onLongLightboxShown() {
if (lightBox.active)
this.activate(false); this.activate(false);
} }
_onShortLightbox(lightBox) { _onShortLightboxShown() {
if (lightBox.active)
this._completeLockScreenShown(); this._completeLockScreenShown();
} }
@@ -945,7 +943,7 @@ var ScreenShield = class {
// use the same speed regardless of original position // use the same speed regardless of original position
// if velocity is specified, it's in pixels per milliseconds // if velocity is specified, it's in pixels per milliseconds
let h = global.stage.height; let h = global.stage.height;
let delta = h + this._lockScreenGroup.y; let delta = (h + this._lockScreenGroup.y);
let minVelocity = global.stage.height / CURTAIN_SLIDE_TIME; let minVelocity = global.stage.height / CURTAIN_SLIDE_TIME;
velocity = Math.max(minVelocity, velocity); velocity = Math.max(minVelocity, velocity);
@@ -955,7 +953,7 @@ var ScreenShield = class {
y: -h, y: -h,
duration, duration,
mode: Clutter.AnimationMode.EASE_IN_QUAD, mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => this._hideLockScreenComplete(), onComplete: () => this._hideLockScreenComplete()
}); });
} else { } else {
this._hideLockScreenComplete(); this._hideLockScreenComplete();
@@ -975,6 +973,7 @@ var ScreenShield = class {
this._dialog = new constructor(this._lockDialogGroup); this._dialog = new constructor(this._lockDialogGroup);
let time = global.get_current_time(); let time = global.get_current_time();
if (!this._dialog.open(time, onPrimary)) { if (!this._dialog.open(time, onPrimary)) {
// This is kind of an impossible error: we're already modal // This is kind of an impossible error: we're already modal
@@ -1022,11 +1021,12 @@ var ScreenShield = class {
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => { onComplete: () => {
this._lockScreenShown({ fadeToBlack, animateFade: true }); this._lockScreenShown({ fadeToBlack, animateFade: true });
}, }
}); });
} else { } else {
this._lockScreenGroup.fixed_position_set = false; this._lockScreenGroup.fixed_position_set = false;
this._lockScreenShown({ fadeToBlack, animateFade: false }); this._lockScreenShown({ fadeToBlack: fadeToBlack,
animateFade: false });
} }
this._lockScreenGroup.grab_key_focus(); this._lockScreenGroup.grab_key_focus();
@@ -1044,11 +1044,10 @@ var ScreenShield = class {
this._animateArrows(); this._animateArrows();
} }
if (!this._arrowWatchId) { if (!this._arrowWatchId)
this._arrowWatchId = this.idleMonitor.add_idle_watch(ARROW_IDLE_TIME, this._arrowWatchId = this.idleMonitor.add_idle_watch(ARROW_IDLE_TIME,
this._pauseArrowAnimation.bind(this)); this._pauseArrowAnimation.bind(this));
} }
}
_pauseArrowAnimation() { _pauseArrowAnimation() {
if (this._arrowAnimationId) { if (this._arrowAnimationId) {
@@ -1140,13 +1139,13 @@ var ScreenShield = class {
vertical: true, vertical: true,
style_class: 'screen-shield-contents-box' }); style_class: 'screen-shield-contents-box' });
this._clock = new Clock(); this._clock = new Clock();
this._lockScreenContentsBox.add_child(this._clock); this._lockScreenContentsBox.add_child(this._clock.actor);
this._lockScreenContents.add_actor(this._lockScreenContentsBox); this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._notificationsBox = new NotificationsBox(); this._notificationsBox = new NotificationsBox();
this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this)); this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
this._lockScreenContentsBox.add_child(this._notificationsBox); this._lockScreenContentsBox.add_child(this._notificationsBox.actor);
this._hasLockScreen = true; this._hasLockScreen = true;
} }
@@ -1229,7 +1228,7 @@ var ScreenShield = class {
scale_y: 0, scale_y: 0,
duration: animate ? Overview.ANIMATION_TIME : 0, duration: animate ? Overview.ANIMATION_TIME : 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD, mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this._completeDeactivate(), onComplete: () => this._completeDeactivate()
}); });
} }
@@ -1239,8 +1238,8 @@ var ScreenShield = class {
this._dialog = null; this._dialog = null;
} }
this._longLightbox.lightOff(); this._longLightbox.hide();
this._shortLightbox.lightOff(); this._shortLightbox.hide();
this.actor.hide(); this.actor.hide();
if (this._becameActiveId != 0) { if (this._becameActiveId != 0) {

View File

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

View File

@@ -32,8 +32,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
/** /**
* sleep: * sleep:
* @param {number} milliseconds - number of milliseconds to wait * @milliseconds: number of milliseconds to wait
* @returns {Promise} that resolves after @milliseconds ms
* *
* Used within an automation script to pause the the execution of the * Used within an automation script to pause the the execution of the
* current script for the specified amount of time. Use as * current script for the specified amount of time. Use as
@@ -51,7 +50,6 @@ function sleep(milliseconds) {
/** /**
* waitLeisure: * waitLeisure:
* @returns {Promise} that resolves when the shell is idle
* *
* Used within an automation script to pause the the execution of the * Used within an automation script to pause the the execution of the
* current script until the shell is completely idle. Use as * current script until the shell is completely idle. Use as
@@ -92,13 +90,13 @@ function _callRemote(obj, method, ...args) {
/** /**
* createTestWindow: * createTestWindow:
* @param {Object} params: options for window creation. * @params: options for window creation.
* {number} [params.width=640] - width of window, in pixels * width - width of window, in pixels (default 640)
* {number} [params.height=480] - height of window, in pixels * height - height of window, in pixels (default 480)
* {bool} [params.alpha=false] - whether the window should have an alpha channel * alpha - whether the window should have an alpha channel (default false)
* {bool} [params.maximized=false] - whether the window should be created maximized * maximized - whether the window should be created maximized (default false)
* {bool} [params.redraws=false] - whether the window should continually redraw itself * redraws - whether the window should continually redraw itself (default false)
* @returns {Promise} * @maximized: whethe the window should be created maximized
* *
* Creates a window using gnome-shell-perf-helper for testing purposes. * Creates a window using gnome-shell-perf-helper for testing purposes.
* While this function can be used with yield in an automation * While this function can be used with yield in an automation
@@ -121,7 +119,6 @@ function createTestWindow(params) {
/** /**
* waitTestWindows: * waitTestWindows:
* @returns {Promise}
* *
* Used within an automation script to pause until all windows previously * Used within an automation script to pause until all windows previously
* created with createTestWindow have been mapped and exposed. * created with createTestWindow have been mapped and exposed.
@@ -133,7 +130,6 @@ function waitTestWindows() {
/** /**
* destroyTestWindows: * destroyTestWindows:
* @returns {Promise}
* *
* Destroys all windows previously created with createTestWindow(). * Destroys all windows previously created with createTestWindow().
* While this function can be used with yield in an automation * While this function can be used with yield in an automation
@@ -148,8 +144,8 @@ function destroyTestWindows() {
/** /**
* defineScriptEvent * defineScriptEvent
* @param {string} name: The event will be called script.<name> * @name: The event will be called script.<name>
* @param {string} description: Short human-readable description of the event * @description: Short human-readable description of the event
* *
* Convenience function to define a zero-argument performance event * Convenience function to define a zero-argument performance event
* within the 'script' namespace that is reserved for events defined locally * within the 'script' namespace that is reserved for events defined locally
@@ -163,7 +159,7 @@ function defineScriptEvent(name, description) {
/** /**
* scriptEvent * scriptEvent
* @param {string} name: Name registered with defineScriptEvent() * @name: Name registered with defineScriptEvent()
* *
* Convenience function to record a script-local performance event * Convenience function to record a script-local performance event
* previously defined with defineScriptEvent * previously defined with defineScriptEvent
@@ -278,9 +274,8 @@ function _collect(scriptModule, outputFile) {
/** /**
* runPerfScript * runPerfScript
* @param {Object} scriptModule: module object with run and finish * @scriptModule: module object with run and finish functions
* functions and event handlers * and event handlers
* @param {string} outputFile: path to write output to
* *
* Runs a script for automated collection of performance data. The * Runs a script for automated collection of performance data. The
* script is defined as a Javascript module with specified contents. * script is defined as a Javascript module with specified contents.

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