Compare commits

...

311 Commits

Author SHA1 Message Date
e207b45317 Bump version to 3.29.92
Update NEWS.
2018-08-29 18:54:14 +02:00
6b5117677d Updated Czech translation 2018-08-29 07:18:37 +02:00
900398406c panel: Keep prefs in sync with shell-shows-app-menu state
Previously mutter listened to Xsettings (via GTK) to get notified
whether the shell showed the app menu. After X11 support was changed in
the direction of being less central, listening to this particular
Xsettings were removed with the intention of having the Shell tell
mutter directly whether it was showing the menu or not.

This commit makes that happen. It still travels through Xsettings (still
via Gtk), as the shell still gets that state from Xsettings, but fixing
this is out of scope for this particular fix.

Closes: https://gitlab.gnome.org/GNOME/mutter/issues/276
2018-08-28 23:53:10 +00:00
461d2b1945 osk: Add Malayalam layout
The layout is based on inscript layout.

Copyright 2018 ICFOSS (info@icfoss.in)

Fixes #441
2018-08-28 20:52:27 +02:00
6c2f11e8a4 inputMethod: Fix to hide preedit text
ibus_engine_update_preedit_text() should hide the pre-edit text
when visible == false.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/431
2018-08-28 20:24:35 +02:00
dbf993300a js: use ES6 template strings for dbus interfaces
Use multiline template strings for dbus interfaces as they're easier to maintain
2018-08-27 19:23:00 +02:00
f77b3da74f js/ui: Choose some actors to cache on the GPU
Flag some actors that are good candidates for caching in texture memory
(what Clutter calls "offscreen redirect"), thereby mostly eliminating
their repaint overhead.

This isn't exactly groundbreaking, it's how you're meant to use
OpenGL in the first place. But the difficulty is in the design of
Clutter which has some peculiarities making universal caching
inefficient at the moment:

 * Repainting an offscreen actor is measurably slower than repainting
   the same actor if it was uncached. But only by less than 100%,
   so if an actor can avoid changing every frame then caching is usually
   more efficient over that timeframe.

 * The cached painting from a container typically includes its children,
   so you can't cache containers whose children are usually animating at
   full frame rate. That results in a performance loss.
     This could be remedied in future by Clutter explicitly separating a
   container's background painting from its child painting and always
   caching the background (as StWidget tries to in some cases already).

So this commit selects just a few areas where caching has been verified
to be beneficial, and many use cases now see their CPU usage halved:

One small window active...... 10% -> 7% (-30%)
...under a panel menu........ 23% -> 9% (-61%)
One maximized window active.. 12% -> 9% (-25%)
...under a panel menu........ 23% -> 11% (-52%)
...under a shell dialog...... 22% -> 12% (-45%)
...in activities overview.... 32% -> 17% (-47%)
(on an i7-7700)

Also a couple of bugs are fixed by this:

https://bugzilla.gnome.org/show_bug.cgi?id=792634
https://bugzilla.gnome.org/show_bug.cgi?id=792633
2018-08-27 14:16:59 +00:00
bc6a38dda7 Update Korean translation 2018-08-27 14:11:52 +00:00
f3a02057c1 Update Italian translation 2018-08-27 07:55:20 +00:00
ad15ce9139 Update Indonesian translation 2018-08-26 13:49:05 +00:00
5d178506bf Update Kazakh translation 2018-08-25 17:27:53 +00:00
14cc9bfb1e Bump version to 3.29.91
Update NEWS.
2018-08-20 16:09:21 +02:00
ce4c485f34 windowManager: Ignore auto-repeat activation of toggle keybindigs
Use Meta.KeyBindingFlags.IGNORE_AUTOREPEAT for open-application-menu
and toggle-message-tray keybindings.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/373
2018-08-20 11:14:38 +00:00
1877a2e00a viewSelector: Ignore auto-repeat activation of toggle keybindigs
Use Meta.KeyBindingFlags.IGNORE_AUTOREPEAT for toggle-application-view
and toggle-application-view keybindings.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/373
2018-08-20 11:14:37 +00:00
b2fa7a6d8f Update British English translation 2018-08-19 16:42:07 +00:00
36c604d793 Update Romanian translation 2018-08-19 16:17:31 +00:00
9a5a4b2206 Revert "workspaceThumbnail: rebuild thumbnails if workareas size changed"
It is unclear what the change was supposed to be fixing, but it
broke animations of workspace additions and removals, as those
events trigger the ::workareas-changed signal.

This reverts commit c29bd46e7a.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/162
2018-08-19 12:41:08 +00:00
3ab9e9e8ad runDialog: Use ClutterText::activate for enter handling
Instead of consuming the event in front of the input method. Enter
is sometimes overriden by those, so it seems better to let the IM
handle the key event, and react later to it if it got propagated
anyway. That is what ::activate does, so use this signal.

This used to work before ClutterInputMethod/InputFocus because the
IM received the events directly from stage captured events. This
is not the case anymore.

Closes: #440
2018-08-17 18:37:32 +00:00
dd59212d3f st: Use ClutterClickAction on StEntry primary/secondary icons
This makes them work on touchscreens as well.

Closes: #116
2018-08-17 18:27:44 +00:00
2b654ec310 Update Catalan translation 2018-08-16 20:45:12 +02:00
764fbbe052 overview: Restore previous workspace switcher policy
We used to keep the workspace switcher slid out when the user made use
of workspaces. This was changed in commit 2d84975 to give more space
to window previews, but it turned out to make the switcher quite a lot
more difficult to interact with (rather than only being a question of
discoverability). So go back to the previous behavior.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/161
2018-08-14 17:34:57 +00:00
328c63bf64 overviewControls: Sync hover after drag operations
During global grabs, actors miss enter and leave events required
for correct hover tracking. This can cause the workspace switcher
to get stuck while slid out, so ensure the actor's hover state is
synced after drag operations.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/161
2018-08-14 17:34:57 +00:00
95788c9834 build: Use dedicated resources for helper programs
Using a single resource file for all JS sources saves a couple of
build system instructions, but has some serious downsides:

 - bundling the entire shell code with the tools blows
   up their size unnecessarily

 - the tools are rebuilt unnecessarily for any shell
   code change

Autotools was painful enough to let this slip, but with meson we
don't have any excuses - using the actual dependencies speeds up
the build a tiny bit and reduces the tools' sizes from over 2M
to about 50k.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/192
2018-08-14 17:28:04 +00:00
9cf571efbd build: Clean up tools' dependencies
Simply reusing the same dependencies as gnome-shell itself not only
means that we link tons of stuff unnecessarily, but also that we
have to do the whole mutter rpath dance for nothing. Just use the
dependencies those executables actually need for a nice cleanup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/192
2018-08-14 17:28:03 +00:00
dc4128c78b build: Don't modify typelib search path in tools
We need this in the main gnome-shell executable in order to locate
the private Shell and St typelibs, but those aren't useful or even
usable in the extension-prefs/portal helper tools.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/192
2018-08-14 17:28:03 +00:00
73d8c82640 layout: Mark chrome container as NO_LAYOUT
Showing and hiding children does not affect the allocation of the uiGroup
nor its other children. We can avoid full relayout/redraw in those
situations.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/197
2018-08-14 19:13:30 +02:00
2f7377b250 Fix typo in Czech translation
https://bugzilla.gnome.org/show_bug.cgi?id=796829
2018-08-13 09:52:22 +02:00
804f23b179 Update German translation 2018-08-12 12:21:06 +00:00
2be6ddc54e Update Chinese (Taiwan) translation 2018-08-12 10:18:17 +00:00
dff4f0109e Update French translation 2018-08-09 17:52:20 +00:00
2e663b2a94 Update Friulian translation 2018-08-08 04:58:52 +00:00
9f4aa6ebf2 build: Fix build with meson >= 47.0
With meson >= 47.0, building gnome-shell will fail
when --rebuild-types is used as an option for gtk-doc,
so stop using that option and bump the meson requirement.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/191
2018-08-06 14:58:51 +02:00
afe5703710 networkAgent: Fix another ByteArray => Uint8Array instance
This was missed in commit 7ca418a79a. As we are dealing with
non-\0-terminated data here, go through GBytes this time.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/189
2018-08-06 12:16:59 +00:00
02d06bb1f3 overview: Use whole stage size for cover pane
We show a cover pane on top of the overview during transitions to
prevent issues caused by clicks and mouseover events when the overview
is not ready. Right now, this pane is only being shown on the primary
monitor, which obviosly allows interactions to happen before the
animations are finished on the secondary monitors.

To fix this, use the size of the whole stage for the cover pane.
2018-08-06 10:18:28 +02:00
3a78695bd9 Update Turkish translation 2018-08-06 07:16:17 +00:00
13e8c35d36 Updated Lithuanian translation 2018-08-05 23:22:14 +03:00
3b8dfd98dd Update Polish translation 2018-08-04 19:14:44 +02:00
6b610b26f8 keyboard: Refactor code resetting IM on window drags
When a window is dragged, the OSK should get hidden. Just
do this in a nicer way.
2018-08-03 17:02:20 +02:00
81956e9b84 keyboard: defer position-changed till we have a rect
Emitting it that soon results in JS warnings, as we don't have
everything in place yet. The position-changed signal will be
emitted from other locations as soon as we have it.

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

Closes: #464
2018-08-03 13:12:20 +02:00
6b41f82346 Updated Slovenian translation 2018-08-03 11:17:49 +02:00
1fca090374 tools: fix XDG desktop syntax in gnome-shell-overrides-migration
Reported by desktop-file-validate:
error: value "True" for boolean key "NoDisplay" in group "Desktop
Entry" contains invalid characters, boolean values must be "false" or
"true"
2018-08-03 00:49:49 +02:00
da2fc2c9d3 workspace: Simplify detecting added dialogs after closing a window
When trying to close a window in the overview by clicking the close
button and the window doesn't get closed but a dialog is added to the
window afterwards, we close the overview and show the dialog.

Instead of adding a separate listener for the window-added signal to the
WindowOverlay, let the WindowClones remember that the close button was
pressed and activate themselves if a dialog is added after that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180
2018-08-03 00:09:02 +02:00
52cbc299a7 workspace: Fix infinite loop when finding parent window of dialogs
When a dialog is added to a window while the overview is shown, we get
its parent using get_transient_for() so we can add it to the right
window clone.

If we have multiple layers of dialogs we have to do this recursively
until we find the root ancestor. This case currently results in an
infinite loop: Since parent is always set to the same window, the
while-condition will always be true.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180
2018-08-03 00:09:02 +02:00
9f436ce373 data: Fix comment in schema 2018-08-01 20:04:53 +02:00
d908940ef3 showOSD: Fix handling of defined 'falsy' parameters
For the OSD, all parameters except for the icon are optional - if the
caller doesn't include the 'label' option, the OSD won't show a label
etc.

While this makes sense for an API, it means that we have to be careful
to correctly differentiate an option that was omitted and an option
that has a 'falsy' value like false or 0.

Unfortunately since commit ccaae5d3c we no longer do, with the result
that OSDs meant for the first monitor will show up on all, and a level
of 0 is presented as no level bar instead of an empty one, whoops.

https://bugzilla.gnome.org/show_bug.cgi?id=791669
2018-08-01 13:58:23 +02:00
eeda54f24d Update Brazilian Portuguese translation 2018-08-01 10:15:51 +00:00
b8b5da1e95 Bump version to 3.29.90
Update NEWS.
2018-08-01 03:43:50 +02:00
3a9ad5c577 Update POTFILES.in 2018-07-31 23:55:20 +02:00
d57dc94d9e tools: Migrate changed overrides settings
While the new per-desktop overrides in GIO are easier to use for
both developers and users, it is still inconvenient for everyone
who changed the defaults using the old overrides hack to lose
their settings. Address this by running a small script on startup
that migrates existing settings.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-31 18:36:26 +00:00
393d7246cc Replace custom override schema with per-desktop override
GSettings now recognizes per-desktop overrides that can be used
to change schemas' default values for a particular desktop. This
is not entirely unlike our existing custom override mechanism in
mutter, except that it is not limited to keys in org.gnome.mutter,
and it doesn't require a separate schema - the latter means that
we (and gnome-teak-tool) no longer have to figure out the correct
schema for the current login session and just use the original one.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-31 18:36:26 +00:00
6217c3b88d volume: Show overamplified icon when in overdrive
Show an overamplified volume icon if volume is louder the max normalized one.
Use a similar logic as gnome-settings-daemon to delimit values, restricted
to output.
The purpose is to help users remember that visiting some websites or
using some apps can get LOUD.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:15 +00:00
ddd4fd9c24 barLevel: Add "overdrive" capability
Implement for barLevel an overdrive area. This is a zone represented via a
different styling to indicate that you are bypassing the normal zone of
a given level, without reaching yet the maximum limit.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:14 +00:00
d2a97e7f1d volume: Allow volume above 100%
Depending on hardware and recorded volume level, turning up the speakers
to the maximum volume may not be enough and the user will want to amplify
the volume above 100%. Currently this requires opening the sound Settings
panel which gets cumbersome when required repeatedly.

To support this case better, allow raising the sound volume above 100%
directly from the system menu if the feature is enabled via the
`allow-volume-above-100-percent` key in `org.gnome.desktop.sound`.
2018-07-31 18:14:13 +00:00
aa75e89216 osdWindow: Allow levels above 100%
Allow osd representing levels that can be more than 100% by accepting
an optional parameter setting that maximum level.
gnome-settings-daemon will use this to indicate volume levels above 100%,
which our own volume indicator will soon support as well.
2018-07-31 18:14:11 +00:00
3f756dc608 barLevel: Support maxValue higher than 1
Ensure that both barLevel and slider can support a higher maxValue than 1
and computes various positions based on it.
It defaults to 1 if not set.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:10 +00:00
ed8e89bc19 osdWindow: Reuse BarLevel drawing functionality
Reuse the BarLevel class to get similar drawing behavior as Slider.
Rename theme css impacted properties and ensure that the osdWindow
remains accessible.
Ensure we don't force setting a custom border color like on the OSD.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:10 +00:00
c90a4e4849 levelBar: Factor out bar drawing
Split drawing logic from Slider to BarLevel subclass.
This changes part of the theme css from -slider- to -barlevel-.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:09 +00:00
f433b12d6e system: Don't execute Settings
In a9ad91c831, a bug was introduced in the following code:

```c
            this._settingsAction.connect('clicked',
                                         this._onSettingsClicked().bind(this));
```

Notice that the callback is being executed! This commit
fixes that by removing the '()' from the callback.
2018-07-31 13:31:59 -03:00
7ca418a79a Explicitly convert raw data to strings
As strings are guaranteed to use UTF-8 in the GNOME platform, generic
file APIs like g_file_load_contents() return raw data instead. Since
gjs' recent update to mozjs60, this data is now returns as Uint8Array
which cannot simply be treated as string - its toString() method boils
down to arr.join(',') - so use gjs' new ByteArray module to explicitly
convert the data.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/179
2018-07-31 16:28:53 +00:00
a9ad91c831 system: Pick up Settings name and icon from app
The settings action button in the system menu simply launches
gnome-control-center, so we want its icon (and accessible name)
to always match the app. So instead of keeping the button in-sync
with Settings, just look up that information from the app itself.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/433
2018-07-31 16:52:47 +02:00
bd1c7774ee system: Enforce symbolic icons in action buttons
We can simply request the symbolic variant from CSS so that we don't
have to append '-symbolic' to all the names. This will always make
it easier to pick up that information from external sources (like
.desktop files).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/433
2018-07-31 16:52:47 +02:00
91da3789bc windowManager: Fix switch animation between non-adjacent workspaces
Commit e5c95b910d refactored the workspace animation to also handle
animations that involve all surrounding workspaces, but due to an
ill-advised review comment (guess whose) it broke the animation
for non-neighboring workspaces.

Update the code to handle correctly whether in a given direction:
 - we have the target workspace of a given index
 - we have a neighboring workspace
 - we don't need to animate anything

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/182
2018-07-31 06:51:35 +02:00
2991f9f102 util: Fix code style
The C code introduced in 49d8ff38e did not follow
GNOME Shell's C code style. This commit adjusts it
to comply with the correct code style.
2018-07-30 21:23:28 -03:00
49d8ff38e7 Add check_cloexec_fds debug command
Add a debug command (to be executed manually via Alt+F2) to check
that all of gnome-shell's file descriptors have the CLOEXEC flag set.
This is important so that internal file descriptors do not get passed
to apps when they are launched.

It prints a warning message for every fd that does not have the flag set.

fdwalk() is used from the standard library if available (it is not
available in glibc), otherwise we use the same implementation as glib
has internally.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132
2018-07-30 23:11:41 +00:00
4b522a02c3 shell-app: remove child_setup from app launching
When the amount of free memory on the system is somewhat low, gnome-shell
will sometimes fail to launch apps, reporting the error:
  fork(): Cannot allocate memory

fork() is failing here because while cloning the process virtual address
space, Linux worries that the thread being forked may end up COWing the
entire address space of the parent process (gnome-shell, which is
memory-hungry), and there is not enough free memory to permit that to
happen. This check is somewhat irrelevant because we are only forking
to immediately exec(), which will discard the whole virtual address
space anyway.

This issue can be avoided by using a new optimized gspawn codepath in
the latest glib development version, which uses posix_spawn() internally.

For the optimized codepath to be used, we must not pass a child_setup
function, so the the file descriptor management is reimplemented here
using new glib API to pass fds to the child process. The old API will
continue to be used on older glib versions.

We must also change the spawn flags for this code path to be hit.
I checked that gnome-shell's open file descriptors are all CLOEXEC
so using G_SPAWN_LEAVE_DESCRIPTORS_OPEN should be safe.

This will result in more resilient app launching when memory is low,
since the optimized spawn path avoids cloning the virtual address
space of the parent process (gnome-shell) and avoids the irrelevant
memory overcommit check.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132
2018-07-30 23:11:41 +00:00
ebe6f59d7e windowManager: Make workspace switching gestures follow motion
When 4fg swipe motion happens, set up early the workspace switching
animation with all surrounding workspaces. This allows us to move
all content back and forth in any direction. This works on both
touchcreens and touchpads.

When the gesture is activated, the same data is reused to follow
up with the tween animation.

The threshold has been also doubled, it was fairly small to start
with, and feels better now that workspaces stick to fingers.

https://bugzilla.gnome.org/show_bug.cgi?id=788994
2018-07-30 21:20:52 +00:00
e5c95b910d windowManager: Refactor workspace switching animations
Besides the separation into distinct functions, the stored data has
been made able to generically store windows from all surrounding
workspaces. All while keeping a special mode to animate between two
workspaces (The usual till now), this is the only mode exercised so
far.

In order to ease animations, all window groups are now children of
a common container, which is then animated.
2018-07-30 21:20:50 +00:00
2f76951658 windowManager: Declare variables
Fixes warnings from GJS.
2018-07-30 21:20:49 +00:00
3efd296fc3 app: Consider "new-window" action for opening new windows
While can_open_new_window() uses some elaborate heuristics to predict
whether an application can open multiple windows, open_new_window()
will always simply relaunch the application. This is often the best
we can do, but when an application provides a "new-window" action in
its .desktop file or on the bus, it is much more likely to work as
expected than blindly activating the app and hoping for a particular
behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=756844
2018-07-30 19:21:40 +00:00
6688610c23 screenshot: Add PickColor() method to Screenshot interface
Use the newly added API to implement a color picker method in the
screenshot interface, so that the desktop portal can expose it
to applications.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
d2c75801ea screenshot: Allow bypassing lockdown setting
The setting is only relevant when writing to disk is required. We
will soon expose a screenshot method that doesn't, so make it
possible to ignore it.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
be84a00022 screenshot: Add pick_color() method
Graphical applications like GIMP or GIMP allow picking colors from
any location on-screen. In order to keep supporting this feature
on wayland and in sandboxed apps, we will expose an appropriate
method in the Screenshot interface, so first add a corresponding
method to ShellScreenshot.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
da537cda43 screenshot: Adopt GIO's async pattern
A custom callback type is more convenient, but only as long as no
other callback type is required. We are about to add functionality
that does not return the filename to a screenshot saved on disk, so
prepare for that by moving to GIO's generic async callback pattern.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:09 +00:00
304c667bca windowManager: Add top edge drag gesture to unmake fullscreen window
Fullscreen windows cannot be restored by touch device users unless the
application adds support for it.
As it is unlikely to change all application lets introduce a top edge
drag gesture which unmakes fullscreen windows.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/123
2018-07-28 12:11:41 +02:00
879a81abeb remoteAccess: Make indicator orange
Make the indicator for active remote access use the warning color, to
indicate the severity of allowing remote access.

This only makes the indicator icon orange; the icon in the system menu
is still white.
2018-07-27 18:10:35 +02:00
e68ca5adbd Updated Spanish translation 2018-07-27 13:38:45 +02:00
cf69fe4b18 gdm, util: Always allow to retry login in unlock mode
When in lockscreen mode there's no point of resetting the auth login as there's
no welcome screen, and that would just cause the UI to freeze, with no reason.
This could have been useful if we were stopping the user to login for a given
time after ALLOWED_FAILURES attempts, but this is not the case yet.
2018-07-25 20:32:42 +00:00
8f848925f6 authPrompt: Do not enable sensitivity if retries are disallowed
Set the sensitivity of the UI according to the canRetry parameter and thus
if no more logins are allowed don't take any input.

Fixes #311
2018-07-25 20:32:42 +00:00
d21657fe61 authPrompt: Unset preemptiveAnswer on reset
When we get a reset signal the preemptiveAnswer should be also unset or it will
be used next time the user authPrompt will be activated, even without any further
user interaction.

Fixes #311
2018-07-25 20:32:41 +00:00
ce3555382b workspaceThumbnail: Sync clone position changes with actor
We need to update the clone position if window actor (not the meta window)
position changed.

https://bugzilla.gnome.org/show_bug.cgi?id=776588
2018-07-24 11:08:25 +00:00
837a00c3f0 workspace: Recompute bounding box on window 'position-changed'
We need to update the clone position if window size changed
also, rename meta window 'size-changed' callback accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=792681
2018-07-24 11:08:25 +00:00
132c8e0cf8 icons: update to current metaphors
- sync with adwaita-icon-theme metaphors
2018-07-24 11:05:55 +02:00
9c62522419 Update POTFILES.in 2018-07-23 23:14:12 +02:00
0d5bae3844 Add remote access indication and control
Add an indicator for when there is something access the display server
remotely. This could be 1) remote desktop, 2) screen cast or 3) remote
control, but all effectively applications using
org.freedesktop.portal.ScreenCast or org.gnome.portal.RemoteDesktop as
well as gnome-remote-desktop using the corresponding org.gnome.Mutter
APIs directly.

As it is now, it'll simply show a single icon for when anything is
having an active session, and a single action "Turn off" that'll close
every active session.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/160
2018-07-23 14:03:26 +02:00
97f6a35b46 Update French translation 2018-07-20 09:00:03 +00:00
43e8dfacb4 build: Don't use libdir for systemd unit path
Some systems define it to /usr/lib64 on 64-bit systems, which is not
where systemd looks for unit files. Just hardcode 'lib' in the install
prefix until we get to use the pkg-config file.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/424
2018-07-18 23:03:30 +02:00
0221099e7e Bump version to 3.29.4
Update NEWS.
2018-07-18 17:46:36 +02:00
374caade47 inputMethod: Handle IBusInputContext::forward-key-press
The input method may hint that certain keycodes should be pressed/released
besides the textual information in ::commit. An example is hitting space
in some IMs to commit text, where both ::commit happens, and an space is
visibly inserted. In order to handle this properly, we must honor
::forward-key-press.

In order to cater for the case that a keypress is forwarded while handling
that same keypress in a physical keyboard, check the current event being
handled and just forward it as-is if it matches. This is necessary to
prevent state from being doubly set, and the second event silenced away.

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

Closes: #275
2018-07-17 23:27:24 +00:00
a5937d1d6d Add systemd units
So that we can be started by systemd --user, instead of gnome-session.

There are three units:

  - gnome-shell.service: Start gnome-shell itself.
  - gnome-shell-x11.target, gnome-shell-wayland.target: Sync points for
    units that need to care if x11 or wayland is in use.
    gnome-settings-daemon will use these, for example.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/138
2018-07-17 18:10:06 +00:00
e36ba874a8 Stop using conditional catch statements
It is a mozilla extension that is going away in SpiderMonkey 60.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/151
2018-07-17 17:02:39 +00:00
22392d1328 loginManager: Get the session ID from logind if XDG_SESSION_ID unset
If we're started by systemd, we won't be in the user's display session.
However, this is still the session that will get locked & unlocked. Ask
logind what the 'display' or 'greeter' session is, and watch for the
Unlock signal for that session to know when to unlock.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/137
2018-07-17 17:44:18 +02:00
0dee82fb9f keyboard: Handle no-window case in FocusTracker
For windows, the cursor location needs to be adjusted by the frame
offsets. However we cannot assume that there is a window, as the
shell itself can have the key focus.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/414
2018-07-17 01:44:18 +02:00
68f00f397f Update Russian translation 2018-07-16 21:27:25 +00:00
905801b178 panel: Allow restoring maximized/tiled windows by touch
Maximized and tiled windows can be restored with a drag gesture,
not only from their titlebars, but also from any non-reactive
parts of the top bar above the window. Currently this only works
for actual pointer devices, extend the behavior to handle touch
as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/112
2018-07-14 18:38:16 +00:00
4a7082bb0f switcherPopup: Cancel window cycling with Tab
If the Escape key is used for a window/app cycler/switcher shortcut
(such as "Switch windows directly"), then there is no way to cancel
the switching/cycling operation with the keyboard.

This change allows cancelling such an operation by pressing the Tab
key, but only if Tab is not already being used by the current
switcher/cycler shortcut.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/315
2018-07-14 14:35:05 +00:00
2e90c5fa4b popupMenu: Don't handle key presses directly if there are modifiers
Key events involved in a keyboard shortcut are not completely consumed by
Mutter. That means that if the popupMenu is bound to a shortcut (e.g.
Alt<Space>) and the user keeps the keys pressed, the same key-event will be
delivered to the popupMenu. We can workaround this issue filtering out all the
events where a a modifier is down (except capslock).

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/372
2018-07-14 14:04:18 +02:00
50e849a186 st-texture-cache: Obey cache policy in st_texture_cache_load
https://bugzilla.gnome.org/show_bug.cgi?id=663461
2018-07-13 20:50:08 +00:00
e7f2e92410 events: Re-use event messages where possible
Destroying and recreating the entire events list on every change is not only
wasteful, it also breaks the clear functionality as messages scheduled for
removal are replaced with "new" messages after the first message has been
removed.

Address both issues by keeping track of all messages and re-use them
whenever possible.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/325
2018-07-13 20:13:30 +00:00
b1b455ff1a st-adjustment: Mark all properties as EXPLICIT_NOTIFY
All adjustment setter functions take good care of avoiding emission of
notify:: when it's not needed. The set_property() implementation already
calls into the setter functions, so mark the properties as EXPLICITY_NOTIFY
in order to optimize notify:: emission away through g_object_set (rather
common from JS code).
2018-07-13 11:53:46 +00:00
ab4c72d758 st-box-layout: Queue relayout on adjustment changes
The actor allocation doesn't change per-se, but apply_transform()
will practically transform it. In order to have the paint volume
update accordingly, queue a relayout.
2018-07-13 11:53:46 +00:00
86a520b880 st: Clip StEntry to allocation
The default get_paint_volume() implementation will do the union
of children, and the child ClutterText paint volume may expand
beyond StEntry size when text overflows.

We actually want all content to be clipped to the StEntry, so
implement get_paint_volume() and tell it so.
2018-07-13 11:53:45 +00:00
4bf033a885 st: Make StScrollables' paint volume reflect the unconstrained view
And constrain it in StScrollView instead (instead of falling back to an
infinite paint volume, as the actor as paint/pick impls, but no
corresponding get_paint_volume one).

Fixes artifacts with the AppView (and possibly other places) when paint
volumes are aggressively cached.
2018-07-13 11:53:45 +00:00
e3ebc8d0c6 keyboard: Remove stale references to global.screen
(Re)introduced by the previous patch.
2018-07-11 18:46:49 +02:00
fc5ab44704 keyboard: Implement standalone FocusTracker
And stop using FocusCaretTracker for caret position purposes. This
new object uses 1) the text-input protocol in wayland and 2) Info
from IBusPanelService for X11 (which is meant to work for XIM too).

This drops the usage of AtspiEventListener for OSK purposes, which
is best to avoid.
2018-07-11 18:32:32 +02:00
d5e8f174d4 Bump version to 3.29.3
Update NEWS.
2018-07-09 19:05:55 +02:00
d9a1434ae9 workspaceThumbnail: Don't keep stale clones in list
If a clone gets destroyed before the corresponding MetaWindow is
removed from the workspace, we will still find it in the list of
clones and try to destroy it again. Avoid the resulting warnings
by updating the list of clones immediately when a clone is destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-07-09 13:00:35 +02:00
d0bdea3178 workspace: Don't keep stale clones in list
If a clone gets destroyed before the corresponding MetaWindow is
removed from the workspace, we will still find it in the list of
clones and try to destroy it again. Avoid the resulting warnings
by updating the list of clones immediately when a clone is destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-07-09 13:00:17 +02:00
ccadf6aca1 workspaceThumbnail: remove unused private win reference 2018-07-09 13:00:15 +02:00
266b0e9dd0 keyboard: remove global.screen
This is disabled code for now, but let's have it fixed once we'll use it
2018-07-08 17:43:15 +02:00
f7355f593d closeDialog: use {disable,enable}_unredirect_for_display
Remove leftover global.screen presency
2018-07-08 17:43:15 +02:00
a301820258 Update Catalan translation 2018-07-08 09:23:29 +02:00
47ea10b7c9 Remove usage of MetaScreen
Remove any usage of MetaScreen, as it has been removed from libmutter
in the API version 3. The corresponding functionality has been moved
into three different places: MetaDisplay, MetaX11Display (for X11
specific functionality) and MetaWorkspaceManager.

https://bugzilla.gnome.org/show_bug.cgi?id=759538
2018-07-06 19:56:19 +02:00
2c0376c150 workspaceThumbnail: Initialize signal handler ids to 0
They are used in conditions, so initialize them first.
2018-07-06 19:55:07 +02:00
ac58c4280b Update Occitan translation 2018-07-05 09:51:43 +00:00
e39d7152f2 st-private: Warn if creating shadow for unallocated actors 2018-06-29 11:00:25 +02:00
e522e2e804 st-icon: Create shadow pipeline only at paint
Don't try to allocate the shadow after allocation, just do it at paint
as it's done by other shadowed widgets
2018-06-29 10:43:12 +02:00
2ba26407f1 st-icon: Remove unused size values 2018-06-29 10:43:12 +02:00
996dd74157 layoutManager: Return null monitor if focusIndex is invalid
https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:30 +02:00
878946962d windowManager: Don't animate unmanaged windows on (un)minimization 2018-06-28 17:05:30 +02:00
84d2d3feb3 keyboard: Check monitor validity before deferencing it
Monitor could be invalid in headless mode.

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:30 +02:00
19e864ed3b keyboard: Handle case where keyboardMonitor is unset
This may be the case where keyboardIndex is -1, which may be the
case where either the keyboard monitor hasn't been set yet, or
the keyboard is being unmanaged and meta_window_get_monitor
returns -1

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 17:05:29 +02:00
c9bf72c5c4 windowMenu: Check if monitorIndex is valid before using it
Calling meta_window_get_monitor on an unmanaged window may return
-1, so we need to check the return value.

https://bugzilla.gnome.org/show_bug.cgi?id=788882
2018-06-28 16:29:07 +02:00
5fe349d5ba thunderbolt: Do not auto start boltd
The service is expected to be activated by systemd when a thunderbolt
device is plugged in, so no need to have it auto-started with the
session.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/54
2018-06-25 14:17:07 +00:00
1f03599d1c st-texture-cache: Save cairo surfaces to a different map
The default keyed_surface is meant to handle CoglTextures thus we can't
add cairo surfaces to it, as the DestroyNotify function won't handle them.

Then the quicker way is to just add another Hash table for handling
such types of textures, with proper destroy function.
2018-06-21 00:56:36 +02:00
a24999b7a3 st-texture-cache: Don't add NULL textures to cache
This might cause a crash when cleaning up the cache as the hash table has
cogl_object_unref as DestroyNotify function but that assumes that
the passed object is a valid CoglObject.

Fixes: #210
2018-06-21 00:48:54 +02:00
8237a1f6e0 Change "const" to "var"
These variables are in fact used from other modules, so gjs complains about them
being const.
2018-06-18 11:19:13 -04:00
f9dec475a1 Update Chinese (Taiwan) translation 2018-06-13 08:38:03 +00:00
68b01a8f56 theme: Use tabular figures where appropriate
In places where numbers appear in columns (like the calendar widget) or
where changing numbers would result in labels jiggling around due to
small width changes (like the clock), use the newly added
font-feature-settings support to request tabular figures.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/34
2018-06-08 13:27:57 -04:00
f56ba0877a st: Add support for font-feature-settings
Cantarell now supports tabular figures, which are useful in places
where digits should either align or not use different widths. In
order to allow elements to request the feature, add support for
the corresponding CSS property[0].

[0] https://www.w3.org/TR/css-fonts-3/#font-rend-desc

https://gitlab.gnome.org/GNOME/gnome-shell/issues/34
2018-06-08 18:45:07 +02:00
5ac6201d91 test-theme: Fix a comment 2018-06-08 17:39:13 +02:00
a21a22fdb5 appDisplay: Make middle-click like Ctrl+click
When middle-clicking an app icon on the Dash, it will always try to open
a new window of that app, even if the app doesn't support multiple
windows. Meanwhile, Ctrl+click on an app will only open a new window if
the app allows it.

This change prevents middle-clicks on app icons from opening new windows
for apps without multi-window support.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/316
2018-06-07 17:49:36 +00:00
a0fa50ac31 Update Scottish Gaelic translation
(cherry picked from commit 0ac0f7e85b)
2018-06-01 10:36:57 +00:00
b1dd746443 network: Keep key focus in dialog when removing networks
When the actor that has the key focus is destroyed, Clutter moves
the focus to the stage. In case the destroyed actor was inside a
ModalDialog, this breaks any keyboard interaction: keynav is broken
because the stage isn't in any focus chain, and access keys like
Escape because they are handled on the dialog's parent.

The only dialog that may destroy a child without recreating the dialog
buttons (and thus moving the key focus there) is the WirelessDialog,
fix it by keeping the key focus within the dialog when removing networks
from the list.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/76
2018-05-31 11:42:14 +00:00
c15e163eb1 network: Handle networks with no access points
This avoids a couple of warnings when encountering such a network.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/76
2018-05-31 11:42:14 +00:00
7a3927c168 screenshot: Store creation time in metadata
It's useful information, even when we are not using JPEG/Exif - at
least nautilus will show it in its image properties.

https://bugzilla.gnome.org/show_bug.cgi?id=790481
2018-05-31 11:36:27 +00:00
6eed4e31d7 workspace: Fall back to app name in window caption
Just like we did for the window list in app icons' context menu,
provide a fallback for window captions in the window picker rather
than showing blank items to the user.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/26
2018-05-31 11:27:44 +00:00
f0557ea05c appDisplay: Fall back to app name in icon menu
The app icon's context menu contains a list of open windows,
identified by their title. As we currently don't handle the
case where the app didn't set a title, we end up with empty
menu items which looks clearly broken. Fall back to the app's
name in that case.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/26
2018-05-31 11:27:43 +00:00
44894262f4 st-label: Unset clutter text instance on disposal
The instance is owned by the actor (being its child), and thus when the
disposal happens for the parent the text is disposed too, thus it's just
safer to nullify its reference so that we won't try to access to invalid
objects later, and this might be the case since the JS objects could be kept
around until they aren't finalized.

https://bugzilla.gnome.org/show_bug.cgi?id=788931
2018-05-29 02:28:26 +03:00
b03bcc85aa closeDialog: Periodically check for window to become responsive again
The close dialog for non-responding windows is closed automatically
when we detect that the window is responding again. However as we
currently only ping the window in response to certain user actions
(like focusing the window or opening the window menu), this can
easily go undetected.

Address this by periodically pinging the window while the close
dialog is shown.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/298
2018-05-25 18:23:55 +02:00
70057c6a55 closeDialog: Disable unredirection while showing
The dialog won't be visible when unredirection is in place (for example
while a fullscreen window is focused), so disable unredirection while
the dialog is up.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/298
2018-05-25 14:05:29 +00:00
86bd5b281d Bump version to 3.29.2
Update NEWS.
2018-05-24 18:54:29 +02:00
ad3e9ab205 docs: Clarify where style changes should be done
After the move to Gitlab, the gnome-shell-sass repository is more
exposed than it used to; clarify that it is not the place where
style changes should happen, but rather the corresponding subtree
in the gnome-shell repository.
2018-05-23 19:03:01 +02:00
02bbf409ea docs: Use Markdown
Markdown produces nicer output where supported, so use that instead
of plain ASCII formatting.
2018-05-23 19:03:01 +02:00
f56e4e177e docs: Remove old style HACKING
The information is outdated, the relevant documentation is all in
[the README](data/theme/README) nowadays.
2018-05-23 19:01:10 +02:00
fc26559f2c docs: Remove obsolete files
The canonical maintainership information is tracked in the project's
.doap file as for any other GNOME project, and the empty AUTHORS
file only existed to make autotools happy.
2018-05-23 19:01:10 +02:00
fdaddbd1e0 Improve notification documentation
Ref: https://gitlab.gnome.org/GNOME/gnome-shell/issues/294
2018-05-22 18:39:19 +02:00
04f61567ba Update Chinese (China) translation 2018-05-21 14:27:23 +00:00
a0785cdbc1 Update Swedish translation 2018-05-20 17:28:17 +00:00
94101e8bb8 magnifier.js: Fix zoom juddering
Make Zoom respond to the mouse silky-smoothly.

It was previously hard-coded to: 1000/50 = 20 FPS.

https://bugzilla.gnome.org/show_bug.cgi?id=682013
https://launchpad.net/bugs/1691675
2018-05-17 11:42:20 +08:00
f13dbf2f26 Update Galician translation 2018-05-15 22:36:45 +00:00
bae6f06e4e Update Galician translation 2018-05-15 21:58:21 +00:00
d8b9e23502 network: Update the icon in the panel whenever NM's state changes
Similar to what it's done when the main connection changes, we need
to make sure that the icon in the panel gets updated before calling
_syncConnectivity(), so that the icon gets always updated if needed,
regardless of whether there's an active connection or not.

This is needed because there's at least one case when an icon should
be shown when the computer is not connected to any network: when a
hotspot has been enabled, which can be useful even if there's not
an internet connection to share (e.g. to easily allow connecting
other devices to the computer.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/214
2018-05-15 09:15:43 +01:00
7d59eaa67e Update Indonesian translation 2018-05-12 03:59:42 +00:00
c0a453f64f networkAgent: Fix fallout from libnm port
While the libnm-glib version of the function returns a GByteArray*
that gjs can directly cast to the required gutf8*, the libnm function
returns GBytes* from which we need to explicitly fetch the data.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/136
2018-05-09 16:19:58 +02:00
5336175736 osdWindow: Fix blurriness at certain resolutions
The y position wasn't rounded, leading to some blurriness at vertical
resolutions that aren't a multiple of 4 (e.g. 1050).

https://bugzilla.gnome.org/show_bug.cgi?id=782011
2018-05-08 21:04:02 +02:00
2997e4950b keyboardManager: take group index into account when preserving keymap
commit 642107a2 attempts to avoid resetting the current keymap on
spurious input source changes.

It does this by checking if the current layout id is found in
the new list of layouts and resetting the current layout to the
associated match in the list. By not nullifying the current
layout, it won't get subsequently reset.

Unfortunately, if the order of the list changes, resetting the
current keymap is still necessary, since the order corresponds
with the index of the activated group.

This commit changes the code to nullify the current layout if
its group index changes.

https://bugzilla.redhat.com/show_bug.cgi?id=1573923
2018-05-08 17:54:37 +00:00
a49fb90d86 build: Include Cally in St introspection
CallyActor is exposed indirectly via StAccessible's parent type,
so add the dependency to shut up a gjs warning.

https://bugzilla.gnome.org/show_bug.cgi?id=781471
2018-05-07 21:10:40 +00:00
ffc0eb1de2 remoteSearch: Actually return icons
Since commit 3b1330880f, a remote search result's createIcon() method
no longer returns the created icon, whoops ...

https://gitlab.gnome.org/GNOME/gnome-shell/issues/249
2018-05-03 08:22:58 +00:00
853c81eb62 Update Brazilian Portuguese translation
(cherry picked from commit e909db5848)
2018-05-02 18:47:03 +00:00
594cc7cbef workspaceThumbnails: Avoid access to undefined variables
If thumbnails haven't been created, they don't need to be destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=787871
2018-05-02 20:04:42 +02:00
0932324d39 calendar-server: Update views only after the time range is set
The gnome-shell-calendar-server calls to refresh queries even when it
has no time range set, which results in:
  a) waste of resources (for example after login),
  b) many runtime warnings in the journalctl log, related to
     incorrect time range being used.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/244
2018-05-02 16:10:33 +02:00
2d6cf236c4 perf-tool: Fix default value for --extra-filter
While it is theoretically fine to run --perf=hwtest without passing --hwtest,
the test will hang in this case because it fails to start gedit. Always append
Gedit to the default value for --extra-filter when running the "hwtest" test
to make it work fine without --hwtest.
2018-04-29 16:15:16 +00:00
642107a28f keyboardManager: Preserve current keymap across reloads
The IM can pretty much update the input sources anytime (even if
to set the same ones). That ends up triggering rebuilding all user
defined keymaps, and losing modifier state if we are unfortunate
enough that this caught us while pressing one.

One common situation seems to be password entries, resulting in
the wrong character being printed if the first character happens
to require the shift key.

If the current keymap is not found in the newly loaded list,
this._current will end up null, with the same behavior as we get
currently (immediate keymap reload).

https://bugzilla.redhat.com/show_bug.cgi?id=1569211

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

Closes: #240
2018-04-29 17:46:31 +02:00
581b38ecf4 scripting: Fix argument list of createTestWindow()
Commit f285f2c6 changed Scripting.createTestWindow() to accept a parameter
object instead of a parameter list but forgot to remove the width and height
arguments. This breaks the "core" test as all windows are created with default
settings.
2018-04-25 23:47:06 +02:00
fbc03cc262 Bump version to 3.29.1
Update NEWS.
2018-04-25 20:34:05 +02:00
a6ff195893 Updated Spanish translation 2018-04-25 13:16:18 +02:00
f411724064 Updated Czech translation 2018-04-24 17:33:14 +02:00
39f43a4cd4 Update Friulian translation 2018-04-23 19:42:08 +00:00
c82cb918ae network: initialize the agent asynchronously
This also bumps the NM requirement. We actually already use API from
1.0, but regularly hit various NetworkManager bugs with versions prior
to 1.10.2. 1.10.4 fixes the asynchronous agent initialization.

https://bugzilla.gnome.org/show_bug.cgi?id=789811
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/63
2018-04-23 10:45:20 +02:00
38cdaa6c20 Update Romanian translation 2018-04-22 16:48:18 +00:00
0327069e83 polkitAgent: Guard against repeated close() calls
We use the close() method to disconnect signal handlers set up in
init(), however the handler ID is only valid in the first call in
case the method is called more than once.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/221
2018-04-21 18:42:15 +02:00
7601b029c8 Updated Slovenian translation 2018-04-20 21:59:35 +02:00
fb509dfc25 thunderbolt: sync D-Bus API with bolt changes
bolt 0.3 deprecated all AUTHORIZED_XXX status flags, but added
a CONNECTING one. Also AuthFlags got renamed to AuthCtrl.
2018-04-20 11:36:37 +02:00
874a91968f thunderbolt: remove gdbus error prefix, if present
If we get an error during device enrollment, the message might be
prefixed to indicate that the error came from the remote peer. We
are presenting that message to the user so strip that prefix away
if it was there.
2018-04-20 11:36:37 +02:00
0963ccddba thunderbolt: fix enroll-failed signal args order
The devices emitted (device, error) while the connected handler
was expecting (error, device). The former is more consistent
with the rest of the code (so change it to device, error).
2018-04-20 11:27:11 +02:00
c4e0f6df08 Update Russian translation
(cherry picked from commit 0d031dc20f)
2018-04-19 20:33:21 +00:00
58aafe9520 theme: Improve look of login user-list
* Remove tiny padding of user-list
* Less space between avatar and username
* Apply the 1em padding only to the user-widget, not the timed-login-indicator
2018-04-19 17:26:14 +02:00
a46df7f8ec theme: Use a padding of 6px on the user-list items according to HIG 2018-04-19 17:26:14 +02:00
1dd16618d1 loginDialog: Don't display timed login indicator if unused
This fixes the slightly bigger padding underneath the login item compared to the padding above
2018-04-19 17:26:14 +02:00
a4190f83ac loginDialog: Correct source name for timed login idle timeout
The _blockTimedLoginUntilIdle method sets a timeout to be called after
the user is idle for 5 seconds.  That timeout is erroneously given the
source name "[gnome-shell] this._timedLoginAnimationTime" which looks
like a copy-and-paste mistake.  The original intention was probably to
use a source name of "[gnome-shell] this._timedLoginIdleTimeOutId" which
more closely matches existing convention for source names.

This commit fixes that.
2018-04-19 17:26:14 +02:00
a8e17f73ec loginDialog: Use more function scope variables inside _startTimedLogin
Using function scope variables increases readability and prevents
unwanted changes from outside while the batch is running.
2018-04-19 17:26:13 +02:00
86a741c1ee loginDialog: Make sure timed login indicator is shown after idle timeout
If the idle timeout is done, always show the user list to make sure the
timed login indicator is visible.
2018-04-19 17:25:02 +02:00
5cc6fef689 loginDialog: Restrict grabbing of focus while timed login is running
Make sure the focus isn't grabbed right after user interaction starts a
new timed login. Only grab it after the idle timeout is done and on the
first run instead.
2018-04-19 09:08:45 +02:00
522a5fe480 loginDialog: Ensure old timed login timeout is removed before starting a new one
Normally, we give the user a 5 second grace period of inactivity before
starting a timed login operation. Unfortunately, that grace period
timeout isn't properly removed if the timed login operation is restarted
during the grace period. That means the timeout handler can
inadvertently get called multiple times leading to the grace period
duration getting subtracted from the total animation time more than
once.

This commit ensures we only ever have one grace period timeout scheduled
at a time.
2018-04-19 09:08:45 +02:00
b1239b1257 loginDialog: Use GLib instead of Mainloop for timeout
imports.mainloop is deprecated
2018-04-19 09:08:45 +02:00
58063d9ee1 loginDialog: Move reset of timed login into _startTimedLogin
This way we can make sure that already running timed logins are
always reset when starting a new one.
2018-04-19 09:08:45 +02:00
d7aba2dece loginDialog: Ensure timed login indicator is hidden on key presses
The timed login feature currently cancels the timed login operation when
a user presses a key but, oddly, only hides the indicator when the user
releases the key. This means that if a user holds down a key that
doesn't key repeat, the timed login indicator will continue to run after
the timed login operation is cancelled.

This commit address the problem by ensuring the timed login indicator is
hidden on any key press event, at the same time the timed login
operation is canceled.
2018-04-19 09:08:45 +02:00
35fced27df ibusCandidatePopup: Fix candidate-clicked signal 2018-04-18 13:37:53 +09:00
be76b19300 st-entry: Set text-related CSS properties on the internal ClutterText
Call _st_set_text_from_style() when updating the entry's style, so
that CSS style properties such as text-decoration or letter-spacing
are applied over the internal ClutterText instance.
2018-04-18 00:14:05 +00:00
376d696b8b st-private: Add support for letter-spacing in ClutterText based StWidgets
Add support in _st_set_text_from_style(), so that this CSS property can
be used from any StWidget holding an internal ClutterText.
2018-04-18 00:14:05 +00:00
695d61968d st-theme-node: Add new getter st_theme_node_get_letter_spacing
This will be used by ClutterText-backed StWidgets to update their
list of PangoAttributes according to the letter-spacing property.
2018-04-18 00:14:04 +00:00
d6d09fd3c8 ui: Theme lookup should respect XDG_DATA_DIRS
Modes, extensions and other GNOME Shell assets are searched in appropriate
subdirectories of each directory in XDG_DATA_DIRS, falling back
to global.datadir.
However, this isn't the case for themes, which are currently always expected
in global.datadir, even when referenced by a mode in a different XDG_DATA_DIR.

The fix is to have the theme finding pattern follow the same logic as other
elements.
Fixes #167.
2018-04-16 19:09:14 +02:00
f1b1501f9b Update Croatian translation 2018-04-16 12:31:09 +00:00
cdbc99e992 popupMenu: Fix wrong call to clutter_actor_add_child()
Specify the horizontal alignment via the x_align property when creating
the StIcon, since this function expects one argument, not two.
2018-04-16 11:40:04 +00:00
69afe7785d remoteMenu: Support icons in app-menu
The HIG discourages the use of icons in menus except for "noun" items
(files, bookmarks, ...). While those should be rarely used in the
application menu, it still makes sense to support them in the few
cases where they are used.

https://bugzilla.gnome.org/show_bug.cgi?id=760985
2018-04-14 09:02:20 +00:00
b99e304f1e workspaceThumbnail: initialize porthole based on workArea
https://bugzilla.gnome.org/show_bug.cgi?id=792687
2018-04-13 16:59:51 -05:00
c29bd46e7a workspaceThumbnail: rebuild thumbnails if workareas size changed
https://bugzilla.gnome.org/show_bug.cgi?id=792687
2018-04-13 16:58:28 -05:00
5fcf40b973 workspaceThumbnail: only update _porthole if the overview is visible
Otherwise it happens that porthole is computed again after that the
overlay is hidden (triggered by a layout reallocation) and thus not
regenerated again afterwards.

https://bugzilla.gnome.org/show_bug.cgi?id=792687
2018-04-13 16:53:18 -05:00
a198dfe3d8 thunderbolt: capitalize Thunderbolt in a translatable string 2018-04-13 21:52:32 +02:00
5b10d157fe Bump version to 3.28.1
Update NEWS.
2018-04-13 20:18:05 +02:00
5cc42b18b0 utils: Simplify URL regex to only support one layer of parentheses
The author of the original URL-matching regex warns[0] that the pattern may
cause certain regex engines to lock up with certain input, namely patterns
that contain parentheses. It turns out SpiderMonkey is affected, but rather
than switching to the author's improved version (that is still crazy), sim-
plify the pattern a bit by removing support for nested parentheses in URLs.
Even a single pair of parentheses is extremely rare, so this is unlikely to
make a noticeable difference (other than not locking up SpiderMonkey of
course) ...

[0] http://daringfireball.net/2010/07/improved_regex_for_matching_urls
2018-04-13 18:15:44 +00:00
cb4252e888 polkitAgent: Hide authentication dialogs while locked
Since commit 78a92fb6be we no longer pop up authentication dialogs
on the lock screen, however any dialog that is already open at that
time remains open. This is unexpected, so hide the dialog until
the screen is unlocked again.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/166
2018-04-13 19:35:31 +02:00
09d3cdb023 workspace: Don't move focus unconditionally
Since commit 1939e22c22, we move the keyboard focus with the hover
highlight. However while this makes sense when interacting with
the window picker, it interferes with keyboard navigation of other
components like dash or top bar. Address this by only moving the
focus when the previous focus was already inside the window picker
or unset.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/50
2018-04-13 14:13:35 +00:00
71515a8a11 networkAgent: Use libnm for plugin loading
After the networking code has been ported to libnm, we can use its
API for loading VPN plugins instead of rolling our own ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/39
2018-04-13 14:04:55 +00:00
11ca8dd54f worldClock: Handle named timezones
The original UTC support in GWeather piggy-backed on the existing API, but
as "country" or "city" don't make sense in the context of UTC or AoE, the
concept of "named timezones" was introduced. Handle those explicitly to get
back labels for those locations.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/150
2018-04-13 09:15:48 +00:00
e00f22ebe6 overview: Use monotonic time to check for consecutive activations
We don't toggle the overview if the request happens too close to the
last activation, to filter out double-clicks or activation by both
the hot corner and a click. However as the check is based on the
real time, the check breaks if the system clock moves backwards and
the last activations appears to be in the future. Fix this by using
monotonic time which is guaranteed to only move forward.

https://bugzilla.gnome.org/show_bug.cgi?id=763886
2018-04-13 09:13:45 +00:00
13390543b0 Update Russian translation 2018-04-12 13:58:31 +00:00
de95ced92c Update Russian translation 2018-04-12 11:47:00 +00:00
f6a08472a0 st: Do not force allocation updates during shadow creation
If an actor is pending a relayout when get_allocation_box() is called,
the method forces an allocation update. In case of StWidget, this might
then result in a style update and a consecutive invalidation of the
shadow spec.

A helper method that invalidates one of its parameters as a side effect
(and by extension its return value as well) is most unexpected, so cur-
rently _st_create_shadow_pipeline_from_actor() poses an easy trap to
callers to run into.

Remove that trap by calling get_size()/get_position() instead, which
don't have the unintended side effect - it is still a good idea to fix
callers who were running into this to not waste resources on creating
shadows that are invalidated before the next paint, but throwing un-
defined behavior at them is harsh ...

https://bugzilla.gnome.org/show_bug.cgi?id=788908
2018-04-11 19:29:25 +00:00
9f7b101437 appFavorites: Add evolution to rename list
Evolution 3.28 changed the desktop filename. Without this patch,
evolution will disappear from the dock.
2018-04-10 14:38:26 +00:00
9c0707d4dc build: Run postinstall script where necessary
Package managers usually take care of compiling GSettings schemas and
updating the .desktop database on installation, but when building
manually from source, we should perform the aforementioned actions
ourselves.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/127
2018-04-09 19:19:33 +00:00
78a92fb6be polkitAgent: Queue authentication requests while locked
While polkit requests *should* be the result of a user action, that's
not always the case in practice and authentication dialogs can pop up
out of nowhere at any time. That's always annoying, but particularly
bad on the lock screen. If we disabled the polkit component altogether,
the fallback GTK-based agent would kick in, so instead handle the case
explicitly and postpone showing the dialog until the session is unlocked.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/179
2018-04-06 20:08:29 +02:00
01509cf1a5 appFavorites: Rename gnome-tweaks.desktop 2018-04-05 22:06:15 -04:00
61e9f51274 system: Align submenu labels with parent - adjust for deeper hierarchies
Adjust the previous commit which applied the alignment to :first-child
descendants, instead of only immediate children. This fixes alignment
issues for a number of Shell extensions by making it easier to override
with a .popup-menu-item style-subclass.
2018-04-02 14:54:43 -07:00
201bd9d42e Update French translation 2018-03-27 12:26:10 +00:00
8a78f08f6c Update Arabic translation 2018-03-25 22:22:06 +02:00
a5e54f9712 Update Dutch translation 2018-03-23 09:12:25 +00:00
526834e39b modalDialog: Remove some unused code
No need to figure out an x_alignment variable that hasn't been used
since commit 0722c06275 ...
2018-03-21 16:48:56 +00:00
bdde2476d2 Added Slovenian translation 2018-03-20 22:37:08 +01:00
3171f9debe Update zh_CN translation 2018-03-20 17:03:11 +08:00
0e2aeac5f9 build: Bump required glib version
Required by 723c49a8

Thanks Marcus Lundblad for identifying this issue.
2018-03-19 16:49:47 -04:00
788fb5547c Update Dutch translation 2018-03-18 10:35:18 +00:00
c4d2c0ee64 Update Brazilian Portuguese translation 2018-03-16 22:42:50 +00:00
977686a77a Update Slovak translation 2018-03-16 21:34:03 +00:00
44b29f210c Update Romanian translation 2018-03-15 18:37:20 +00:00
36c7d65ccf inputMethod: Pass all key events through the current IM method
Even though we are using an "xkb" source, it still makes sense to
pass the event through the IBus simple engine, in order to let it
handle compose keys and ctrl+shift+[u|e].

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

Closes: #115
2018-03-15 16:09:38 +01:00
b81d24fdb4 Update Russian translation 2018-03-14 19:59:53 +00:00
bfdbee8115 shellEntry: Use correct enum for input purpose hints
This was mistakenly left using the GTK+ counterparts. Luckily the enums
are binary compatible, but oops.
2018-03-14 13:30:47 +00:00
4a17c8f4a9 shell-global: Do not deal with allocated strings as const char
The imagedir and userdatadir variables are not fetched from
constants/environment but created with g_strdup*/g_build*. Acknowledge that
and also free the strings in finalize.
2018-03-14 13:30:47 +00:00
d4f67a7d42 Bump version to 3.28.0
Update NEWS.
2018-03-12 12:17:03 +01:00
d5769ae409 Update Hungarian translation 2018-03-12 06:02:34 +00:00
f356b61e5a Update Swedish translation 2018-03-11 20:36:26 +00:00
398768dcbd Update Catalan translation 2018-03-10 21:30:17 +01:00
272d5b6e4a Update Chinese (Taiwan) translation 2018-03-10 12:31:16 +00:00
a479aa2594 Update Croatian translation 2018-03-07 21:47:09 +00:00
f48d620ac5 Update Punjabi translation 2018-03-07 11:57:04 +00:00
0684b42f67 Bump version to 3.27.92
Update NEWS.
2018-03-05 23:29:38 +01:00
190a31dd5f thunderbolt: honor boltd's AuthMode property
boltd 0.2 gained a property that indicates if it is authorizing
devices or not. If it indeed is not authorizing then we wont
try to enroll new devices because that would otherwise lead to
and error.
2018-03-05 22:03:28 +01:00
cccfc7faca thunderbolt: adapt to bolt 0.2 interface changes
All enums are now strings on the bus. Also the Device.Security
property is gnome. Some new properties got added instead.
2018-03-05 22:03:11 +01:00
5e9e4f8c73 viewSelector: Don't mark synth event as in capture phase
When we move keyboard focus to the search entry, we replay the key press
that triggered the move to the entry using ClutterActor's event() method.
Since commit 3b293e91e we specify that the event is in the capture phase
to make it work with StIMText, but now that commit 83accce24 removed it,
we have to return to the expected non-capture flag that matches the orig-
inal event to unbreak find-as-you-type functionality.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/72
2018-03-05 19:12:59 +00:00
b28e48094b viewSelector: Don't duplicate find-as-you-type in captured-event
Find-as-you type was never automatically handled by StIMText, but
by the existing stage key-press handler. The functionality broke
for a different reason, we will fix it after reverting the recent
captured-event changes.

This reverts commits bc4462cd0c and e4ee944d8d.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/72
2018-03-05 19:12:58 +00:00
01bad21704 Updated Danish translation 2018-03-05 15:55:14 +01:00
aab9a20b6a Update Russian translation 2018-03-05 12:46:50 +00:00
201c5b23f3 Update Latvian translation 2018-03-04 18:09:02 +00:00
b79e11bef8 Update French translation 2018-03-03 10:21:59 +00:00
81dfcb85ca messageList: Fix invisible close buttons still working
Since commit c4f2bb5f, close buttons are hidden by making them fully
transparent rather than setting their visibility to false to keep
the overall message layout stable. As a result, the buttons now work
even when invisible, which is clearly unexpected - fix this by updating
the reactive property appropriately.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/66
2018-03-02 19:59:48 +00:00
c8e69a2154 menutracker: Fix a small memory leak
https://gitlab.gnome.org/GNOME/gnome-shell/issues/64
2018-03-02 19:43:45 +00:00
3ee50adad9 Updated Lithuanian translation 2018-02-28 23:40:44 +02:00
d1386ee8e4 Update Dutch translation 2018-02-26 21:31:44 +00:00
6b994602d5 Updated Czech translation 2018-02-26 18:05:31 +01:00
00039bbb47 Updated Czech translation 2018-02-26 18:00:00 +01:00
0195b2f7c0 Update Scottish Gaelic translation
(cherry picked from commit 4d598b3294)
2018-02-26 12:56:36 +00:00
adc60f3212 Update Scottish Gaelic translation
(cherry picked from commit e1b9babac5)
2018-02-26 12:50:19 +00:00
579f59816f Update Italian translation 2018-02-26 08:09:42 +00:00
9e0df3c5c6 Updated Vietnamese translation
Signed-off-by: Trần Ngọc Quân <vnwildman@gmail.com>
2018-02-26 07:30:59 +07:00
c6b14ef97e Update Hungarian translation 2018-02-25 19:54:54 +00:00
59e535244f Update Turkish translation 2018-02-25 15:49:46 +00:00
720b9dd3d2 Update Korean translation 2018-02-25 14:48:41 +00:00
60df5b4381 Update Slovak translation 2018-02-24 17:09:59 +00:00
94a4dc4576 Update Chinese (Taiwan) translation 2018-02-24 13:18:53 +00:00
dbda223858 Update German translation 2018-02-23 15:06:44 +00:00
822875d5c3 Update Spanish translation 2018-02-23 07:27:14 +00:00
b11b28b83b Updated Spanish translation 2018-02-22 10:19:35 +01:00
ea0770ae22 build: Bump mutter API version
The API number was updated, let's keep up.
2018-02-21 19:05:49 +01:00
bdc9f293be Bump version to 3.27.91
Update NEWS.
2018-02-21 17:56:00 +01:00
922d73a09b Revert "build: Bump mutter API version"
Mutter only bumped the API version after 3.27.91 was released, so
don't require it for gnome-shell's 3.27.91 release.
2018-02-21 17:56:00 +01:00
46292fbdc5 build: Bump mutter API version
The API number was updated, let's keep up.
2018-02-21 23:49:11 +08:00
3b1330880f cleanup: Use Function.prototype.bind()
When not using arrow notation with anonymous functions, we use Lang.bind()
to bind `this` to named callbacks. However since ES5, this functionality
is already provided by Function.prototype.bind() - in fact, Lang.bind()
itself uses it when no extra arguments are specified. Just use the built-in
function directly where possible, and use arrow notation in the few places
where we pass additional arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/23
2018-02-21 13:55:02 +00:00
213e38c2ef cleanup: Use arrow notation for anonymous functions
Arrow notation is great, use it consistently through-out the code base
to bind `this` to anonymous functions, replacing the more overbose
Lang.bind(this, function() {}).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/23
2018-02-21 13:55:00 +00:00
76f09b1e49 cleanup: Use method syntax
Modern javascript has a short-hand for function properties, embrace
it for better readability and to prepare for an eventual port to
ES6 classes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/23
2018-02-21 13:54:58 +00:00
cff0b81f32 tests: Set calendar event source
Ever since commit e9e30138bd (2011!), the calendar only initialized
the header at construction time. Set an event source to trigger an
update of the content area, which is what the test is mainly intended
for.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:52 +01:00
23d6c4dcc0 tests: Fix import error in calendar
The Calendar module requires C_ at import time, which is only
available after Environment.init() has been called.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:37 +01:00
66c86109dd tests: Fix a warning
Gjs now warns about excess parameters passed to functions, so don't
use Gtk.main_quit directly as signal callback.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:30 +01:00
2e45be96b6 tests: Replace "for each" construct
It is no longer supported by recent mozjs versions, so replace it with
a regular for loop to unbreak the tests.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:22 +01:00
5d1626aba1 tests: Avoid redeclarations with let
Mozjs made this error fatal a while ago, so those tests were broken
by gjs' JS engine updates.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:09 +01:00
b7f083b1da tests: Fix gnome-shell theme import
The current import rule fails in two ways:
 - commit c62e7a6a moved the theme's stylesheet to the builddir
 - since commit 49c4ba56, assets are addressed as resource:// URIs

Fix both issues by loading and referencing the theme resource instead
of the stylesheet itself.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/38
2018-02-21 14:30:00 +01:00
2bce1f1510 keyboard: Fix a warning
imports.misc.ibusManager.IBus is declared as const, so referencing it
from another module triggers a warning with recent mozjs. As of commit
083d11a032 IBus is mandatory, so just make it a regular import to avoid
the warning.
2018-02-21 13:19:15 +01:00
1683f4953e Update Serbian translation 2018-02-21 09:51:44 +00:00
1b2c67a726 Remove po/Makevars
Meson doesn’t use it, and Damned Lies learned to read po/meson.build.
2018-02-21 00:02:41 +01:00
e1d9bdbbd6 loginDialog: only emit session-activated on user action
Right now we emit session-activated any time the bullet
moves in the session menu. That includes at startup when
picking an item arbitrarily, and any time GDM reports the
session was read from the user's account settings.

session-activated informs GDM about the newly selected session,
so emitting it in response to GDM reporting a session is a
bad idea.

This commit changes the code to only emit session-activated when
the user explicitly activates a session item from the gear menu.

Note, we no longer set the active session explicitly at start up.
This is a good thing since the item we were picking wasn't
necessarily correct.  It does means if GDM fails to inform us
about the correct default session we'll now show no bullet instead
of a bullet on the wrong item.

https://bugzilla.gnome.org/show_bug.cgi?id=740142
2018-02-20 10:27:08 -05:00
58827ba36d gdm: use password authentication if all schemes are disabled
This prevents a traceback, at least.
2018-02-20 10:21:23 -05:00
9ef1bc7273 gdm: honor timed login delay even if animations disabled
gnome-shell currently initiates an automatic login attempt if
timed login is enabled and the timed login animation completes.

Unfortunately, if animations are disabled (as is the case for
virtual machines) then the timed login animation will complete
instantly, and timed login will proceed immediately after gnome-shell
has noticed the user is idle for 5 seconds.

This commit addresses that problem by initiating timed login and the
animation from a main loop timeout, instead of using the tweener api.
2018-02-20 10:18:18 -05:00
a347ed9912 build: Minor cleanups
find_program() defaults to require the program in question, and as
failing to locate it is now fatal, there's no longer a need for
checking whether it was found later.

Spotted by Michael Catanzaro.
2018-02-20 11:09:40 +01:00
99d32d2add Update Serbian Latin translation 2018-02-20 10:02:15 +00:00
2d03e1974a Update Serbian translation 2018-02-20 10:01:08 +00:00
07cae5377a theme: use cantarell light
- lock screen
- date in the calendar popover

fixes issue #45
2018-02-20 09:19:09 +00:00
436cac4134 theme: use cantarell light
- lock screen
- date in the calendar popover

fixes issue #45
2018-02-20 09:19:09 +00:00
117fcc9743 Update Friulian translation 2018-02-19 12:41:20 +00:00
6d969250ca Update British English translation 2018-02-18 10:45:31 +00:00
d68d1d1371 Update Catalan translation 2018-02-18 08:19:38 +00:00
7d8b9b257a Update Kazakh translation 2018-02-18 04:11:37 +00:00
f237e42737 Update Croatian translation 2018-02-17 00:04:56 +00:00
ca095acd34 theme: Update OSK theme
Enter/shift/layout/hide buttons have been made to use our own assets, key
labels have been made slightly bigger, and incorrect padding has been
removed from the extended keys popovers.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 21:30:54 +01:00
630c70f13c keyboard: Set 'latched' pseudo-class on latched shift key
This is pseudo-class is added on .shift-key-uppercase whenever the shift
state is latched, a matching selector would be:
.keyboard-key.shift-key-uppercase:latched {}

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:48 +01:00
ebb39bcbe2 keyboard: Delegate enter/shift/layout/hide buttons style to theming
Drop the UTF8 glyphs from those, and add style classes so those can be
specifically themed and given a background image. The style classes are:
.keyboard-key.enter-key{}
.keyboard-key.shift-key-lowercase{} /* applies while lowercase */
.keyboard-key.shift-key-uppercase{} /* applies while uppercase */
.keyboard-key.layout-key{}
.keyboard-key.hide-key{}

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:45 +01:00
9cf2ec8bd2 keyboard: Avoid using key.label for anything else than presentation
Do the finicky checks to adjust key widths and whatnot based on other
values than the label. This makes the label exclusively used for
presentation (i.e. setting up a St.Label).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:41 +01:00
5f6745cad0 keyboard: Shift key shouldn't latch the state unless long pressed
Instead of latching all states, make shift unlatched by default, and only
latched when making a long press on the key. When not latched, the keyboard
will switch to the first level (alphabetic lowercase) after the first key
press.

Also, move the actual level switch to Key::pressed, so it feels more
reactive on long press.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:36 +01:00
d8fd7b5a44 keyboard: Implement Key object 'long-press' signal
This signal may be emitted on any key, regardless of extended keys, so
make the timeout useful for both situations.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:32 +01:00
f8abe073eb keyboard: Remove needless function
It boils down to another function call, and has a single caller. Just let
the caller make _setActiveLayer() directly.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:29 +01:00
0608413b96 keyboard: Do key presses on actual key press
It was mistakenly connecting twice to the 'released' signal. Also, move
level changes to key release, since it will be more convenient to hook
latched states on long press.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/46
2018-02-15 19:36:03 +01:00
7f8a1ec1fb keyboard: make Key objects' topmost actor to be this.actor
These objects created this.actor being the St.Button, and a surrounding
this.container actor that is the actual actor callers care about. Turn this
around and make this.actor be the parent-less actor, and this.keyButton the
contained internal button. This is more consistent with gnome-shell style.
2018-02-12 17:00:51 +01:00
e859fc8f16 keyboard: Do not call non-existent function
Commit 8fdf47ea5b removed _addKeys(), but forgot one caller. We just want
to regenerate the keyboard for the current group, so call into the
_onGroupChanged function.
2018-02-12 17:00:51 +01:00
2f9b0f8820 Update Brazilian Portuguese translation 2018-02-12 13:49:03 +00:00
d66fcb60b1 Update Indonesian translation 2018-02-10 15:05:17 +00:00
2937cd7e77 Update Turkish translation 2018-02-10 08:16:39 +00:00
c62e7a6a82 build: Make sassc mandatory and always generate CSS files from Sass sources
The previous implementation of the CSS generation logic considered sassc
an optional dependency and made sure for that reason that the result CSS
files ended up in the source directory, so that they could be checked
in and kept in sync with the source sass files.

As we are making sassc a required dependency, we can now stop doing that
extra work and simply rely on the CSS files being automatically generated
each time the sass sources change. By doing this, we can now effectively
get rid of the CSS files checked in the repo as well as of the parse_sass.sh
script, since the CSS files will now live on the build directory only.

https://bugzilla.gnome.org/show_bug.cgi?id=792822
2018-02-10 07:54:40 +00:00
92f1aec3dd appDisplay: Fix small app folder icons when using HIDPI
While the scale factor is taken into account for app icons, we set
an explicit size when combining the into a folder icon - unless we
take the factor into account, the result will be too small on HiDPI
displays.

https://bugzilla.gnome.org/show_bug.cgi?id=792259
2018-02-10 00:40:48 +00:00
bc4462cd0c viewSelector: Avoid stealing focus from other entries into overview entry
The captured-event handler just redirects focus there on the first keypress,
what it doesn't account for is that other entries may be active while the
Activities overview is opened (eg. alt-f2, or other modal dialogs). Play
along with other entries, and make it only steal focus if no other entry
is selected.

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

Closes: #33
2018-02-10 00:03:11 +00:00
1ce5ed8685 Update Brazilian Portuguese translation 2018-02-09 23:57:38 +00:00
433b28b223 Update Friulian translation 2018-02-09 23:36:06 +00:00
3fe45e29e4 theme: Replace gnome-shell-sass submodule with subtree
As the style has grown bigger and more complex, generating the different
variants from a common source has been a good decision. However given how
intertwined the theme is with gnome-shell itself, relying on a submodule
has proven to be quite painful. And as things stand right now, it is going
to get worse:

 - using either pre-generated CSS or generating it at build time is
   odd, and violates meson's strict separation between source- and
   build directories; we are therefore considering dropping the CSS
   and depending on sassc to always generate it at build time

 - with the migration to gitlab, our workflow shifts decisively towards
   branches; however there is no support in either git or gitlab for
   handling two brances of separate repositories consecutively, which
   gets particularly awkward for branches in a private namespace

With those pain points in mind, we will adjust our setup as follows:

 - remove the submodule from gnome-shell and instead import the
   sass as subtree

 - after that, the sass sources can be changed like any other files
   in the repository, and regular contributors can forget that there
   was ever anything special about them

 - whenever we want to update the classic style, we can push the subtree
   changes and bump gnome-shell-extension's sass submodule

In other words: Updating the classic styling will become slightly more
painful, but not much and only for me; in return, everyone else can
stop fiddling with submodules (and buy me a beer).
2018-02-09 21:45:09 +00:00
259 changed files with 29020 additions and 22638 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "data/theme/gnome-shell-sass"]
path = data/theme/gnome-shell-sass
url = https://git.gnome.org/browse/gnome-shell-sass
[submodule "subprojects/gvc"]
path = subprojects/gvc
url = https://git.gnome.org/browse/libgnome-volume-control

View File

@ -1,19 +1,16 @@
Coding guide
============
# Coding guide
Our goal is to have all JavaScript code in GNOME follow a consistent style. In
a dynamic language like JavaScript, it is essential to be rigorous about style
(and unit tests), or you rapidly end up with a spaghetti-code mess.
A quick note
------------
## A quick note
Life isn't fun if you can't break the rules. If a rule seems unnecessarily
restrictive while you're coding, ignore it, and let the patch reviewer decide
what to do.
Indentation and whitespace
--------------------------
## Indentation and whitespace
Use four-space indents. Braces are on the same line as their associated
statements. You should only omit braces if *both* sides of the statement are
@ -22,7 +19,7 @@ on one line.
* One space after the `function` keyword. No space between the function name
* in a declaration or a call. One space before the parens in the `if`
* statements, or `while`, or `for` loops.
```javascript
function foo(a, b) {
let bar;
@ -39,22 +36,20 @@ on one line.
print(20);
}
}
```
Semicolons
----------
## Semicolons
JavaScript allows omitting semicolons at the end of lines, but don't. Always
end statements with a semicolon.
js2-mode
--------
## js2-mode
If using Emacs, do not use js2-mode. It is outdated and hasn't worked for a
while. emacs now has a built-in JavaScript mode, js-mode, based on
espresso-mode. It is the de facto emacs mode for JavaScript.
File naming and creation
------------------------
## File naming and creation
For JavaScript files, use lowerCamelCase-style names, with a `.js` extension.
@ -67,14 +62,13 @@ library name followed by a dash, e.g. `shell-app-system.c`. Create a
`-private.h` header when you want to share code internally in the
library. These headers are not installed, distributed or introspected.
Imports
-------
## Imports
Use UpperCamelCase when importing modules to distinguish them from ordinary
variables, e.g.
```javascript
const GLib = imports.gi.GLib;
```
Imports should be categorized into one of two places. The top-most import block
should contain only "environment imports". These are either modules from
gobject-introspection or modules added by gjs itself.
@ -85,7 +79,7 @@ e.g. `imports.ui.popupMenu`.
Each import block should be sorted alphabetically. Don't import modules you
don't use.
```javascript
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
@ -95,23 +89,22 @@ don't use.
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
```
The alphabetical ordering should be done independently of the location of the
location. Never reference `imports` in actual code.
Constants
---------
## Constants
We use CONSTANTS_CASE to define constants. All constants should be directly
under the imports:
```javascript
const MY_DBUS_INTERFACE = 'org.my.Interface';
```
Variable declaration
--------------------
## Variable declaration
Always use either `const` or `let` when defining a variable.
```javascript
// Iterating over an array
for (let i = 0; i < arr.length; ++i) {
let item = arr[i];
@ -121,31 +114,32 @@ Always use either `const` or `let` when defining a variable.
for (let prop in someobj) {
...
}
```
If you use "var" then the variable is added to function scope, not block scope.
See [What's new in JavaScript 1.7](https://developer.mozilla.org/en/JavaScript/New_in_JavaScript/1.7#Block_scope_with_let_%28Merge_into_let_Statement%29)
Classes
-------
## Classes
There are many approaches to classes in JavaScript. We use our own class framework
(sigh), which is built in gjs. The advantage is that it supports inheriting from
GObjects, although this feature isn't used very often in the Shell itself.
```javascript
var IconLabelMenuItem = new Lang.Class({
Name: 'IconLabelMenuItem',
Extends: PopupMenu.PopupMenuBaseItem,
_init: function(icon, label) {
_init(icon, label) {
this.parent({ reactive: false });
this.actor.add_child(icon);
this.actor.add_child(label);
},
open: function() {
open() {
log("menu opened!");
}
});
```
* 'Name' is required. 'Extends' is optional. If you leave it out, you will
automatically inherit from Object.
@ -162,35 +156,34 @@ GObjects, although this feature isn't used very often in the Shell itself.
still a giant function call, even though it may resemble a more
conventional syntax.
GObject Introspection
---------------------
## GObject Introspection
GObject Introspection is a powerful feature that allows us to have native
bindings for almost any library built around GObject. If a library requires
you to inherit from a type to use it, you can do so:
```javascript
var MyClutterActor = new Lang.Class({
Name: 'MyClutterActor',
Extends: Clutter.Actor,
vfunc_get_preferred_width: function(actor, forHeight) {
vfunc_get_preferred_width(actor, forHeight) {
return [100, 100];
},
vfunc_get_preferred_height: function(actor, forWidth) {
vfunc_get_preferred_height(actor, forWidth) {
return [100, 100];
},
vfunc_paint: function(actor) {
vfunc_paint(actor) {
let alloc = this.get_allocation_box();
Cogl.set_source_color4ub(255, 0, 0, 255);
Cogl.rectangle(alloc.x1, alloc.y1,
alloc.x2, alloc.y2);
}
});
```
Translatable strings, `environment.js`
--------------------------------------
## Translatable strings, `environment.js`
We use gettext to translate the GNOME Shell into all the languages that GNOME
supports. The `gettext` function is aliased globally as `_`, you do not need to
@ -204,8 +197,7 @@ and "double quotes" for strings that the user may see. This allows us to
quickly find untranslated or mistranslated strings by grepping through the
sources for double quotes without a gettext call around them.
`actor` and `_delegate`
-----------------------
## `actor` and `_delegate`
gjs allows us to set so-called "expando properties" on introspected objects,
allowing us to treat them like any other. Because the Shell was built before
@ -214,21 +206,22 @@ that has a property called `actor`. We call this wrapper class the "delegate".
We sometimes use expando properties to set a property called `_delegate` on
the actor itself:
```javascript
var MyClass = new Lang.Class({
Name: 'MyClass',
_init: function() {
_init() {
this.actor = new St.Button({ text: "This is a button" });
this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('clicked', this._onClicked.bind(this));
},
_onClicked: function(actor) {
_onClicked(actor) {
actor.set_label("You clicked the button!");
}
});
```
The 'delegate' property is important for anything which trying to get the
delegate object from an associated actor. For instance, the drag and drop
@ -236,57 +229,60 @@ system calls the `handleDragOver` function on the delegate of a "drop target"
when the user drags an item over it. If you do not set the `_delegate`
property, your actor will not be able to be dropped onto.
Functional style
----------------
## Functional style
JavaScript Array objects offer a lot of common functional programming
capabilities such as forEach, map, filter and so on. You can use these when
they make sense, but please don't have a spaghetti mess of function programming
messed in a procedural style. Use your best judgment.
Closures
--------
## Closures
`this` will not be captured in a closure, it is relative to how the closure is
invoked, not to the value of this where the closure is created, because "this"
is a keyword with a value passed in at function invocation time, it is not a
variable that can be captured in closures.
All closures should be wrapped with a Lang.bind.
All closures should be wrapped with Function.prototype.bind or use arrow
notation.
```javascript
const Lang = imports.lang;
let closure = Lang.bind(this, function() { this._fnorbate(); });
let closure1 = () => { this._fnorbate(); };
let closure2 = this._fnorbate.bind(this);
```
A more realistic example would be connecting to a signal on a method of a
prototype:
```javascript
const Lang = imports.lang;
const FnorbLib = imports.fborbLib;
var MyClass = new Lang.Class({
_init: function() {
_init() {
let fnorb = new FnorbLib.Fnorb();
fnorb.connect('frobate', Lang.bind(this, this._onFnorbFrobate));
fnorb.connect('frobate', this._onFnorbFrobate.bind(this));
},
_onFnorbFrobate: function(fnorb) {
_onFnorbFrobate(fnorb) {
this._updateFnorb();
}
});
```
Object literal syntax
---------------------
## Object literal syntax
In JavaScript, these are equivalent:
```javascript
foo = { 'bar': 42 };
foo = { bar: 42 };
```
and so are these:
```javascript
var b = foo['bar'];
var b = foo.bar;
```
If your usage of an object is like an object, then you're defining "member
variables." For member variables, use the no-quotes no-brackets syntax: `{ bar:
@ -296,20 +292,19 @@ If your usage of an object is like a hash table (and thus conceptually the keys
can have special chars in them), don't use quotes, but use brackets: `{ bar: 42
}`, `foo['bar']`.
Getters, setters, and Tweener
-----------------------------
## Getters, setters, and Tweener
Getters and setters should be used when you are dealing with an API that is
designed around setting properties, like Tweener. If you want to animate an
arbitrary property, create a getter and setter, and use Tweener to animate the
property.
```javascript
var ANIMATION_TIME = 2000;
var MyClass = new Lang.Class({
Name: 'MyClass',
_init: function() {
_init() {
this.actor = new St.BoxLayout();
this._position = 0;
},
@ -329,3 +324,4 @@ property.
{ position: 100,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
```

View File

@ -1,7 +0,0 @@
Owen Taylor
E-mail: otaylor@redhat.com
Userid: otaylor
Colin Walters
E-mail: walters@verbum.org
Userid: walters

197
NEWS
View File

@ -1,3 +1,200 @@
3.29.92
=======
* Choose some actors to cache on the GPU [Daniel; #792633]
* inputMethod: Hide preedit text if requested [Takao; #431]
* Fix forced fallback app-menus on wayland [Jonas; #276]
Contributors:
Jonas Ådahl, Takao Fujiwara, Mohammed Sadiq, Marco Trevisan (Treviño),
Daniel van Vugt
Translators:
Baurzhan Muftakhidinov [kk], Kukuh Syafaat [id], Milo Casagrande [it],
Changwoo Ryu [ko], Marek Cernocky [cs]
3.29.91
=======
* Fix handling of 0/false options in ShowOSD D-Bus API [Florian; #791669]
* overview: Fix handling of confirmation dialogs on wayland [verdre; !180]
* Avoid some full relayout/redraws [Carlos; !197]
* Keep workspace switcher slid out when workspaces are in use [Florian; !161]
* Ignore auto-repeat for some keybindings [Andrea; #373]
* Misc. bug fixes [Carlos, Florian, Pascal; #464, !189, !191, !192, !162]
Contributors:
Andrea Azzarone, Olivier Blin, Carlos Garnacho, Florian Müllner,
Pascal Nowack, verdre
Translators:
Bruno Lopes da Silva [pt_BR], Matej Urbančič [sl], Piotr Drąg [pl],
Aurimas Černius [lt], Emin Tufan Çetin [tr], Fabio Tomat [fur],
Alexandre Franke [fr], Yi-Jyun Pan [zh_TW], Bernd Homuth [de],
Andre Klapper [cs], Jordi Mas [ca], Daniel Șerbănescu [ro],
Bruce Cowan [en_GB]
3.29.90
=======
* Add remote access indication on wayland [Jonas; !160]
* Fix wrong window positions in overview on wayland [Marco; #776588]
* Add gesture to unfullscreen a window [Jan-Michael; !123]
* Add PickColor method to screenshot D-Bus interface [Florian; #286]
* Consider "new-window" action when opening new windows [Florian; #756844]
* Make workspace switching gestures follow motion [Carlos; #788994]
* Support audio volumes above 100% [Didier; #790280]
* Misc. bug fixes [Florian, Daniel; #424, !132, !182, #433, !179, #786496]
Contributors:
Jonas Ådahl, Jan-Michael Brummer, Piotr Drąg, Daniel Drake, Carlos Garnacho,
Florian Müllner, Georges Basile Stavracas Neto, Didier Roche, Jakub Steiner,
Marco Trevisan (Treviño)
Translators:
Charles Monzat [fr], Daniel Mustieles [es]
3.29.4
======
* Fix "Clear All" for calendar events [Florian; #325]
* Allow cancelling direct switch operations [Xavier; #315]
* Support being started by systemd --user [Iain; !137, !138]
* Support key event forwarding required by some input methods [Carlos; #275]
* Misc. bug fixes and cleanups [Jasper, Andrea, Florian; #663461, #372, !112,
#414, !151]
Contributors:
Andrea Azzarone, Carlos Garnacho, Xavier Johnson, Iain Lane, Florian Müllner,
Jasper St. Pierre
Translators:
Stas Solovey [ru]
3.29.3
======
* Save creation time in screenshot metadata [Florian; #790481]
* Improve consistency between ctrl- and middle-click on app icons [Xavier; #316]
* Add support for font-feature-settings CSS property [Ryan; #34]
* Adjust to MetaScreen removal [Jonas; #759538]
* Misc. bug fixes [Florian, Marco, Sam; #298, #788931, #26, #76, !54, #788882,
#791233]
Contributors:
Jonas Ådahl, Ryan Hendrickson, Xavier Johnson, Florian Müllner, Joe Rabinoff,
Sam Spilsbury, Marco Trevisan (Treviño)
Translators:
Gun Chleoc [gd], Yi-Jyun Pan [zh_TW], Cédric Valmary [oc], Jordi Mas [ca]
3.29.2
======
* Guard against untimely keyboard map changes [Carlos; #240]
* Fix icons in search provider results [Florian; #249]
* Fix blurriness of OSD under some resolutions [Silvère; #782011]
* Fix lagging pointer when zoomed [Daniel; #682013]
* Misc. bug fixes [Milan, Xiaoguang, Florian, Mario, Ole; #244, #787871,
#781471, #136, #214, #294]
Contributors:
Ole Jørgen Brønner, Milan Crha, Carlos Garnacho, Yussuf Khalil,
Silvère Latchurié, Florian Müllner, Mario Sanchez Prada, Ray Strode,
Daniel van Vugt, Xiaoguang Wang
Translators:
Rafael Fontenelle [pt_BR], Kukuh Syafaat [id], Marcos Lans [gl],
Anders Jonsson [sv], Mingcong Bai [zh_CN]
3.29.1
======
* Support icons in app-menu [Florian; #760985]
* Misc. bug fixes [Marco, Florian, Lubomir; #792687, #221, !63]
Contributors:
Piotr Drąg, Takao Fujiwara, Christian Kellner, Florian Müllner,
Mario Sanchez Prada, Lubomir Rintel, Didier Roche, Marco Trevisan (Treviño),
verdre
Translators:
gogo [hr], Stas Solovey [ru], Matej Urbančič [sl], Daniel Șerbănescu [ro],
Fabio Tomat [fur], Marek Cernocky [cs], Daniel Mustieles [es]
3.28.1
======
* Fix compose characters in shell entries [Carlos; #115]
* Don't show authentication dialogs on lock screen [Florian; #179, #166]
* Fix handling of UTC timezone in world clock [Florian; #150]
* Fix keyboard navigation in overview when hovering windows [Florian; #50]
* Misc. bug fixes [Florian; #127, #788908, #763886, !39]
Contributors:
Jeremy Bicha, Carlos Garnacho, Andy Holmes, Florian Müllner, Bastien Nocera
Translators:
Stas Solovey [ru], Daniel Șerbănescu [ro], Dušan Kazik [sk],
Rafael Fontenelle [pt_BR], Nathan Follens [nl], Dz Chen [zh_CN],
Matej Urbančič [sl], Hannie Dumoleyn [nl], Khaled Hosny [ar],
Guillaume Bernard [fr]
3.28.0
======
Translators:
A S Alam [pa], gogo [hr], Chao-Hsiung Liao [zh_TW], Jordi Mas [ca],
Anders Jonsson [sv], Balázs Úr [hu]
3.27.92
=======
* Misc. bug fixes [Florian; #64, #66, #72]
Contributors:
Jonas Ådahl, Christian Kellner, Florian Müllner
Translators:
Daniel Mustieles [es], Wolfgang Stöggl [de], Cheng-Chia Tseng [zh_TW],
Dušan Kazik [sk], Changwoo Ryu [ko], Furkan Ahmet Kara [tr], Balázs Úr [hu],
Trần Ngọc Quân [vi], Milo Casagrande [it], GNOME Translation Robot [gd, nl],
Marek Cernocky [cs], Aurimas Černius [lt], Alain Lojewski [fr],
Rūdolfs Mazurs [lv], Stas Solovey [ru], Alan Mortensen [da]
3.27.91
=======
* Fix wrong bluetooth state when disabled by HW airplane mode [Mario; #789110]
* Dump javascript stack on aborts, traps and segfaults [Marco; #789237]
* Allow Escape to "cancel" top bar focus [Stefano; #671121]
* Fix leaving the overview erroneously on window hover [Carlos; #784545]
* Add keyboard accessibility dialog [Olivier; #788564]
* Port to libnm [Lubomir, Florian; #789811]
* Don't pop up on-screen-keyboard on touch events [Florian, Carlos; #788188]
* Improve the on-screen-keyboard [Carlos; !9, #46]
* Add Thunderbolt support [Christian; !14]
* Don't lock immediately on login after a wayland session crash [Florian; !17]
* Respect cursor's hot x/y coordinates when recording [Florian Z.; #792860]
* Allow closing windows and apps during <alt>Tab [Florian, Mario; #620106]
* Fix small app folder icons when using HiDPI [Nikita; #792259]
* Make sassc a mandatory build dependency [Mario; #792822]
* Misc. bug fixes [Florian, Marco, Alessandro, Gautier, Jeremy, Bastien, Ray,
Carlos, Didier, Exalm, Rafal; #789231, #789277, #788542, #789103, #779974,
#788931, #776940, #786987, #791007, #791233, #791148, #706191, #791655,
#791487, #779413, #787845, #10, #788627, #792354, #792616, #781329, #780957,
#33, #740142, !38, !23]
Contributors:
Jeremy Bicha, Alessandro Bono, Nikita Churaev, Piotr Drąg, Exalm,
Stefano Facchini, Olivier Fourdan, Carlos Garnacho, Christian Kellner,
Rafal Luzynski, Iñigo Martínez, Florian Müllner, Bastien Nocera,
Gautier Pelloux-Prayer, Mario Sanchez Prada, Lubomir Rintel, Didier Roche,
Jakub Steiner, Ray Strode, Marco Trevisan (Treviño), Florian Zwoch
Translators:
Mingcong Bai [zh_CN], Hannie Dumoleyn [nl], Khaled Hosny [ar],
Kjartan Maraas [nb], Petr Kovar [cs], Marek Cernocky [cs],
Aurimas Černius [lt], Yosef Or Boczko [he], Kukuh Syafaat [id],
Sveinn í Felli [is], Jordi Mas [ca], Daniel Mustieles [es], Fabio Tomat [fur],
Rūdolfs Mazurs [lv], Emin Tufan Çetin [tr], Anders Jonsson [sv],
Matej Urbančič [sl], Jiri Grönroos [fi], Tim Sabsch [de], Gil Forcada [ca],
Dušan Kazik [sk], Balázs Meskó [hu], Piotr Drąg [pl], Tong Hui [zh_CN],
Fran Dieguez [gl], Enrico Nicoletto [pt_BR], gogo [hr],
Baurzhan Muftakhidinov [kk], Robert Antoni Buj Gelonch [ca],
Bruce Cowan [en_GB], Борисав Живановић [sr], Милош Поповић [sr@latin],
Марко Костић [sr]
3.27.1
======
* Fix using icon-name strings with PopupImageMenuItems [Florian; #789018]

View File

@ -1,3 +1,4 @@
# GNOME Shell
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
like switching to windows and launching applications. GNOME Shell takes
advantage of the capabilities of modern graphics hardware and introduces
@ -6,15 +7,14 @@ easy to use experience.
For more information about GNOME Shell, including instructions on how
to build GNOME Shell from source and how to get involved with the project,
see:
see the [project wiki][wiki]
https://wiki.gnome.org/Projects/GnomeShell
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
License
=======
## License
GNOME Shell is distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.
version 2 or later. See the [COPYING][license] file for details.
[project-wiki]: https://wiki.gnome.org/Projects/GnomeShell
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell/issues
[license]: COPYING

View File

@ -4,14 +4,14 @@ the extensions repository to provide good integration, letting the website
know which extensions are enabled and disabled, and allowing the website to
enable, disable and install them.
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
Bugs should be reported to the GNOME [bug tracking system][bug-tracker].
License
=======
## License
The GNOME Shell Browser Plugin, like GNOME Shell itself is distributed under
the GNU General Public License, version 2 or later. The plugin also contains
header files from the "NPAPI SDK" project, tri-licensed under MPL 1.1, GPL 2.0
and LGPL 2.1. These headers are third-party sources and can be retrieved from:
http://code.google.com/p/npapi-sdk/
[bug-tracker]: https://gitlab.gnome.org/GNOME/gnome-shell/issues

View File

@ -24,3 +24,9 @@
/* Define if _NL_TIME_FIRST_WEEKDATE is available */
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
/* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */
#mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
/* Define if fdwalk is available in libc */
#mesondefine HAVE_FDWALK

View File

@ -0,0 +1,6 @@
[org.gnome.mutter:GNOME]
attach-modal-dialogs=true
edge-tiling=true
dynamic-workspaces=true
workspaces-only-on-primary=true
focus-change-on-pointer-rest=true

View File

@ -22,6 +22,7 @@
<file>id.json</file>
<file>il.json</file>
<file>in+bolnagri.json</file>
<file>in+mal.json</file>
<file>ir.json</file>
<file>is.json</file>
<file>it.json</file>

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=GNOME settings overrides migration
NoDisplay=true
Exec=@libexecdir@/gnome-shell-overrides-migration.sh

View File

@ -19,6 +19,12 @@
<file>filter-selected-rtl.svg</file>
<file>gnome-shell.css</file>
<file>gnome-shell-high-contrast.css</file>
<file>key-enter.svg</file>
<file>key-hide.svg</file>
<file>key-layout.svg</file>
<file>key-shift.svg</file>
<file>key-shift-uppercase.svg</file>
<file>key-shift-latched-uppercase.svg</file>
<file>logged-in-indicator.svg</file>
<file alias="icons/message-indicator-symbolic.svg">message-indicator-symbolic.svg</file>
<file>no-events.svg</file>

View File

@ -0,0 +1,5 @@
[Unit]
Description=GNOME Shell (wayland sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-x11.target

View File

@ -0,0 +1,5 @@
[Unit]
Description=GNOME Shell (x11 sync point)
After=gnome-shell.service
BindsTo=gnome-shell.service
Conflicts=gnome-shell-wayland.target

View File

@ -0,0 +1,11 @@
[Unit]
Description=GNOME Shell
Wants=gnome-session.service
After=graphical-session-pre.target gnome-session-bus.target
PartOf=graphical-session.target
[Service]
Type=dbus
ExecStart=@bindir@/gnome-shell
Restart=on-failure
BusName=org.gnome.Shell

View File

@ -92,6 +92,33 @@ schema = configure_file(
configuration: schemaconf,
install_dir: schemadir
)
install_data('00_org.gnome.shell.gschema.override', install_dir: schemadir)
overrides_migration_conf = configuration_data()
overrides_migration_conf.set('libexecdir', libexecdir)
overrides_migration = configure_file(
input: 'gnome-shell-overrides-migration.desktop.in',
output: 'gnome-shell-overrides-migration.desktop',
configuration: overrides_migration_conf,
install_dir: autostartdir
)
if have_systemd
unitconf = configuration_data()
unitconf.set('bindir', bindir)
unit = configure_file(
input: 'gnome-shell.service.in',
output: 'gnome-shell.service',
configuration: unitconf,
install_dir: systemduserunitdir
)
units = files('gnome-shell-wayland.target',
'gnome-shell-x11.target')
install_data(units, install_dir: systemduserunitdir)
endif
# for unit tests - gnome.compile_schemas() only looks in srcdir
custom_target('compile-schemas',

View File

@ -91,6 +91,23 @@
<arg type="s" direction="out" name="filename_used"/>
</method>
<!--
PickColor:
Picks a color and returns the result.
The @result vardict contains:
<variablelist>
<varlistentry>
<term>color (ddd)</term>
<listitem><para>The color, RGB values in the range [0,1].</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="PickColor">
<arg type="a{sv}" direction="out" name="result"/>
</method>
<!--
FlashArea:
@x: the X coordinate of the area to flash

View File

@ -190,6 +190,7 @@
</key>
</schema>
<!-- unused, change 00_org.gnome.shell.gschema.override instead -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b">

View File

@ -0,0 +1,559 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"െ"
],
[
"ൌ"
],
[
"ൈ"
],
[
"ാ"
],
[
"ീ"
],
[
"ൂ"
],
[
"ബ"
],
[
"ഹ"
],
[
"ഗ"
],
[
"ദ"
],
[
"ജ"
],
[
"ഡ"
],
[
""
]
],
[
[
"ോ"
],
[
"േ"
],
[
"്"
],
[
"ി"
],
[
"ു"
],
[
"പ"
],
[
"ര"
],
[
"ക"
],
[
"ത"
],
[
"ച"
],
[
"ട"
]
],
[
[
"െ"
],
[
""
],
[
"മ",
"ç"
],
[
"ന"
],
[
"വ"
],
[
"ല",
"ñ"
],
[
"സ"
],
[
"ഷ"
],
[
"യ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"ഔ"
],
[
"ഐ"
],
[
"ആ"
],
[
"ഈ"
],
[
"ഊ"
],
[
"ഭ"
],
[
"ങ"
],
[
"ഘ"
],
[
"ധ"
],
[
"ഝ"
],
[
"ഢ"
],
[
"ഞ"
]
],
[
[
"ഓ"
],
[
"ഏ"
],
[
"അ"
],
[
"ഇ"
],
[
"ഉ"
],
[
"ഫ"
],
[
"റ"
],
[
"ഖ"
],
[
"ഥ"
],
[
"ഛ"
],
[
""
]
],
[
[
"എ"
],
[
""
],
[
"ണ"
],
[
"ന"
],
[
"ഴ"
],
[
"ള"
],
[
"ശ"
],
[
"ഷ"
],
[
"യ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"൧",
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"൨",
"2",
"²",
"⅔"
],
[
"൩",
"3",
"³",
"¾",
"⅜"
],
[
"൪",
"4",
"⁴"
],
[
"൫",
"5",
"⅝"
],
[
"൬",
"6"
],
[
"",
"7",
"⅞"
],
[
"൮",
"8"
],
[
"൯",
"9"
],
[
"",
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₹",
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ml",
"name": "Malayalam"
}

View File

@ -1,3 +0,0 @@
To generate the css files, from the project directory:
sass --sourcemap=none --update .

View File

@ -1,34 +0,0 @@
Summary
-------
* Do not edit the CSS directly, edit the source SCSS files and process them with SASS (running
`make` should do that when you have the required software installed, as described below;
run `./parse-sass.sh` manually if it doesn't)
* Most SASS preprocessors should produce similar results, however the build system
integration and 'parse-sass.sh' script use sassc. You should be able to install
it with `pkcon install sassc` or your distribution's package manager.
How to tweak the theme
----------------------
Adwaita is a complex theme, so to keep it maintainable it's written and processed in SASS, the
generated CSS is then transformed into a gresource file during gtk build and used at runtime in a
non-legible or editable form.
It is very likely your change will happen in the _common.scss file. That's where all the widget
selectors are defined. Here's a rundown of the "supporting" stylesheets, that are unlikely to be the
right place for a drive by stylesheet fix:
_colors.scss - global color definitions. We keep the number of defined colors to a necessary minimum,
most colors are derived from a handful of basics. It is an exact copy of the gtk+
counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell
default.
_drawing.scss - drawing helper mixings/functions to allow easier definition of widget drawing under
specific context. This is why Adwaita isn't 15000 LOC.
_common.scss - actual definitions of style for each widget. This is where you are likely to add/remove
your changes.
You can read about SASS at http://sass-lang.com/documentation/. Once you make your changes to the
_common.scss file, you can either run make or the ./parse-sass.sh script.

32
data/theme/README.md Normal file
View File

@ -0,0 +1,32 @@
## Summary
Do not edit the CSS directly, edit the source SCSS files and the CSS files
will be generated automatically when building with meson + ninja and left
inside the build directory to be incorporated into the gresource XML (you'll
need to have sassc installed).
## How to tweak the theme
Adwaita is a complex theme, so to keep it maintainable it's written and
processed in SASS, the generated CSS is then transformed into a gresource
file during gtk build and used at runtime in a non-legible or editable form.
It is very likely your change will happen in the [_common.scss][common] file.
That's where all the widget selectors are defined. Here's a rundown of
the "supporting" stylesheets, that are unlikely to be the right place
for a drive by stylesheet fix:
| File | Description |
| ------------------------ | ----------------- |
| [_colors.scss][colors] | global color definitions. We keep the number of defined colors to a necessary minimum, most colors are derived from a handful of basics. It is an exact copy of the gtk+ counterpart. Light theme is used for the classic theme and dark is for GNOME3 shell default. |
| [_drawing.scss][drawing] | drawing helper mixings/functions to allow easier definition of widget drawing under specific context. This is why Adwaita isn't 15000 LOC. |
| [_common.scss][common] | actual definitions of style for each widget. This is where you are likely to add/remove your changes. |
You can read about SASS on its [web page][sass-web]. Once you make your
changes to the [_common.scss][common] file, you can run ninja to generate the
final CSS files.
[common]: data/theme/gnome-shell-sass/_common.scss
[colors]: data/theme/gnome-shell-sass/_colors.scss
[drawing]: data/theme/gnome-shell-sass/_drawing.scss
[sass-web]: http://sass-lang.com/documentation/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. <http://fsf.org>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,16 @@
# GNOME Shell Sass
GNOME Shell Sass is a project intended to allow the sharing of the
theme sources in sass between gnome-shell and other projects like
gnome-shell-extensions.
Any changes should be done in the [GNOME Shell subtree][shell-subtree]
and not the stand-alone [gnome-shell-sass repository][sass-repo]. They
will then be synchronized periodically before releases.
## License
GNOME Shell Sass is distributed under the terms of the GNU General Public
License, version 2 or later. See the [COPYING][license] file for details.
[shell-subtree]: https://gitlab.gnome.org/GNOME/gnome-shell/tree/master/data/theme/gnome-shell-sass
[sass-repo]: https://gitlab.gnome.org/GNOME/gnome-shell-sass
[license]: COPYING

View File

@ -0,0 +1,44 @@
// When color definition differs for dark and light variant,
// it gets @if ed depending on $variant
$base_color: if($variant =='light', #ffffff, #292929);
$bg_color: if($variant =='light', #ededed, #393f3f);
$fg_color: if($variant =='light', #2e3436, #eeeeec);
$selected_fg_color: #ffffff;
$selected_bg_color: if($variant == 'light', #4a90d9, darken(#4a90d9,20%));
$selected_borders_color: if($variant=='light', darken($selected_bg_color, 30%),
darken($selected_bg_color, 20%));
$borders_color: if($variant =='light', darken($bg_color,30%), darken($bg_color,12%));
$borders_edge: if($variant =='light', white, transparentize($fg_color, 0.9));
$link_color: if($variant == 'light', darken($selected_bg_color,10%),
lighten($selected_bg_color,20%));
$link_visited_color: if($variant == 'light', darken($selected_bg_color,20%),
lighten($selected_bg_color,10%));
$top_hilight: $borders_edge;
$warning_color: #f57900;
$error_color: #cc0000;
$success_color: if($variant =='light', #73d216, darken(#73d216,10%));
$destructive_color: if($variant =='light', #ef2929, darken(#ef2929,10%));
$osd_fg_color: #eeeeec;
$osd_bg_color: #2e3436;
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);
$tooltip_borders_color: $osd_outer_borders_color;
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
$insensitive_borders_color: $borders_color;
//colors for the backdrop state, derived from the main colors.
$backdrop_base_color: if($variant =='light', darken($base_color,1%), lighten($base_color,1%));
$backdrop_bg_color: $bg_color;
$backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
$backdrop_insensitive_color: if($variant =='light', darken($backdrop_bg_color,15%), lighten($backdrop_bg_color,15%));
$backdrop_borders_color: mix($borders_color, $bg_color, 90%);
$backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,221 @@
// Drawing mixins
// generic drawing of more complex things
@function _widget_edge($c:$borders_edge) {
// outer highlight "used" on most widgets
@return 0 1px $c;
}
// provide font size in rem, with px fallback
@mixin fontsize($size: 24, $base: 16) {
font-size: round($size) + pt;
//font-size: ($size / $base) * 1rem;
}
@mixin _shadows($shadow1, $shadow2:none, $shadow3:none, $shadow4:none) {
//
// Helper function to stack up to 4 box-shadows;
//
@if $shadow4!=none { box-shadow: $shadow1, $shadow2, $shadow3, $shadow4; }
@else if $shadow3!=none { box-shadow: $shadow1, $shadow2, $shadow3; }
@else if $shadow2!=none { box-shadow: $shadow1, $shadow2; }
@else { box-shadow: $shadow1; }
}
// entries
@mixin entry($t, $fc:$selected_bg_color, $edge: $borders_edge) {
//
// Entries drawing function
//
// $t: entry type
// $fc: focus color
// $edge: set to none to not draw the bottom edge or specify a color to not
// use the default one
//
// possible $t values:
// normal, focus, insensitive
//
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
@if $t==normal {
background-color: $base_color;
border-color: $borders_color;
@include _shadows($_inner_shadows);
}
@if $t==focus {
@include _shadows($_inner_shadows);
border-color: if($fc==$selected_bg_color,
$selected_borders_color,
darken($fc,35%));
}
@if $t==hover { }
@if $t==insensitive {
color: $insensitive_fg_color;
border-color: $insensitive_bg_color;
box-shadow: none;
}
}
// buttons
@function _border_color ($c) { @return darken($c,25%); } // colored buttons want
// the border form the
// base color
@function _text_shadow_color ($tc:$fg_color, $bg:$bg_color) {
//
// calculate the color of text shadows
//
// $tc is the text color
// $bg is the background color
//
$_lbg: lightness($bg)/100%;
@if lightness($tc)<50% { @return transparentize(white,1-$_lbg/($_lbg*1.3)); }
@else { @return transparentize(black,$_lbg*0.8); }
}
@function _button_hilight_color($c) {
//
// calculate the right top hilight color for buttons
//
// $c: base color;
//
@if lightness($c)>90% { @return white; }
@else if lightness($c)>80% { @return transparentize(white, 0.3); }
@else if lightness($c)>50% { @return transparentize(white, 0.5); }
@else if lightness($c)>40% { @return transparentize(white, 0.7); }
@else { @return transparentize(white, 0.9); }
}
@mixin _button_text_shadow ($tc:$fg_color, $bg:$bg_color) {
//
// helper function for the text emboss effect
//
// $tc is the optional text color, not the shadow color
//
// TODO: this functions needs a way to deal with special cases
//
$_shadow: _text_shadow_color($tc, $bg);
@if lightness($tc)<50% {
text-shadow: 0 1px $_shadow;
icon-shadow: 0 1px $_shadow;
}
@else {
text-shadow: 0 -1px $_shadow;
icon-shadow: 0 -1px $_shadow;
}
}
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
//
// Button drawing function
//
// $t: button type,
// $c: base button color for colored* types
// $tc: optional text color for colored* types
// $edge: set to none to not draw the bottom edge or specify a color to not
// use the default one
//
// possible $t values:
// normal, hover, active, insensitive, insensitive-active,
// backdrop, backdrop-active, backdrop-insensitive, backdrop-insensitive-active,
// osd, osd-hover, osd-active, osd-insensitive, osd-backdrop, undecorated
//
$_hilight_color: _button_hilight_color($c);
$_button_edge: if($edge == none, none, _widget_edge($edge));
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
@if $t==normal {
//
// normal button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $osd_fg_color;
background-color: $_bg;
border-color: $osd_borders_color;
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
}
@if $t==focus {
//
// focused button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $osd_fg_color;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
}
@else if $t==hover {
//
// active osd button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,10%));
color: white;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
}
@else if $t==active {
//
// active osd button
//
$_bg: if($c!=$bg_color, $c, $osd_borders_color);
color: white;
border-color: $osd_borders_color;
background-color: darken($_bg,5%);
// This should be none, but it's creating some issues with borders, so to
// workaround it for now, use inset wich goes through a different code path.
// see https://bugzilla.gnome.org/show_bug.cgi?id=752934
box-shadow: inset 0 0 black;
text-shadow: none;
icon-shadow: none;
}
@else if $t==insensitive {
//
// insensitive osd button
//
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
color: $insensitive_fg_color;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: none;
text-shadow: none;
icon-shadow: none;
}
@else if $t==undecorated {
//
// reset
//
border-color: transparent;
background-color: transparent;
background-image: none;
@include _shadows(inset 0 1px transparentize(white,1),
$_blank_edge);
text-shadow: none;
icon-shadow: none;
}
}

View File

@ -0,0 +1,41 @@
// When color definition differs for dark and light variant,
// it gets @if ed depending on $variant
$base_color: #222;
$bg_color: #000;
$fg_color: #fff;
$selected_fg_color: #ffffff;
$selected_bg_color: darken(#4a90d9,20%);
$selected_borders_color: darken($selected_bg_color, 20%);
$borders_color: darken($bg_color,12%);
$borders_edge: transparentize($fg_color, 0.9);
$link_color: lighten($selected_bg_color,20%);
$link_visited_color: lighten($selected_bg_color,10%);
$top_hilight: $borders_edge;
$warning_color: #f57900;
$error_color: #cc0000;
$success_color: darken(#73d216,10%);
$destructive_color: darken(#ef2929,10%);
$osd_fg_color: #eeeeec;
$osd_bg_color: #2e3436;
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);
$tooltip_borders_color: $osd_outer_borders_color;
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);
$insensitive_bg_color: mix($bg_color, $base_color, 60%);
$insensitive_borders_color: $borders_color;
//colors for the backdrop state, derived from the main colors.
$backdrop_base_color: lighten($base_color,1%);
$backdrop_bg_color: $bg_color;
$backdrop_fg_color: mix($fg_color, $backdrop_bg_color, 80%);
$backdrop_insensitive_color: lighten($backdrop_bg_color,15%);
$backdrop_borders_color: mix($borders_color, $bg_color, 90%);
$backdrop_dark_fill: mix($backdrop_borders_color,$backdrop_bg_color, 35%);

View File

@ -0,0 +1,37 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<name xml:lang="en">GNOME Shell Sass</name>
<shortdesc xml:lang="en">Sass sources of GNOME Shell</shortdesc>
<description>GNOME Shell Sass is a project intended to allow the sharing of the
sass theme sources between gnome-shell and other projects like gnome-shell-extensions.</description>
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>sass</programming-language>
<programming-language>css</programming-language>
<maintainer>
<foaf:Person>
<foaf:name>Carlos Soriano</foaf:name>
<foaf:mbox rdf:resource="mailto:csoriano@gnome.org" />
<gnome:userid>csoriano</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Florian Müllner</foaf:name>
<foaf:mbox rdf:resource="mailto:fmuellner@gnome.org" />
<gnome:userid>fmuellner</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Jakub Steiner</foaf:name>
<foaf:mbox rdf:resource="mailto:jimmac@gmail.com" />
<gnome:userid>jimmac</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

File diff suppressed because it is too large Load Diff

109
data/theme/key-enter.svg Normal file
View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-enter.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1744"
inkscape:window-height="866"
id="namedview19"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="7.9322034"
inkscape:cy="14.554666"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer9" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer10" />
<g
transform="translate(-141.0002,-791)"
id="layer11" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer13" />
<g
transform="translate(-141.0002,-791)"
id="layer14" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer15" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g71291" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g4953" />
<g
transform="matrix(2,0,0,2,-281.56285,-1615.0002)"
style="display:inline"
id="layer12">
<path
id="path16589"
d="m 148.00015,821.0002 h -1 c -0.26528,0 -0.53057,-0.093 -0.71875,-0.2812 l -3.71875,-3.7188 c 0,0 2.47917,-2.4792 3.71875,-3.7187 0.18817,-0.1882 0.45344,-0.2813 0.71875,-0.2813 h 1 v 1 c 0,0.2653 -0.0931,0.5306 -0.28125,0.7188 l -2.28125,2.2812 2.28125,2.2813 c 0.18811,0.1881 0.28129,0.4534 0.28125,0.7187 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:'Bitstream Vera Sans';-inkscape-font-specification:'Bitstream Vera Sans';text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:accumulate"
inkscape:connector-curvature="0" />
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#bebebe;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 154.0002,810 v 4.5 c 0,1.3807 -1.11929,2.5 -2.5,2.5 h -6.50005"
id="path16591"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

114
data/theme/key-hide.svg Normal file
View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-hide.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1919"
inkscape:window-height="1011"
id="namedview19"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-12.338983"
inkscape:cy="14.554666"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer9" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer10" />
<g
transform="translate(-141.0002,-791)"
id="layer11" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer13" />
<g
transform="translate(-141.0002,-791)"
id="layer14" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer15" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g71291" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g4953" />
<g
style="display:inline"
inkscape:label="go-down"
id="g11722"
transform="matrix(2,0,0,2,-362.0004,-1494)">
<rect
transform="rotate(90)"
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:1;marker:none;enable-background:new"
id="rect11718"
y="-197.0002"
x="747"
height="16"
width="16" />
<path
style="display:inline;fill:#e5e5e5;fill-opacity:1;stroke:none"
d="m 189.0002,759.4375 -5.71875,-5.7187 C 183.08558,753.5229 183.0002,753.2556 183.0002,753 v -1 h 1 c 0.25562,0 0.52288,0.085 0.71875,0.2813 l 4.28125,4.2812 4.28125,-4.2812 C 193.47732,752.0854 193.74458,752 194.0002,752 h 1 v 1 c 0,0.2556 -0.0854,0.5229 -0.28125,0.7188 z"
id="path11720"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscsccsscscc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

129
data/theme/key-layout.svg Normal file
View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-layout.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3440"
inkscape:window-height="1376"
id="namedview19"
showgrid="false"
inkscape:zoom="1"
inkscape:cx="46.246852"
inkscape:cy="17.474578"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7384">
<inkscape:grid
type="xygrid"
id="grid861" />
</sodipodi:namedview>
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer9" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer10" />
<g
transform="translate(-141.0002,-791)"
id="layer11" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer13" />
<g
transform="translate(-141.0002,-791)"
id="layer14" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer15" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g71291" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g4953" />
<g
style="stroke-width:0.5;enable-background:new"
id="g3561"
inkscape:label="preferences-desktop-locale"
transform="matrix(2,0,0,2,135.99464,-895.9793)">
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path3535"
d="m -65,450 v 12"
style="fill:#e5e5e5;fill-opacity:1;fill-rule:evenodd;stroke:#e5e5e5;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3537"
d="m -65,456 h 4 l 1,2 h 5 v -6 h -4 l -1,-2 h -5 z"
style="fill:none;fill-rule:evenodd;stroke:#e5e5e5;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;vector-effect:none;fill:#e5e5e5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m -65,456 h 4 l 1,2 h 5 v -6 h -4 l -1,-2 h -5 z"
id="path3539"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:0.89050001;marker:none;enable-background:new"
id="rect3543"
y="448"
x="-68"
height="16"
width="16" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-shift-latched-uppercase.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1791"
inkscape:window-height="984"
id="namedview19"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-0.77966097"
inkscape:cy="18.847458"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer9" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer10" />
<g
transform="translate(-141.0002,-791)"
id="layer11" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer13" />
<g
transform="translate(-141.0002,-791)"
id="layer14" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer15" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g71291" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g4953" />
<g
transform="matrix(2,0,0,2,-282.0004,-1614.2187)"
style="display:inline;fill:#006098;fill-opacity:1"
id="layer12">
<path
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#006098;fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:new"
d="m 147,818 v -4 h -3.1248 l 5.125,-5.7813 5.125,5.7813 h -3.1875 v 4 z"
id="path16532"
inkscape:connector-curvature="0" />
<path
id="path16534"
d="m 147,822 v -2 h 3.9377 v 2 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#006098;fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:new"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-shift-uppercase.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2160"
inkscape:window-height="1311"
id="namedview18"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-27.898305"
inkscape:cy="8"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="1"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer9" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer10" />
<g
transform="translate(-141.0002,-791)"
id="layer11" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer13" />
<g
transform="translate(-141.0002,-791)"
id="layer14" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="layer15" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g71291" />
<g
transform="translate(-141.0002,-791)"
style="display:inline"
id="g4953" />
<g
transform="matrix(2,0,0,2,-282.0008,-1614.2187)"
style="display:inline;fill:#006098;fill-opacity:1"
id="layer12">
<path
id="path16548"
d="m 147.0002,820 v -4 h -3.1248 l 5.125,-5.7813 5.125,5.7813 h -3.1875 v 4 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#006098;fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:new"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

108
data/theme/key-shift.svg Normal file
View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
viewBox="0 0 32 32"
version="1.1"
id="svg7384"
height="32"
sodipodi:docname="key-shift.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1400"
inkscape:window-height="1034"
id="namedview4569"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="14.75"
inkscape:cx="1.5993763"
inkscape:cy="5"
inkscape:window-x="0"
inkscape:window-y="55"
inkscape:window-maximized="0"
inkscape:current-layer="svg7384" />
<metadata
id="metadata90">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Gnome Symbolic Icon Theme</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<title
id="title9167">Gnome Symbolic Icon Theme</title>
<defs
id="defs7386">
<linearGradient
osb:paint="solid"
id="linearGradient19282"
gradientTransform="matrix(-2.7365795,0.28202934,-0.18908311,-0.99988321,239.54008,-879.45557)">
<stop
style="stop-color:#666666;stop-opacity:1;"
offset="0"
id="stop19284" />
</linearGradient>
</defs>
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="layer9" />
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="layer10" />
<g
transform="translate(-143.8754,-788)"
id="layer11" />
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="layer13" />
<g
transform="translate(-143.8754,-788)"
id="layer14" />
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="layer15" />
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="g71291" />
<g
transform="translate(-143.8754,-788)"
style="display:inline"
id="g4953" />
<g
transform="matrix(2,0,0,2,-282.0008,-1614.2187)"
style="display:inline"
id="layer12">
<path
id="path16548"
d="m 147.0002,820 v -4 h -3.1248 l 5.125,-5.7813 5.125,5.7813 h -3.1875 v 4 z"
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none;enable-background:new"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -7,15 +7,19 @@ theme_sources = files([
'gnome-shell-sass/_high-contrast-colors.scss'
])
styles = [
'gnome-shell-high-contrast',
'gnome-shell'
]
theme_deps = []
if sassc.found()
parse_sass = files('parse-sass.sh')
theme_deps += custom_target('update-theme',
output: 'theme-update.stamp',
depend_files: theme_sources,
command: [parse_sass, '@OUTPUT@'],
build_by_default: true
)
endif
foreach style: styles
theme_deps += custom_target('style-' + style,
input: '@0@.scss'.format(style),
output: '@0@.css'.format(style),
command: [
sassc, '-a', '@INPUT@', '@OUTPUT@'
],
depend_files: theme_sources)
endforeach

View File

@ -13,10 +13,102 @@
height="64px"
id="svg3393"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="New document 2">
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="no-notifications.svg">
<defs
id="defs3395" />
id="defs3395">
<clipPath
id="clipPath6262-0"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6264-6"
width="3.8250003"
height="6.3750005"
x="26.849981"
y="220.75" />
</clipPath>
<clipPath
id="clipPath6258-0"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6260-6"
width="2.8977275"
height="5.3129687"
x="26.965673"
y="221.28162" />
</clipPath>
<clipPath
id="clipPath6254-6"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none"
id="rect6256-6"
width="1.876245"
height="4.8783236"
x="26.998718"
y="221.50153" />
</clipPath>
<clipPath
id="clipPath8028-3"
clipPathUnits="userSpaceOnUse">
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -73,-30 -7,-7 v -4.5 h 16.5 v 4.5 l -7.5,7 z"
id="path8030-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6810-7-87-7">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
id="rect6812-2-4-5"
width="14"
height="11"
x="21"
y="281" />
</clipPath>
<clipPath
id="clipPath6262"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6264"
width="3.8250003"
height="6.3750005"
x="26.849981"
y="220.75" />
</clipPath>
<clipPath
id="clipPath6258"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6260"
width="2.8977275"
height="5.3129687"
x="26.965673"
y="221.28162" />
</clipPath>
<clipPath
id="clipPath6254"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none"
id="rect6256"
width="1.876245"
height="4.8783236"
x="26.998718"
y="221.50153" />
</clipPath>
<inkscape:path-effect
effect="spiro"
id="path-effect3951"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
@ -24,17 +116,17 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.5"
inkscape:cx="32"
inkscape:cy="32"
inkscape:zoom="1"
inkscape:cx="125.08157"
inkscape:cy="-13.805087"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:document-units="px"
inkscape:grid-bbox="true"
inkscape:window-width="697"
inkscape:window-height="613"
inkscape:window-x="100"
inkscape:window-y="77"
inkscape:window-width="1664"
inkscape:window-height="1034"
inkscape:window-x="1479"
inkscape:window-y="252"
inkscape:window-maximized="0" />
<metadata
id="metadata3398">
@ -54,7 +146,7 @@
inkscape:groupmode="layer">
<g
style="display:inline"
transform="matrix(4,0,0,4,0.29733827,-0.35415646)"
transform="matrix(4,0,0,4,-79.702662,-0.35415646)"
id="g19245">
<g
id="g19247"
@ -71,15 +163,15 @@
transform="translate(-323.02908,-649.02581)">
<path
inkscape:connector-curvature="0"
d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 l 0,2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 1.61114,0 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 l 0,-5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z"
d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 v 2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 h 1.61114 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 v -5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z"
id="path19253"
sodipodi:nodetypes="csscsscccssssc"
style="opacity:0.5;color:#000000;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" />
<path
inkscape:connector-curvature="0"
d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 1.03125,0 -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 l 0.0625,1.3751 -1.03125,0 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 L 326.96895,651 z"
d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 h 1.03125 l -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 L 328.0002,656 h -1.03125 l 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 z"
id="path19255"
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate" />
</g>
<g
id="g19257"
@ -110,5 +202,22 @@
style="display:inline"
transform="translate(-323.02908,-649.02581)" />
</g>
<g
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
inkscape:label="preferences-system-notifications"
id="g13967"
transform="matrix(4,0,0,4,-1044.0008,-2172)">
<path
inkscape:connector-curvature="0"
d="m 268.94244,544.94838 c -2.20914,0 -3.33013,1.5 -4,4 l -1,5 c -0.10831,0.54156 -0.44772,1 -1,1 v 1 h 12 v -1 c -0.55229,0 -0.89169,-0.45844 -1,-1 l -1,-5 c -0.53033,-2.5 -1.79086,-4 -4,-4 z"
id="path40220"
sodipodi:nodetypes="ccsccccscc"
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal" />
<path
inkscape:connector-curvature="0"
d="m 269.11822,556.94838 a 1.5,1.5 0 0 0 1.41211,1 1.5,1.5 0 0 0 1.41211,-1 z"
id="path40774"
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,10 +0,0 @@
#!/bin/sh
srcdir=`dirname $0`
stamp=${1}
for scss in $srcdir/*.scss
do
sassc -a $scss ${scss%%.scss}.css || exit 1
done
[ "$stamp" ] && touch $stamp

View File

@ -50,8 +50,7 @@ gnome.gtkdoc('shell',
join_paths(meson.build_root(), 'src')
],
scan_args: [
'--ignore-headers=' + ' '.join(private_headers + exclude_directories),
'--rebuild-types'
'--ignore-headers=' + ' '.join(private_headers + exclude_directories)
],
install: true
)

View File

@ -17,8 +17,7 @@ gnome.gtkdoc('st',
],
scan_args: [
'--ignore-headers=' + ' '.join(private_headers),
'--rebuild-sections',
'--rebuild-types'
'--rebuild-sections'
],
install: true
)

View File

@ -14,15 +14,16 @@ const _ = Gettext.gettext;
const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const GnomeShellIface = '<node> \
<interface name="org.gnome.Shell.Extensions"> \
<signal name="ExtensionStatusChanged"> \
<arg type="s" name="uuid"/> \
<arg type="i" name="state"/> \
<arg type="s" name="error"/> \
</signal> \
</interface> \
</node>';
const GnomeShellIface = `
<node>
<interface name="org.gnome.Shell.Extensions">
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
</interface>
</node>`;
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -34,16 +35,16 @@ function stripPrefix(string, prefix) {
var Application = new Lang.Class({
Name: 'Application',
_init: function() {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs');
this.application = new Gtk.Application({
application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
});
this.application.connect('activate', Lang.bind(this, this._onActivate));
this.application.connect('command-line', Lang.bind(this, this._onCommandLine));
this.application.connect('startup', Lang.bind(this, this._onStartup));
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('command-line', this._onCommandLine.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
this._extensionPrefsModules = {};
@ -52,7 +53,7 @@ var Application = new Lang.Class({
this._skipMainWindow = false;
},
_extensionAvailable: function(uuid) {
_extensionAvailable(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
@ -64,7 +65,7 @@ var Application = new Lang.Class({
return true;
},
_getExtensionPrefsModule: function(extension) {
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
if (this._extensionPrefsModules.hasOwnProperty(uuid))
@ -79,7 +80,7 @@ var Application = new Lang.Class({
return prefsModule;
},
_selectExtension: function(uuid) {
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
return;
@ -114,7 +115,7 @@ var Application = new Lang.Class({
dialog.show();
},
_buildErrorUI: function(extension, exc) {
_buildErrorUI(extension, exc) {
let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
let label = new Gtk.Label({
label: _("There was an error loading the preferences dialog for %s:").format(extension.metadata.name)
@ -127,9 +128,7 @@ var Application = new Lang.Class({
errortext += 'Stack trace:\n';
// Indent stack trace.
errortext += exc.stack.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
errortext += exc.stack.split('\n').map(line => ' ' + line).join('\n');
let scroll = new Gtk.ScrolledWindow({ vexpand: true });
let buffer = new Gtk.TextBuffer({ text: errortext });
@ -142,7 +141,7 @@ var Application = new Lang.Class({
return box;
},
_buildUI: function(app) {
_buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: app,
window_position: Gtk.WindowPosition.CENTER });
@ -164,28 +163,28 @@ var Application = new Lang.Class({
this._window.add(scroll);
this._extensionSelector = new Gtk.ListBox({ selection_mode: Gtk.SelectionMode.NONE });
this._extensionSelector.set_sort_func(Lang.bind(this, this._sortList));
this._extensionSelector.set_header_func(Lang.bind(this, this._updateHeader));
this._extensionSelector.set_sort_func(this._sortList.bind(this));
this._extensionSelector.set_header_func(this._updateHeader.bind(this));
scroll.add(this._extensionSelector);
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStatusChanged', Lang.bind(this, function(proxy, senderName, [uuid, state, error]) {
this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
if (ExtensionUtils.extensions[uuid] !== undefined)
this._scanExtensions();
}));
});
this._window.show_all();
},
_sortList: function(row1, row2) {
_sortList(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
},
_updateHeader: function(row, before) {
_updateHeader(row, before) {
if (!before || row.get_header())
return;
@ -193,27 +192,26 @@ var Application = new Lang.Class({
row.set_header(sep);
},
_scanExtensions: function() {
_scanExtensions() {
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', Lang.bind(this, this._extensionFound));
finder.connect('extension-found', this._extensionFound.bind(this));
finder.scanExtensions();
this._extensionsLoaded();
},
_extensionFound: function(finder, extension) {
_extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', Lang.bind(this,
function() {
this._selectExtension(row.uuid);
}));
row.prefsButton.connect('clicked', () => {
this._selectExtension(row.uuid);
});
row.show_all();
this._extensionSelector.add(row);
},
_extensionsLoaded: function() {
_extensionsLoaded() {
if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid);
this._startupUuid = null;
@ -221,16 +219,16 @@ var Application = new Lang.Class({
this._loaded = true;
},
_onActivate: function() {
_onActivate() {
this._window.present();
},
_onStartup: function(app) {
_onStartup(app) {
this._buildUI(app);
this._scanExtensions();
},
_onCommandLine: function(app, commandLine) {
_onCommandLine(app, commandLine) {
app.activate();
let args = commandLine.get_arguments();
@ -257,7 +255,7 @@ var DescriptionLabel = new Lang.Class({
Name: 'DescriptionLabel',
Extends: Gtk.Label,
vfunc_get_preferred_height_for_width: function(width) {
vfunc_get_preferred_height_for_width(width) {
// Hack: Request the maximum height allowed by the line limit
if (this.lines > 0)
return this.parent(0);
@ -269,29 +267,28 @@ var ExtensionRow = new Lang.Class({
Name: 'ExtensionRow',
Extends: Gtk.ListBoxRow,
_init: function(uuid) {
_init(uuid) {
this.parent();
this.uuid = uuid;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', Lang.bind(this,
function() {
this._switch.state = this._isEnabled();
}));
this._settings.connect('changed::enabled-extensions', () => {
this._switch.state = this._isEnabled();
});
this._settings.connect('changed::disable-extension-version-validation',
Lang.bind(this, function() {
() => {
this._switch.sensitive = this._canEnable();
}));
});
this._settings.connect('changed::disable-user-extensions',
Lang.bind(this, function() {
() => {
this._switch.sensitive = this._canEnable();
}));
});
this._buildUI();
},
_buildUI: function() {
_buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
@ -328,18 +325,17 @@ var ExtensionRow = new Lang.Class({
this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
sensitive: this._canEnable(),
state: this._isEnabled() });
this._switch.connect('notify::active', Lang.bind(this,
function() {
if (this._switch.active)
this._enable();
else
this._disable();
}));
this._switch.connect('state-set', function() { return true; });
this._switch.connect('notify::active', () => {
if (this._switch.active)
this._enable();
else
this._disable();
});
this._switch.connect('state-set', () => true);
hbox.add(this._switch);
},
_canEnable: function() {
_canEnable() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
@ -347,12 +343,12 @@ var ExtensionRow = new Lang.Class({
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
},
_isEnabled: function() {
_isEnabled() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
},
_enable: function() {
_enable() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
@ -361,7 +357,7 @@ var ExtensionRow = new Lang.Class({
this._settings.set_strv('enabled-extensions', extensions);
},
_disable: function() {
_disable() {
let extensions = this._settings.get_strv('enabled-extensions');
let pos = extensions.indexOf(this.uuid);
if (pos == -1)
@ -378,11 +374,11 @@ function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
window.global = {
log: function() {
log() {
print([].join.call(arguments, ', '));
},
logError: function(s) {
logError(s) {
log('ERROR: ' + s);
},

View File

@ -41,7 +41,7 @@ var BeginRequestType = {
var AuthPrompt = new Lang.Class({
Name: 'AuthPrompt',
_init: function(gdmClient, mode) {
_init(gdmClient, mode) {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this._gdmClient = gdmClient;
@ -55,35 +55,33 @@ var AuthPrompt = new Lang.Class({
this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly: reauthenticationOnly });
this._userVerifier.connect('ask-question', Lang.bind(this, this._onAskQuestion));
this._userVerifier.connect('show-message', Lang.bind(this, this._onShowMessage));
this._userVerifier.connect('verification-failed', Lang.bind(this, this._onVerificationFailed));
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
this._userVerifier.connect('smartcard-status-changed', Lang.bind(this, this._onSmartcardStatusChanged));
this._userVerifier.connect('ovirt-user-authenticated', Lang.bind(this, this._onOVirtUserAuthenticated));
this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this));
this._userVerifier.connect('show-message', this._onShowMessage.bind(this));
this._userVerifier.connect('verification-failed', this._onVerificationFailed.bind(this));
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
this._userVerifier.connect('reset', this._onReset.bind(this));
this._userVerifier.connect('smartcard-status-changed', this._onSmartcardStatusChanged.bind(this));
this._userVerifier.connect('ovirt-user-authenticated', this._onOVirtUserAuthenticated.bind(this));
this.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('next', Lang.bind(this, function() {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
}));
this.connect('next', () => {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('key-press-event',
Lang.bind(this, function(actor, event) {
if (event.get_key_symbol() == Clutter.KEY_Escape) {
this.cancel();
}
return Clutter.EVENT_PROPAGATE;
}));
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('key-press-event', (actor, event) => {
if (event.get_key_symbol() == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
});
this._userWell = new St.Bin({ x_fill: true,
x_align: St.Align.START });
@ -136,21 +134,18 @@ var AuthPrompt = new Lang.Class({
this._defaultButtonWell.add_child(this._spinner.actor);
},
_onDestroy: function() {
_onDestroy() {
this._userVerifier.destroy();
this._userVerifier = null;
},
_initButtons: function() {
_initButtons() {
this.cancelButton = new St.Button({ style_class: 'modal-dialog-button button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
label: _("Cancel") });
this.cancelButton.connect('clicked',
Lang.bind(this, function() {
this.cancel();
}));
this.cancelButton.connect('clicked', () => { this.cancel(); });
this._buttonBox.add(this.cancelButton,
{ expand: false,
x_fill: false,
@ -169,10 +164,7 @@ var AuthPrompt = new Lang.Class({
reactive: true,
can_focus: true,
label: _("Next") });
this.nextButton.connect('clicked',
Lang.bind(this, function() {
this.emit('next');
}));
this.nextButton.connect('clicked', () => { this.emit('next'); });
this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add(this.nextButton,
{ expand: false,
@ -183,20 +175,19 @@ var AuthPrompt = new Lang.Class({
this._updateNextButtonSensitivity(this._entry.text.length > 0);
this._entry.clutter_text.connect('text-changed',
Lang.bind(this, function() {
if (!this._userVerifier.hasPendingMessages)
this._fadeOutMessage();
this._entry.clutter_text.connect('text-changed', () => {
if (!this._userVerifier.hasPendingMessages)
this._fadeOutMessage();
this._updateNextButtonSensitivity(this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING);
}));
this._entry.clutter_text.connect('activate', Lang.bind(this, function() {
this._updateNextButtonSensitivity(this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING);
});
this._entry.clutter_text.connect('activate', () => {
if (this.nextButton.reactive)
this.emit('next');
}));
});
},
_onAskQuestion: function(verifier, serviceName, question, passwordChar) {
_onAskQuestion(verifier, serviceName, question, passwordChar) {
if (this._queryingService)
this.clear();
@ -222,12 +213,12 @@ var AuthPrompt = new Lang.Class({
this.emit('prompted');
},
_onOVirtUserAuthenticated: function() {
_onOVirtUserAuthenticated() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
_onSmartcardStatusChanged: function() {
_onSmartcardStatusChanged() {
this.smartcardDetected = this._userVerifier.smartcardDetected;
// Most of the time we want to reset if the user inserts or removes
@ -246,36 +237,36 @@ var AuthPrompt = new Lang.Class({
this.reset();
},
_onShowMessage: function(userVerifier, message, type) {
_onShowMessage(userVerifier, message, type) {
this.setMessage(message, type);
this.emit('prompted');
},
_onVerificationFailed: function() {
_onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null;
this.clear();
this.updateSensitivity(true);
this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
},
_onVerificationComplete: function() {
_onVerificationComplete() {
this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
},
_onReset: function() {
_onReset() {
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.reset();
},
addActorToDefaultButtonWell: function(actor) {
addActorToDefaultButtonWell(actor) {
this._defaultButtonWell.add_child(actor);
},
setActorInDefaultButtonWell: function(actor, animate) {
setActorInDefaultButtonWell(actor, animate) {
if (!this._defaultButtonWellActor &&
!actor)
return;
@ -312,7 +303,7 @@ var AuthPrompt = new Lang.Class({
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
onComplete() {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
@ -339,25 +330,25 @@ var AuthPrompt = new Lang.Class({
this._defaultButtonWellActor = actor;
},
startSpinning: function() {
startSpinning() {
this.setActorInDefaultButtonWell(this._spinner.actor, true);
},
stopSpinning: function() {
stopSpinning() {
this.setActorInDefaultButtonWell(null, false);
},
clear: function() {
clear() {
this._entry.text = '';
this.stopSpinning();
},
setPasswordChar: function(passwordChar) {
setPasswordChar(passwordChar) {
this._entry.clutter_text.set_password_char(passwordChar);
this._entry.menu.isPassword = passwordChar != '';
},
setQuestion: function(question) {
setQuestion(question) {
this._label.set_text(question);
this._label.show();
@ -366,7 +357,7 @@ var AuthPrompt = new Lang.Class({
this._entry.grab_key_focus();
},
getAnswer: function() {
getAnswer() {
let text;
if (this._preemptiveAnswer) {
@ -379,7 +370,7 @@ var AuthPrompt = new Lang.Class({
return text;
},
_fadeOutMessage: function() {
_fadeOutMessage() {
if (this._message.opacity == 0)
return;
Tweener.removeTweens(this._message);
@ -390,7 +381,7 @@ var AuthPrompt = new Lang.Class({
});
},
setMessage: function(message, type) {
setMessage(message, type) {
if (type == GdmUtil.MessageType.ERROR)
this._message.add_style_class_name('login-dialog-message-warning');
else
@ -410,18 +401,18 @@ var AuthPrompt = new Lang.Class({
}
},
_updateNextButtonSensitivity: function(sensitive) {
_updateNextButtonSensitivity(sensitive) {
this.nextButton.reactive = sensitive;
this.nextButton.can_focus = sensitive;
},
updateSensitivity: function(sensitive) {
updateSensitivity(sensitive) {
this._updateNextButtonSensitivity(sensitive && (this._entry.text.length > 0 || this.verificationStatus == AuthPromptStatus.VERIFYING));
this._entry.reactive = sensitive;
this._entry.clutter_text.editable = sensitive;
},
hide: function() {
hide() {
this.setActorInDefaultButtonWell(null, true);
this.actor.hide();
this._message.opacity = 0;
@ -432,7 +423,7 @@ var AuthPrompt = new Lang.Class({
this._entry.set_text('');
},
setUser: function(user) {
setUser(user) {
let oldChild = this._userWell.get_child();
if (oldChild)
oldChild.destroy();
@ -443,11 +434,12 @@ var AuthPrompt = new Lang.Class({
}
},
reset: function() {
reset() {
let oldStatus = this.verificationStatus;
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true;
this.nextButton.label = _("Next");
this._preemptiveAnswer = null;
if (this._userVerifier)
this._userVerifier.cancel();
@ -480,7 +472,7 @@ var AuthPrompt = new Lang.Class({
this.emit('reset', beginRequestType);
},
addCharacter: function(unichar) {
addCharacter(unichar) {
if (!this._entry.visible)
return;
@ -488,7 +480,7 @@ var AuthPrompt = new Lang.Class({
this._entry.clutter_text.insert_unichar(unichar);
},
begin: function(params) {
begin(params) {
params = Params.parse(params, { userName: null,
hold: null });
@ -502,22 +494,21 @@ var AuthPrompt = new Lang.Class({
this.verificationStatus = AuthPromptStatus.VERIFYING;
},
finish: function(onComplete) {
finish(onComplete) {
if (!this._userVerifier.hasPendingMessages) {
this._userVerifier.clear();
onComplete();
return;
}
let signalId = this._userVerifier.connect('no-more-messages',
Lang.bind(this, function() {
this._userVerifier.disconnect(signalId);
this._userVerifier.clear();
onComplete();
}));
let signalId = this._userVerifier.connect('no-more-messages', () => {
this._userVerifier.disconnect(signalId);
this._userVerifier.clear();
onComplete();
});
},
cancel: function() {
cancel() {
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED) {
return;
}

View File

@ -50,7 +50,7 @@ const Signals = imports.signals;
var Task = new Lang.Class({
Name: 'Task',
_init: function(scope, handler) {
_init(scope, handler) {
if (scope)
this.scope = scope;
else
@ -59,7 +59,7 @@ var Task = new Lang.Class({
this.handler = handler;
},
run: function() {
run() {
if (this.handler)
return this.handler.call(this.scope);
@ -72,39 +72,37 @@ var Hold = new Lang.Class({
Name: 'Hold',
Extends: Task,
_init: function() {
this.parent(this, function () {
return this;
});
_init() {
this.parent(this, () => this);
this._acquisitions = 1;
},
acquire: function() {
acquire() {
if (this._acquisitions <= 0)
throw new Error("Cannot acquire hold after it's been released");
this._acquisitions++;
},
acquireUntilAfter: function(hold) {
acquireUntilAfter(hold) {
if (!hold.isAcquired())
return;
this.acquire();
let signalId = hold.connect('release', Lang.bind(this, function() {
hold.disconnect(signalId);
this.release();
}));
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.release();
});
},
release: function() {
release() {
this._acquisitions--;
if (this._acquisitions == 0)
this.emit('release');
},
isAcquired: function() {
isAcquired() {
return this._acquisitions > 0;
}
});
@ -114,7 +112,7 @@ var Batch = new Lang.Class({
Name: 'Batch',
Extends: Task,
_init: function(scope, tasks) {
_init(scope, tasks) {
this.parent();
this.tasks = [];
@ -134,11 +132,11 @@ var Batch = new Lang.Class({
}
},
process: function() {
process() {
throw new Error('Not implemented');
},
runTask: function() {
runTask() {
if (!(this._currentTaskIndex in this.tasks)) {
return null;
}
@ -146,11 +144,11 @@ var Batch = new Lang.Class({
return this.tasks[this._currentTaskIndex].run();
},
_finish: function() {
_finish() {
this.hold.release();
},
nextTask: function() {
nextTask() {
this._currentTaskIndex++;
// if the entire batch of tasks is finished, release
@ -163,7 +161,7 @@ var Batch = new Lang.Class({
this.process();
},
_start: function() {
_start() {
// acquire a hold to get released when the entire
// batch of tasks is finished
this.hold = new Hold();
@ -171,7 +169,7 @@ var Batch = new Lang.Class({
this.process();
},
run: function() {
run() {
this._start();
// hold may be destroyed at this point
@ -179,7 +177,7 @@ var Batch = new Lang.Class({
return this.hold;
},
cancel: function() {
cancel() {
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
}
});
@ -189,7 +187,7 @@ var ConcurrentBatch = new Lang.Class({
Name: 'ConcurrentBatch',
Extends: Batch,
process: function() {
process() {
let hold = this.runTask();
if (hold) {
@ -208,17 +206,16 @@ var ConsecutiveBatch = new Lang.Class({
Name: 'ConsecutiveBatch',
Extends: Batch,
process: function() {
process() {
let hold = this.runTask();
if (hold && hold.isAcquired()) {
// This task is inhibiting the batch. Wait on it
// before processing the next one.
let signalId = hold.connect('release',
Lang.bind(this, function() {
hold.disconnect(signalId);
this.nextTask();
}));
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one

View File

@ -5,13 +5,14 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = '<node> \
<interface name="net.reactivated.Fprint.Manager"> \
<method name="GetDefaultDevice"> \
<arg type="o" direction="out" /> \
</method> \
</interface> \
</node>';
const FprintManagerIface = `
<node>
<interface name="net.reactivated.Fprint.Manager">
<method name="GetDefaultDevice">
<arg type="o" direction="out" />
</method>
</interface>
</node>`;
const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(FprintManagerIface);

File diff suppressed because it is too large Load Diff

View File

@ -4,13 +4,13 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const OVirtCredentialsIface = '<node> \
<interface name="org.ovirt.vdsm.Credentials"> \
<signal name="UserAuthenticated"> \
<arg type="s" name="token"/> \
</signal> \
</interface> \
</node>';
const OVirtCredentialsIface =`<node>
<interface name="org.ovirt.vdsm.Credentials">
<signal name="UserAuthenticated">
<arg type="s" name="token"/>
</signal>
</interface>
</node>`;
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);
@ -29,28 +29,28 @@ function OVirtCredentials() {
var OVirtCredentialsManager = new Lang.Class({
Name: 'OVirtCredentialsManager',
_init: function() {
_init() {
this._token = null;
this._credentials = new OVirtCredentials();
this._credentials.connectSignal('UserAuthenticated',
Lang.bind(this, this._onUserAuthenticated));
this._onUserAuthenticated.bind(this));
},
_onUserAuthenticated: function(proxy, sender, [token]) {
_onUserAuthenticated(proxy, sender, [token]) {
this._token = token;
this.emit('user-authenticated', token);
},
hasToken: function() {
hasToken() {
return this._token != null;
},
getToken: function() {
getToken() {
return this._token;
},
resetToken: function() {
resetToken() {
this._token = null;
}
});

View File

@ -5,78 +5,81 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const ProviderIface = '<node> \
<interface name="org.freedesktop.realmd.Provider"> \
<property name="Name" type="s" access="read"/> \
<property name="Version" type="s" access="read"/> \
<property name="Realms" type="ao" access="read"/> \
<method name="Discover"> \
<arg name="string" type="s" direction="in"/> \
<arg name="options" type="a{sv}" direction="in"/> \
<arg name="relevance" type="i" direction="out"/> \
<arg name="realm" type="ao" direction="out"/> \
</method> \
</interface> \
</node>';
const ProviderIface = `
<node>
<interface name="org.freedesktop.realmd.Provider">
<property name="Name" type="s" access="read"/>
<property name="Version" type="s" access="read"/>
<property name="Realms" type="ao" access="read"/>
<method name="Discover">
<arg name="string" type="s" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
<arg name="relevance" type="i" direction="out"/>
<arg name="realm" type="ao" direction="out"/>
</method>
</interface>
</node>`;
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
const ServiceIface = '<node> \
<interface name="org.freedesktop.realmd.Service"> \
<method name="Cancel"> \
<arg name="operation" type="s" direction="in"/> \
</method> \
<method name="Release" /> \
<method name="SetLocale"> \
<arg name="locale" type="s" direction="in"/> \
</method> \
<signal name="Diagnostics"> \
<arg name="data" type="s"/> \
<arg name="operation" type="s"/> \
</signal> \
</interface> \
</node>';
const ServiceIface = `
<node>
<interface name="org.freedesktop.realmd.Service">
<method name="Cancel">
<arg name="operation" type="s" direction="in"/>
</method>
<method name="Release" />
<method name="SetLocale">
<arg name="locale" type="s" direction="in"/>
</method>
<signal name="Diagnostics">
<arg name="data" type="s"/>
<arg name="operation" type="s"/>
</signal>
</interface>
</node>`;
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = '<node> \
<interface name="org.freedesktop.realmd.Realm"> \
<property name="Name" type="s" access="read"/> \
<property name="Configured" type="s" access="read"/> \
<property name="Details" type="a(ss)" access="read"/> \
<property name="LoginFormats" type="as" access="read"/> \
<property name="LoginPolicy" type="s" access="read"/> \
<property name="PermittedLogins" type="as" access="read"/> \
<property name="SupportedInterfaces" type="as" access="read"/> \
<method name="ChangeLoginPolicy"> \
<arg name="login_policy" type="s" direction="in"/> \
<arg name="permitted_add" type="as" direction="in"/> \
<arg name="permitted_remove" type="as" direction="in"/> \
<arg name="options" type="a{sv}" direction="in"/> \
</method> \
<method name="Deconfigure"> \
<arg name="options" type="a{sv}" direction="in"/> \
</method> \
</interface> \
</node>';
const RealmIface = `
<node>
<interface name="org.freedesktop.realmd.Realm">
<property name="Name" type="s" access="read"/>
<property name="Configured" type="s" access="read"/>
<property name="Details" type="a(ss)" access="read"/>
<property name="LoginFormats" type="as" access="read"/>
<property name="LoginPolicy" type="s" access="read"/>
<property name="PermittedLogins" type="as" access="read"/>
<property name="SupportedInterfaces" type="as" access="read"/>
<method name="ChangeLoginPolicy">
<arg name="login_policy" type="s" direction="in"/>
<arg name="permitted_add" type="as" direction="in"/>
<arg name="permitted_remove" type="as" direction="in"/>
<arg name="options" type="a{sv}" direction="in"/>
</method>
<method name="Deconfigure">
<arg name="options" type="a{sv}" direction="in"/>
</method>
</interface>
</node>`;
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = new Lang.Class({
Name: 'Manager',
_init: function(parentActor) {
_init(parentActor) {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
Lang.bind(this, this._reloadRealms))
this._reloadRealms.bind(this))
this._realms = {};
this._signalId = this._aggregateProvider.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('Realms' in properties.deep_unpack())
this._reloadRealms();
}));
(proxy, properties) => {
if ('Realms' in properties.deep_unpack())
this._reloadRealms();
});
},
_reloadRealms: function() {
_reloadRealms() {
let realmPaths = this._aggregateProvider.Realms;
if (!realmPaths)
@ -86,11 +89,11 @@ var Manager = new Lang.Class({
let realm = Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
Lang.bind(this, this._onRealmLoaded));
this._onRealmLoaded.bind(this));
}
},
_reloadRealm: function(realm) {
_reloadRealm(realm) {
if (!realm.Configured) {
if (this._realms[realm.get_object_path()])
delete this._realms[realm.get_object_path()];
@ -103,20 +106,19 @@ var Manager = new Lang.Class({
this._updateLoginFormat();
},
_onRealmLoaded: function(realm, error) {
_onRealmLoaded(realm, error) {
if (error)
return;
this._reloadRealm(realm);
realm.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('Configured' in properties.deep_unpack())
this._reloadRealm(realm);
}));
realm.connect('g-properties-changed', (proxy, properties) => {
if ('Configured' in properties.deep_unpack())
this._reloadRealm(realm);
});
},
_updateLoginFormat: function() {
_updateLoginFormat() {
let newLoginFormat;
for (let realmPath in this._realms) {
@ -142,13 +144,11 @@ var Manager = new Lang.Class({
return this._loginFormat;
},
release: function() {
release() {
Service(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
function(service) {
service.ReleaseRemote();
});
service => { service.ReleaseRemote(); });
this._aggregateProvider.disconnect(this._signalId);
this._realms = { };
this._updateLoginFormat();

View File

@ -60,7 +60,7 @@ function fadeInActor(actor) {
height: naturalHeight,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
onComplete() {
this.set_height(-1);
hold.release();
},
@ -82,7 +82,7 @@ function fadeOutActor(actor) {
height: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
onComplete() {
this.hide();
this.set_height(-1);
hold.release();
@ -111,7 +111,7 @@ function cloneAndFadeOutActor(actor) {
{ opacity: 0,
time: CLONE_FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
onComplete() {
clone.destroy();
hold.release();
}
@ -122,7 +122,7 @@ function cloneAndFadeOutActor(actor) {
var ShellUserVerifier = new Lang.Class({
Name: 'ShellUserVerifier',
_init: function(client, params) {
_init(client, params) {
params = Params.parse(params, { reauthenticationOnly: false });
this._reauthOnly = params.reauthenticationOnly;
@ -133,7 +133,7 @@ var ShellUserVerifier = new Lang.Class({
this._settings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed',
Lang.bind(this, this._updateDefaultService));
this._updateDefaultService.bind(this));
this._updateDefaultService();
this._fprintManager = Fprint.FprintManager();
@ -147,9 +147,9 @@ var ShellUserVerifier = new Lang.Class({
this._checkForSmartcard();
this._smartcardInsertedId = this._smartcardManager.connect('smartcard-inserted',
Lang.bind(this, this._checkForSmartcard));
this._checkForSmartcard.bind(this));
this._smartcardRemovedId = this._smartcardManager.connect('smartcard-removed',
Lang.bind(this, this._checkForSmartcard));
this._checkForSmartcard.bind(this));
this._messageQueue = [];
this._messageQueueTimeoutId = 0;
@ -164,10 +164,10 @@ var ShellUserVerifier = new Lang.Class({
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated));
this._oVirtUserAuthenticated.bind(this));
},
begin: function(userName, hold) {
begin(userName, hold) {
this._cancellable = new Gio.Cancellable();
this._hold = hold;
this._userName = userName;
@ -179,13 +179,13 @@ var ShellUserVerifier = new Lang.Class({
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
this._client.open_reauthentication_channel(userName, this._cancellable,
Lang.bind(this, this._reauthenticationChannelOpened));
this._reauthenticationChannelOpened.bind(this));
} else {
this._client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
this._client.get_user_verifier(this._cancellable, this._userVerifierGot.bind(this));
}
},
cancel: function() {
cancel() {
if (this._cancellable)
this._cancellable.cancel();
@ -195,14 +195,14 @@ var ShellUserVerifier = new Lang.Class({
}
},
_clearUserVerifier: function() {
_clearUserVerifier() {
if (this._userVerifier) {
this._userVerifier.run_dispose();
this._userVerifier = null;
}
},
clear: function() {
clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
@ -212,7 +212,7 @@ var ShellUserVerifier = new Lang.Class({
this._clearMessageQueue();
},
destroy: function() {
destroy() {
this.clear();
this._settings.run_dispose();
@ -226,24 +226,23 @@ var ShellUserVerifier = new Lang.Class({
this._oVirtCredentialsManager = null;
},
answerQuery: function(serviceName, answer) {
answerQuery(serviceName, answer) {
if (!this.hasPendingMessages) {
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
} else {
let signalId = this.connect('no-more-messages',
Lang.bind(this, function() {
this.disconnect(signalId);
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
}));
let signalId = this.connect('no-more-messages', () => {
this.disconnect(signalId);
this._userVerifier.call_answer_query(serviceName, answer, this._cancellable, null);
});
}
},
_getIntervalForMessage: function(message) {
_getIntervalForMessage(message) {
// We probably could be smarter here
return message.length * USER_READ_TIME;
},
finishMessageQueue: function() {
finishMessageQueue() {
if (!this.hasPendingMessages)
return;
@ -253,7 +252,7 @@ var ShellUserVerifier = new Lang.Class({
this.emit('no-more-messages');
},
_queueMessageTimeout: function() {
_queueMessageTimeout() {
if (this._messageQueue.length == 0) {
this.finishMessageQueue();
return;
@ -268,15 +267,15 @@ var ShellUserVerifier = new Lang.Class({
this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
message.interval,
Lang.bind(this, function() {
() => {
this._messageQueueTimeoutId = 0;
this._queueMessageTimeout();
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout');
},
_queueMessage: function(message, messageType) {
_queueMessage(message, messageType) {
let interval = this._getIntervalForMessage(message);
this.hasPendingMessages = true;
@ -284,7 +283,7 @@ var ShellUserVerifier = new Lang.Class({
this._queueMessageTimeout();
},
_clearMessageQueue: function() {
_clearMessageQueue() {
this.finishMessageQueue();
if (this._messageQueueTimeoutId != 0) {
@ -294,7 +293,7 @@ var ShellUserVerifier = new Lang.Class({
this.emit('show-message', null, MessageType.NONE);
},
_checkForFingerprintReader: function() {
_checkForFingerprintReader() {
this._haveFingerprintReader = false;
if (!this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY) ||
@ -303,21 +302,21 @@ var ShellUserVerifier = new Lang.Class({
return;
}
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable, Lang.bind(this,
function(device, error) {
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, this._cancellable,
(device, error) => {
if (!error && device) {
this._haveFingerprintReader = true;
this._updateDefaultService();
}
}));
});
},
_oVirtUserAuthenticated: function(token) {
_oVirtUserAuthenticated(token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
},
_checkForSmartcard: function() {
_checkForSmartcard() {
let smartcardDetected;
if (!this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
@ -339,7 +338,7 @@ var ShellUserVerifier = new Lang.Class({
}
},
_reportInitError: function(where, error) {
_reportInitError(where, error) {
logError(error, where);
this._hold.release();
@ -347,20 +346,23 @@ var ShellUserVerifier = new Lang.Class({
this._verificationFailed(false);
},
_reauthenticationChannelOpened: function(client, result) {
_reauthenticationChannelOpened(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
!this._reauthOnly) {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is
// no session to reauthenticate. Fall back to performing verification
// from this login session
client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
!this._reauthOnly) {
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there
// is no session to reauthenticate. Fall back to performing
// verification from this login session
client.get_user_verifier(this._cancellable,
this._userVerifierGot.bind(this));
return;
}
this._reportInitError('Failed to open reauthentication channel', e);
return;
}
@ -371,13 +373,13 @@ var ShellUserVerifier = new Lang.Class({
this._hold.release();
},
_userVerifierGot: function(client, result) {
_userVerifierGot(client, result) {
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to obtain user verifier', e);
return;
}
@ -387,84 +389,89 @@ var ShellUserVerifier = new Lang.Class({
this._hold.release();
},
_connectSignals: function() {
this._userVerifier.connect('info', Lang.bind(this, this._onInfo));
this._userVerifier.connect('problem', Lang.bind(this, this._onProblem));
this._userVerifier.connect('info-query', Lang.bind(this, this._onInfoQuery));
this._userVerifier.connect('secret-info-query', Lang.bind(this, this._onSecretInfoQuery));
this._userVerifier.connect('conversation-stopped', Lang.bind(this, this._onConversationStopped));
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete));
_connectSignals() {
this._userVerifier.connect('info', this._onInfo.bind(this));
this._userVerifier.connect('problem', this._onProblem.bind(this));
this._userVerifier.connect('info-query', this._onInfoQuery.bind(this));
this._userVerifier.connect('secret-info-query', this._onSecretInfoQuery.bind(this));
this._userVerifier.connect('conversation-stopped', this._onConversationStopped.bind(this));
this._userVerifier.connect('reset', this._onReset.bind(this));
this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this));
},
_getForegroundService: function() {
_getForegroundService() {
if (this._preemptingService)
return this._preemptingService;
return this._defaultService;
},
serviceIsForeground: function(serviceName) {
serviceIsForeground(serviceName) {
return serviceName == this._getForegroundService();
},
serviceIsDefault: function(serviceName) {
serviceIsDefault(serviceName) {
return serviceName == this._defaultService;
},
_updateDefaultService: function() {
_updateDefaultService() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
this._defaultService = PASSWORD_SERVICE_NAME;
else if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
this._defaultService = SMARTCARD_SERVICE_NAME;
else if (this._haveFingerprintReader)
this._defaultService = FINGERPRINT_SERVICE_NAME;
if (!this._defaultService) {
log("no authentication service is enabled, using password authentication");
this._defaultService = PASSWORD_SERVICE_NAME;
}
},
_startService: function(serviceName) {
_startService(serviceName) {
this._hold.acquire();
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
(obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
}));
});
} else {
this._userVerifier.call_begin_verification(serviceName,
this._cancellable,
Lang.bind(this, function(obj, result) {
(obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
}));
});
}
},
_beginVerification: function() {
_beginVerification() {
this._startService(this._getForegroundService());
if (this._userName && this._haveFingerprintReader && !this.serviceIsForeground(FINGERPRINT_SERVICE_NAME))
this._startService(FINGERPRINT_SERVICE_NAME);
},
_onInfo: function(client, serviceName, info) {
_onInfo(client, serviceName, info) {
if (this.serviceIsForeground(serviceName)) {
this._queueMessage(info, MessageType.INFO);
} else if (serviceName == FINGERPRINT_SERVICE_NAME &&
@ -479,21 +486,21 @@ var ShellUserVerifier = new Lang.Class({
}
},
_onProblem: function(client, serviceName, problem) {
_onProblem(client, serviceName, problem) {
if (!this.serviceIsForeground(serviceName))
return;
this._queueMessage(problem, MessageType.ERROR);
},
_onInfoQuery: function(client, serviceName, question) {
_onInfoQuery(client, serviceName, question) {
if (!this.serviceIsForeground(serviceName))
return;
this.emit('ask-question', serviceName, question, '');
},
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
_onSecretInfoQuery(client, serviceName, secretQuestion) {
if (!this.serviceIsForeground(serviceName))
return;
@ -506,7 +513,7 @@ var ShellUserVerifier = new Lang.Class({
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
},
_onReset: function() {
_onReset() {
// Clear previous attempts to authenticate
this._failCounter = 0;
this._updateDefaultService();
@ -514,56 +521,55 @@ var ShellUserVerifier = new Lang.Class({
this.emit('reset');
},
_onVerificationComplete: function() {
_onVerificationComplete() {
this.emit('verification-complete');
},
_cancelAndReset: function() {
_cancelAndReset() {
this.cancel();
this._onReset();
},
_retry: function() {
_retry() {
this.begin(this._userName, new Batch.Hold());
},
_verificationFailed: function(retry) {
_verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset
// the dialog
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
// go back to the welcome screen.
// Otherwise, when in login mode we allow ALLOWED_FAILURES attempts.
// After that, we go back to the welcome screen.
this._failCounter++;
let canRetry = retry && this._userName &&
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
(this._reauthOnly ||
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY));
if (canRetry) {
if (!this.hasPendingMessages) {
this._retry();
} else {
let signalId = this.connect('no-more-messages',
Lang.bind(this, function() {
this.disconnect(signalId);
if (this._cancellable && !this._cancellable.is_cancelled())
this._retry();
}));
let signalId = this.connect('no-more-messages', () => {
this.disconnect(signalId);
if (this._cancellable && !this._cancellable.is_cancelled())
this._retry();
});
}
} else {
if (!this.hasPendingMessages) {
this._cancelAndReset();
} else {
let signalId = this.connect('no-more-messages',
Lang.bind(this, function() {
this.disconnect(signalId);
this._cancelAndReset();
}));
let signalId = this.connect('no-more-messages', () => {
this.disconnect(signalId);
this._cancelAndReset();
});
}
}
this.emit('verification-failed');
this.emit('verification-failed', canRetry);
},
_onConversationStopped: function(client, serviceName) {
_onConversationStopped(client, serviceName) {
// If the login failed with the preauthenticated oVirt credentials
// then discard the credentials and revert to default authentication
// mechanism.

View File

@ -9,8 +9,6 @@
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
@ -33,8 +31,6 @@
<file>perf/core.js</file>
<file>perf/hwtest.js</file>
<file>portalHelper/main.js</file>
<file>ui/accessDialog.js</file>
<file>ui/altTab.js</file>
<file>ui/animation.js</file>
@ -43,6 +39,7 @@
<file>ui/audioDeviceSelection.js</file>
<file>ui/backgroundMenu.js</file>
<file>ui/background.js</file>
<file>ui/barLevel.js</file>
<file>ui/boxpointer.js</file>
<file>ui/calendar.js</file>
<file>ui/checkBox.js</file>
@ -130,6 +127,7 @@
<file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file>
<file>ui/status/remoteAccess.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/status/thunderbolt.js</file>

View File

@ -6,3 +6,17 @@ js_resources = gnome.compile_resources(
c_name: 'shell_js_resources',
dependencies: [config_js]
)
portal_resources = gnome.compile_resources(
'portal-resources', 'portal-resources.gresource.xml',
source_dir: ['.', meson.current_build_dir()],
c_name: 'portal_js_resources',
dependencies: [config_js]
)
prefs_resources = gnome.compile_resources(
'prefs-resources', 'prefs-resources.gresource.xml',
source_dir: ['.', meson.current_build_dir()],
c_name: 'prefs_js_resources',
dependencies: [config_js]
)

View File

@ -112,6 +112,8 @@ function createExtensionObject(uuid, dir, type) {
let metadataContents, success, tag;
try {
[success, metadataContents, tag] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) {
throw new Error('Failed to load metadata.json: ' + e);
}
@ -161,7 +163,7 @@ function installImporter(extension) {
var ExtensionFinder = new Lang.Class({
Name: 'ExtensionFinder',
_loadExtension: function(extensionDir, info, perUserDir) {
_loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
@ -184,9 +186,11 @@ var ExtensionFinder = new Lang.Class({
this.emit('extension-found', extension);
},
scanExtensions: function() {
scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir));
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
this._loadExtension(dir, info, perUserDir);
});
}
});
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -4,17 +4,18 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const PresenceIface = '<node> \
<interface name="org.gnome.SessionManager.Presence"> \
<method name="SetStatus"> \
<arg type="u" direction="in"/> \
</method> \
<property name="status" type="u" access="readwrite"/> \
<signal name="StatusChanged"> \
<arg type="u" direction="out"/> \
</signal> \
</interface> \
</node>';
const PresenceIface = `
<node>
<interface name="org.gnome.SessionManager.Presence">
<method name="SetStatus">
<arg type="u" direction="in"/>
</method>
<property name="status" type="u" access="readwrite"/>
<signal name="StatusChanged">
<arg type="u" direction="out"/>
</signal>
</interface>
</node>`;
var PresenceStatus = {
AVAILABLE: 0,
@ -32,16 +33,17 @@ function Presence(initCallback, cancellable) {
// Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form
// of new inhibitors)
const InhibitorIface = '<node> \
<interface name="org.gnome.SessionManager.Inhibitor"> \
<method name="GetAppId"> \
<arg type="s" direction="out" /> \
</method> \
<method name="GetReason"> \
<arg type="s" direction="out" /> \
</method> \
</interface> \
</node>';
const InhibitorIface = `
<node>
<interface name="org.gnome.SessionManager.Inhibitor">
<method name="GetAppId">
<arg type="s" direction="out" />
</method>
<method name="GetReason">
<arg type="s" direction="out" />
</method>
</interface>
</node>`;
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
function Inhibitor(objectPath, initCallback, cancellable) {
@ -49,29 +51,30 @@ function Inhibitor(objectPath, initCallback, cancellable) {
}
// Not the full interface, only the methods we use
const SessionManagerIface = '<node> \
<interface name="org.gnome.SessionManager"> \
<method name="Logout"> \
<arg type="u" direction="in" /> \
</method> \
<method name="Shutdown" /> \
<method name="Reboot" /> \
<method name="CanShutdown"> \
<arg type="b" direction="out" /> \
</method> \
<method name="IsInhibited"> \
<arg type="u" direction="in" /> \
<arg type="b" direction="out" /> \
</method> \
<property name="SessionIsActive" type="b" access="read"/> \
<signal name="InhibitorAdded"> \
<arg type="o" direction="out"/> \
</signal> \
<signal name="InhibitorRemoved"> \
<arg type="o" direction="out"/> \
</signal> \
</interface> \
</node>';
const SessionManagerIface = `
<node>
<interface name="org.gnome.SessionManager">
<method name="Logout">
<arg type="u" direction="in" />
</method>
<method name="Shutdown" />
<method name="Reboot" />
<method name="CanShutdown">
<arg type="b" direction="out" />
</method>
<method name="IsInhibited">
<arg type="u" direction="in" />
<arg type="b" direction="out" />
</method>
<property name="SessionIsActive" type="b" access="read"/>
<signal name="InhibitorAdded">
<arg type="o" direction="out"/>
</signal>
<signal name="InhibitorRemoved">
<arg type="o" direction="out"/>
</signal>
</interface>
</node>`;
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
function SessionManager(initCallback, cancellable) {

View File

@ -10,7 +10,7 @@ var DEFAULT_LIMIT = 512;
var HistoryManager = new Lang.Class({
Name: 'HistoryManager',
_init: function(params) {
_init(params) {
params = Params.parse(params, { gsettingsKey: null,
limit: DEFAULT_LIMIT,
entry: null });
@ -22,7 +22,7 @@ var HistoryManager = new Lang.Class({
if (this._key) {
this._history = global.settings.get_strv(this._key);
global.settings.connect('changed::' + this._key,
Lang.bind(this, this._historyChanged));
this._historyChanged.bind(this));
} else {
this._history = [];
@ -32,16 +32,16 @@ var HistoryManager = new Lang.Class({
if (this._entry) {
this._entry.connect('key-press-event',
Lang.bind(this, this._onEntryKeyPress));
this._onEntryKeyPress.bind(this));
}
},
_historyChanged: function() {
_historyChanged() {
this._history = global.settings.get_strv(this._key);
this._historyIndex = this._history.length;
},
_setPrevItem: function(text) {
_setPrevItem(text) {
if (this._historyIndex <= 0)
return false;
@ -52,7 +52,7 @@ var HistoryManager = new Lang.Class({
return true;
},
_setNextItem: function(text) {
_setNextItem(text) {
if (this._historyIndex >= this._history.length)
return false;
@ -63,7 +63,7 @@ var HistoryManager = new Lang.Class({
return true;
},
lastItem: function() {
lastItem() {
if (this._historyIndex != this._history.length) {
this._historyIndex = this._history.length;
this._indexChanged();
@ -72,7 +72,7 @@ var HistoryManager = new Lang.Class({
return this._historyIndex ? this._history[this._historyIndex -1] : null;
},
addItem: function(input) {
addItem(input) {
if (this._history.length == 0 ||
this._history[this._history.length - 1] != input) {
@ -82,7 +82,7 @@ var HistoryManager = new Lang.Class({
this._historyIndex = this._history.length;
},
_onEntryKeyPress: function(entry, event) {
_onEntryKeyPress(entry, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Up) {
return this._setPrevItem(entry.get_text());
@ -92,7 +92,7 @@ var HistoryManager = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_indexChanged: function() {
_indexChanged() {
let current = this._history[this._historyIndex] || '';
this.emit('changed', current);
@ -100,7 +100,7 @@ var HistoryManager = new Lang.Class({
this._entry.set_text(current);
},
_save: function() {
_save() {
if (this._history.length > this._limit)
this._history.splice(0, this._history.length - this._limit);

View File

@ -40,7 +40,7 @@ var IBusManager = new Lang.Class({
_MAX_INPUT_SOURCE_ACTIVATION_TIME: 4000, // ms
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_init: function() {
_init() {
IBus.init();
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
@ -53,16 +53,16 @@ var IBusManager = new Lang.Class({
this._preloadEnginesId = 0;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
this._ibus.connect('connected', this._onConnected.bind(this));
this._ibus.connect('disconnected', this._clear.bind(this));
// Need to set this to get 'global-engine-changed' emitions
this._ibus.set_watch_ibus_signal(true);
this._ibus.connect('global-engine-changed', Lang.bind(this, this._engineChanged));
this._ibus.connect('global-engine-changed', this._engineChanged.bind(this));
this._spawn();
},
_spawn: function() {
_spawn() {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
@ -71,7 +71,7 @@ var IBusManager = new Lang.Class({
}
},
_clear: function() {
_clear() {
if (this._panelService)
this._panelService.destroy();
@ -87,15 +87,15 @@ var IBusManager = new Lang.Class({
this._spawn();
},
_onConnected: function() {
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
_onConnected() {
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
Lang.bind(this, this._initPanelService));
this._initPanelService.bind(this));
},
_initEngines: function(ibus, result) {
_initEngines(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
@ -108,13 +108,18 @@ var IBusManager = new Lang.Class({
}
},
_initPanelService: function(ibus, result) {
_initPanelService(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
this._panelService.connect('update-property', Lang.bind(this, this._updateProperty));
this._panelService.connect('update-property', this._updateProperty.bind(this));
this._panelService.connect('set-cursor-location', (ps, x, y, w, h) => {
let cursorLocation = { x, y, width: w, height: h };
this.emit('set-cursor-location', cursorLocation);
});
try {
// IBus versions older than 1.5.10 have a bug which
// causes spurious set-content-type emissions when
@ -122,11 +127,11 @@ var IBusManager = new Lang.Class({
// and hints defeating its intended semantics and
// confusing users. We thus don't use it in that case.
_checkIBusVersion(1, 5, 10);
this._panelService.connect('set-content-type', Lang.bind(this, this._setContentType));
this._panelService.connect('set-content-type', this._setContentType.bind(this));
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, Lang.bind(this, function(i, result) {
this._ibus.get_global_engine_async(-1, null, (i, result) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
@ -136,20 +141,20 @@ var IBusManager = new Lang.Class({
return;
}
this._engineChanged(this._ibus, engine.get_name());
}));
});
this._updateReadiness();
} else {
this._clear();
}
},
_updateReadiness: function() {
_updateReadiness() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this.emit('ready', this._ready);
},
_engineChanged: function(bus, engineName) {
_engineChanged(bus, engineName) {
if (!this._ready)
return;
@ -159,7 +164,7 @@ var IBusManager = new Lang.Class({
return;
this._registerPropertiesId =
this._panelService.connect('register-properties', Lang.bind(this, function(p, props) {
this._panelService.connect('register-properties', (p, props) => {
if (!props.get(0))
return;
@ -167,29 +172,29 @@ var IBusManager = new Lang.Class({
this._registerPropertiesId = 0;
this.emit('properties-registered', this._currentEngineName, props);
}));
});
},
_updateProperty: function(panel, prop) {
_updateProperty(panel, prop) {
this.emit('property-updated', this._currentEngineName, prop);
},
_setContentType: function(panel, purpose, hints) {
_setContentType(panel, purpose, hints) {
this.emit('set-content-type', purpose, hints);
},
activateProperty: function(key, state) {
activateProperty(key, state) {
this._panelService.property_activate(key, state);
},
getEngineDesc: function(id) {
getEngineDesc(id) {
if (!this._ready || !this._engines.hasOwnProperty(id))
return null;
return this._engines[id];
},
setEngine: function(id, callback) {
setEngine(id, callback) {
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
@ -203,7 +208,7 @@ var IBusManager = new Lang.Class({
null, callback);
},
preloadEngines: function(ids) {
preloadEngines(ids) {
if (!this._ibus || ids.length == 0)
return;
@ -214,7 +219,7 @@ var IBusManager = new Lang.Class({
this._preloadEnginesId =
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
Lang.bind(this, function() {
() => {
this._ibus.preload_engines_async(
ids,
-1,
@ -222,7 +227,7 @@ var IBusManager = new Lang.Class({
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
}));
});
},
});
Signals.addSignalMethods(IBusManager.prototype);

View File

@ -9,22 +9,29 @@ var InputMethod = new Lang.Class({
Name: 'InputMethod',
Extends: Clutter.InputMethod,
_init: function() {
_init() {
this.parent();
this._hints = 0;
this._purpose = 0;
this._enabled = true;
this._currentFocus = null;
this._currentEvent = null;
this._doForwardEvent = false;
this._preeditStr = '';
this._preeditPos = 0;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
this.connect('notify::can-show-preedit', Lang.bind(this, this._updateCapabilities));
this._ibus.connect('connected', this._onConnected.bind(this));
this._ibus.connect('disconnected', this._clear.bind(this));
this.connect('notify::can-show-preedit', this._updateCapabilities.bind(this));
this._inputSourceManager = Keyboard.getInputSourceManager();
this._sourceChangedId = this._inputSourceManager.connect('current-source-changed',
Lang.bind(this, this._onSourceChanged));
this._onSourceChanged.bind(this));
this._currentSource = this._inputSourceManager.currentSource;
let deviceManager = Clutter.DeviceManager.get_default();
this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
if (this._ibus.is_connected())
this._onConnected();
},
@ -33,7 +40,7 @@ var InputMethod = new Lang.Class({
return this._currentFocus;
},
_updateCapabilities: function() {
_updateCapabilities() {
let caps = 0;
if (this.can_show_preedit)
@ -48,55 +55,89 @@ var InputMethod = new Lang.Class({
this._context.set_capabilities(caps);
},
_onSourceChanged: function() {
_onSourceChanged() {
this._currentSource = this._inputSourceManager.currentSource;
},
_onConnected: function() {
_onConnected() {
this._ibus.create_input_context_async ('gnome-shell', -1, null,
Lang.bind(this, this._setContext));
this._setContext.bind(this));
},
_setContext: function(bus, res) {
_setContext(bus, res) {
this._context = this._ibus.create_input_context_async_finish(res);
this._context.connect('enabled', Lang.bind(this, function () { this._enabled = true }));
this._context.connect('disabled', Lang.bind(this, function () { this._enabled = false }));
this._context.connect('commit-text', Lang.bind(this, this._onCommitText));
this._context.connect('delete-surrounding-text', Lang.bind(this, this._onDeleteSurroundingText));
this._context.connect('update-preedit-text', Lang.bind(this, this._onUpdatePreeditText));
this._context.connect('enabled', () => { this._enabled = true });
this._context.connect('disabled', () => { this._enabled = false });
this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
this._context.connect('show-preedit-text', this._onShowPreeditText.bind(this));
this._context.connect('hide-preedit-text', this._onHidePreeditText.bind(this));
this._context.connect('forward-key-event', this._onForwardKeyEvent.bind(this));
this._updateCapabilities();
},
_clear: function() {
_clear() {
this._context = null;
this._hints = 0;
this._purpose = 0;
this._enabled = false;
this._preeditStr = ''
this._preeditPos = 0;
},
_emitRequestSurrounding: function() {
_emitRequestSurrounding() {
if (this._context.needs_surrounding_text())
this.emit('request-surrounding');
},
_onCommitText: function(context, text) {
_onCommitText(context, text) {
this.commit(text.get_text());
},
_onDeleteSurroundingText: function (context) {
_onDeleteSurroundingText(context) {
this.delete_surrounding();
},
_onUpdatePreeditText: function (context, text, pos, visible) {
let str = null;
if (visible && text != null)
str = text.get_text();
this.set_preedit_text(str, pos);
_onUpdatePreeditText(context, text, pos, visible) {
if (text == null)
return;
this._preeditStr = text.get_text();
this._preeditPos = pos;
if (visible)
this.set_preedit_text(this._preeditStr, pos);
else
this.set_preedit_text(null, pos);
},
vfunc_focus_in: function(focus) {
_onShowPreeditText(context) {
this.set_preedit_text(this._preeditStr, this._preeditPos);
},
_onHidePreeditText(context) {
this.set_preedit_text(null, this._preeditPos);
},
_onForwardKeyEvent(context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
if (this._currentEvent) {
// If we are handling this same event in filter_key_press(),
// just let it go through, sending the same event again will
// be silenced away because the key counts as pressed.
if (this._currentEvent.get_key_symbol() == keyval &&
(this._currentEvent.type() == Clutter.EventType.KEY_PRESS) == press) {
this._doForwardEvent = true;
return;
}
}
this._virtualDevice.notify_key(Clutter.get_current_event_time(), keycode,
press ? Clutter.KeyState.PRESSED : Clutter.KeyState.RELEASED);
},
vfunc_focus_in(focus) {
this._currentFocus = focus;
if (this._context) {
this._context.focus_in();
@ -105,7 +146,7 @@ var InputMethod = new Lang.Class({
}
},
vfunc_focus_out: function() {
vfunc_focus_out() {
this._currentFocus = null;
if (this._context) {
this._context.focus_out();
@ -116,7 +157,7 @@ var InputMethod = new Lang.Class({
this.set_preedit_text(null, 0);
},
vfunc_reset: function() {
vfunc_reset() {
if (this._context) {
this._context.reset();
this._emitRequestSurrounding();
@ -126,7 +167,7 @@ var InputMethod = new Lang.Class({
this.set_preedit_text(null, 0);
},
vfunc_set_cursor_location: function(rect) {
vfunc_set_cursor_location(rect) {
if (this._context) {
this._context.set_cursor_location(rect.get_x(), rect.get_y(),
rect.get_width(), rect.get_height());
@ -134,12 +175,12 @@ var InputMethod = new Lang.Class({
}
},
vfunc_set_surrounding: function(text, cursor, anchor) {
vfunc_set_surrounding(text, cursor, anchor) {
if (this._context)
this._context.set_surrounding_text(text, cursor, anchor);
},
vfunc_update_content_hints: function(hints) {
vfunc_update_content_hints(hints) {
let ibusHints = 0;
if (hints & Clutter.InputContentHintFlags.COMPLETION)
ibusHints |= IBus.InputHints.WORD_COMPLETION;
@ -159,7 +200,7 @@ var InputMethod = new Lang.Class({
this._context.set_content_type(this._purpose, this._hints);
},
vfunc_update_content_purpose: function(purpose) {
vfunc_update_content_purpose(purpose) {
let ibusPurpose = 0;
if (purpose == Clutter.InputContentPurpose.NORMAL)
ibusPurpose = IBus.InputPurpose.FREE_FORM;
@ -185,11 +226,10 @@ var InputMethod = new Lang.Class({
this._context.set_content_type(this._purpose, this._hints);
},
vfunc_filter_key_event: function(event) {
vfunc_filter_key_event(event) {
if (!this._context || !this._enabled)
return false;
if (!this._currentSource ||
this._currentSource.type == Keyboard.INPUT_SOURCE_TYPE_XKB)
if (!this._currentSource)
return false;
let state = event.get_state();
@ -198,17 +238,27 @@ var InputMethod = new Lang.Class({
if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK;
this._currentEvent = event;
this._doForwardEvent = false;
this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, null,
Lang.bind(this, (context, res) => {
(context, res) => {
try {
let retval = context.process_key_event_async_finish(res);
if (this._doForwardEvent)
retval = false;
this.notify_key_event(event, retval);
this._doForwardEvent = false;
this._currentEvent = null;
} catch (e) {
log('Error processing key on IM: ' + e.message);
}
}));
});
return true;
},
});

View File

@ -23,9 +23,9 @@ function getCompletions(text, commandHeader, globalCompletionList) {
if (matches) {
[expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
}
// Look for the empty expression or partially entered words
@ -33,9 +33,9 @@ function getCompletions(text, commandHeader, globalCompletionList) {
matches = text.match(/^(\w*)$/);
if (text == '' || matches) {
[expr, attrHead] = matches;
methods = globalCompletionList.filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
}
}
@ -175,7 +175,7 @@ function getPropertyNamesFromExpression(expr, commandHeader) {
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
allProps.map(function(p){ propsUnique[p] = null; });
allProps.map(p => propsUnique[p] = null);
}
return Object.keys(propsUnique).sort();
}
@ -233,7 +233,7 @@ function isUnsafeExpression(str) {
// Returns a list of global keywords derived from str
function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(function(s) {
str.split(';').forEach(s => {
let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/);
if (match) {

View File

@ -47,24 +47,24 @@ var KeyboardManager = new Lang.Class({
// even as a Wayland compositor, we can't bump this.
MAX_LAYOUTS_PER_GROUP: 4,
_init: function() {
_init() {
this._xkbInfo = getXkbInfo();
this._current = null;
this._localeLayoutInfo = this._getLocaleLayout();
this._layoutInfos = {};
},
_applyLayoutGroup: function(group) {
_applyLayoutGroup(group) {
let options = this._buildOptionsString();
let [layouts, variants] = this._buildGroupStrings(group);
Meta.get_backend().set_keymap(layouts, variants, options);
},
_applyLayoutGroupIndex: function(idx) {
_applyLayoutGroupIndex(idx) {
Meta.get_backend().lock_layout_group(idx);
},
apply: function(id) {
apply(id) {
let info = this._layoutInfos[id];
if (!info)
return;
@ -80,7 +80,7 @@ var KeyboardManager = new Lang.Class({
this._current = info;
},
reapply: function() {
reapply() {
if (!this._current)
return;
@ -88,7 +88,9 @@ var KeyboardManager = new Lang.Class({
this._applyLayoutGroupIndex(this._current.groupIndex);
},
setUserLayouts: function(ids) {
setUserLayouts(ids) {
let currentId = this._current ? this._current.id : null;
let currentGroupIndex = this._current ? this._current.groupIndex : null;
this._current = null;
this._layoutInfos = {};
@ -115,11 +117,14 @@ var KeyboardManager = new Lang.Class({
info.group = group;
info.groupIndex = groupIndex;
if (currentId == id && currentGroupIndex == groupIndex)
this._current = info;
i += 1;
}
},
_getLocaleLayout: function() {
_getLocaleLayout() {
let locale = GLib.get_language_names()[0];
if (locale.indexOf('_') == -1)
locale = DEFAULT_LOCALE;
@ -136,18 +141,18 @@ var KeyboardManager = new Lang.Class({
return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
},
_buildGroupStrings: function(_group) {
_buildGroupStrings(_group) {
let group = _group.concat(this._localeLayoutInfo);
let layouts = group.map(function(g) { return g.layout; }).join(',');
let variants = group.map(function(g) { return g.variant; }).join(',');
let layouts = group.map(g => g.layout).join(',');
let variants = group.map(g => g.variant).join(',');
return [layouts, variants];
},
setKeyboardOptions: function(options) {
setKeyboardOptions(options) {
this._xkbOptions = options;
},
_buildOptionsString: function() {
_buildOptionsString() {
let options = this._xkbOptions.join(',');
return options;
}

View File

@ -7,47 +7,60 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const SystemdLoginManagerIface = '<node> \
<interface name="org.freedesktop.login1.Manager"> \
<method name="Suspend"> \
<arg type="b" direction="in"/> \
</method> \
<method name="CanSuspend"> \
<arg type="s" direction="out"/> \
</method> \
<method name="Inhibit"> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="s" direction="in"/> \
<arg type="h" direction="out"/> \
</method> \
<method name="GetSession"> \
<arg type="s" direction="in"/> \
<arg type="o" direction="out"/> \
</method> \
<method name="ListSessions"> \
<arg name="sessions" type="a(susso)" direction="out"/> \
</method> \
<signal name="PrepareForSleep"> \
<arg type="b" direction="out"/> \
</signal> \
</interface> \
</node>';
const SystemdLoginManagerIface = `
<node>
<interface name="org.freedesktop.login1.Manager">
<method name="Suspend">
<arg type="b" direction="in"/>
</method>
<method name="CanSuspend">
<arg type="s" direction="out"/>
</method>
<method name="Inhibit">
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="h" direction="out"/>
</method>
<method name="GetSession">
<arg type="s" direction="in"/>
<arg type="o" direction="out"/>
</method>
<method name="ListSessions">
<arg name="sessions" type="a(susso)" direction="out"/>
</method>
<signal name="PrepareForSleep">
<arg type="b" direction="out"/>
</signal>
</interface>
</node>`;
const SystemdLoginSessionIface = '<node> \
<interface name="org.freedesktop.login1.Session"> \
<signal name="Lock" /> \
<signal name="Unlock" /> \
<property name="Active" type="b" access="read" /> \
<method name="SetLockedHint"> \
<arg type="b" direction="in"/> \
</method> \
</interface> \
</node>';
const SystemdLoginSessionIface = `
<node>
<interface name="org.freedesktop.login1.Session">
<signal name="Lock" />
<signal name="Unlock" />
<property name="Active" type="b" access="read" />
<property name="Class" type="s" access="read" />
<property name="Id" type="s" access="read" />
<method name="SetLockedHint">
<arg type="b" direction="in"/>
</method>
</interface>
</node>`;
const SystemdLoginUserIface = `
<node>
<interface name="org.freedesktop.login1.User">
<property name="Display" type="(so)" access="read" />
<property name="Sessions" type="a(so)" access="read" />
</interface>
</node>`;
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const SystemdLoginUser = Gio.DBusProxy.makeProxyWrapper(SystemdLoginUserIface);
function haveSystemd() {
return GLib.access("/run/systemd/seats", 0) >= 0;
@ -105,15 +118,18 @@ function getLoginManager() {
var LoginManagerSystemd = new Lang.Class({
Name: 'LoginManagerSystemd',
_init: function() {
_init() {
this._proxy = new SystemdLoginManager(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1');
this._userProxy = new SystemdLoginUser(Gio.DBus.system,
'org.freedesktop.login1',
'/org/freedesktop/login1/user/self');
this._proxy.connectSignal('PrepareForSleep',
Lang.bind(this, this._prepareForSleep));
this._prepareForSleep.bind(this));
},
getCurrentSessionProxy: function(callback) {
getCurrentSessionProxy(callback) {
if (this._currentSession) {
callback (this._currentSession);
return;
@ -121,25 +137,47 @@ var LoginManagerSystemd = new Lang.Class({
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session.');
return;
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.');
let [session, objectPath] = this._userProxy.Display;
if (session) {
log(`Will monitor session ${session}`);
sessionId = session;
} else {
log('Failed to find "Display" session; are we the greeter?');
for (let [session, objectPath] of this._userProxy.Sessions) {
let sessionProxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
objectPath);
log(`Considering ${session}, class=${sessionProxy.Class}`);
if (sessionProxy.Class == 'greeter') {
log(`Yes, will monitor session ${session}`);
sessionId = session;
break;
}
}
if (!sessionId) {
log('No, failed to get session from logind.');
return;
}
}
}
this._proxy.GetSessionRemote(sessionId, Lang.bind(this,
function(result, error) {
if (error) {
logError(error, 'Could not get a proxy for the current session');
} else {
this._currentSession = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
result[0]);
callback(this._currentSession);
}
}));
this._proxy.GetSessionRemote(sessionId, (result, error) => {
if (error) {
logError(error, 'Could not get a proxy for the current session');
} else {
this._currentSession = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
result[0]);
callback(this._currentSession);
}
});
},
canSuspend: function(asyncCallback) {
this._proxy.CanSuspendRemote(function(result, error) {
canSuspend(asyncCallback) {
this._proxy.CanSuspendRemote((result, error) => {
if (error) {
asyncCallback(false, false);
} else {
@ -150,8 +188,8 @@ var LoginManagerSystemd = new Lang.Class({
});
},
listSessions: function(asyncCallback) {
this._proxy.ListSessionsRemote(function(result, error) {
listSessions(asyncCallback) {
this._proxy.ListSessionsRemote((result, error) => {
if (error)
asyncCallback([]);
else
@ -159,18 +197,18 @@ var LoginManagerSystemd = new Lang.Class({
});
},
suspend: function() {
suspend() {
this._proxy.SuspendRemote(true);
},
inhibit: function(reason, callback) {
inhibit(reason, callback) {
let inVariant = GLib.Variant.new('(ssss)',
['sleep',
'GNOME Shell',
reason,
'delay']);
this._proxy.call_with_unix_fd_list('Inhibit', inVariant, 0, -1, null, null,
Lang.bind(this, function(proxy, result) {
(proxy, result) => {
let fd = -1;
try {
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
@ -180,10 +218,10 @@ var LoginManagerSystemd = new Lang.Class({
logError(e, "Error getting systemd inhibitor");
callback(null);
}
}));
});
},
_prepareForSleep: function(proxy, sender, [aboutToSuspend]) {
_prepareForSleep(proxy, sender, [aboutToSuspend]) {
this.emit('prepare-for-sleep', aboutToSuspend);
}
});
@ -192,26 +230,26 @@ Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = new Lang.Class({
Name: 'LoginManagerDummy',
getCurrentSessionProxy: function(callback) {
getCurrentSessionProxy(callback) {
// we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer
},
canSuspend: function(asyncCallback) {
canSuspend(asyncCallback) {
asyncCallback(false, false);
},
listSessions: function(asyncCallback) {
listSessions(asyncCallback) {
asyncCallback([]);
},
suspend: function() {
suspend() {
this.emit('prepare-for-sleep', true);
this.emit('prepare-for-sleep', false);
},
inhibit: function(reason, callback) {
inhibit(reason, callback) {
callback(null);
}
});

View File

@ -92,63 +92,65 @@ function _findProviderForSid(sid) {
// The following are not the complete interfaces, just the methods we need
// (or may need in the future)
const ModemGsmNetworkInterface = '<node> \
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> \
<method name="GetRegistrationInfo"> \
<arg type="(uss)" direction="out" /> \
</method> \
<method name="GetSignalQuality"> \
<arg type="u" direction="out" /> \
</method> \
<property name="AccessTechnology" type="u" access="read" /> \
<signal name="SignalQuality"> \
<arg type="u" direction="out" /> \
</signal> \
<signal name="RegistrationInfo"> \
<arg type="u" direction="out" /> \
<arg type="s" direction="out" /> \
<arg type="s" direction="out" /> \
</signal> \
</interface> \
</node>';
const ModemGsmNetworkInterface = `
<node>
<interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
<method name="GetRegistrationInfo">
<arg type="(uss)" direction="out" />
</method>
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<property name="AccessTechnology" type="u" access="read" />
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
<signal name="RegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</signal>
</interface>
</node>`;
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = '<node> \
<interface name="org.freedesktop.ModemManager.Modem.Cdma"> \
<method name="GetSignalQuality"> \
<arg type="u" direction="out" /> \
</method> \
<method name="GetServingSystem"> \
<arg type="(usu)" direction="out" /> \
</method> \
<signal name="SignalQuality"> \
<arg type="u" direction="out" /> \
</signal> \
</interface> \
</node>';
const ModemCdmaInterface = `
<node>
<interface name="org.freedesktop.ModemManager.Modem.Cdma">
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<method name="GetServingSystem">
<arg type="(usu)" direction="out" />
</method>
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
</interface>
</node>`;
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
var ModemGsm = new Lang.Class({
Name: 'ModemGsm',
_init: function(path) {
_init(path) {
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
// Code is duplicated because the function have different signatures
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
this._proxy.connectSignal('SignalQuality', (proxy, sender, [quality]) => {
this.signal_quality = quality;
this.emit('notify::signal-quality');
}));
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
});
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [status, code, name]) => {
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
}));
this._proxy.GetRegistrationInfoRemote(Lang.bind(this, function([result], err) {
});
this._proxy.GetRegistrationInfoRemote(([result], err) => {
if (err) {
log(err);
return;
@ -157,8 +159,8 @@ var ModemGsm = new Lang.Class({
let [status, code, name] = result;
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
}));
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
});
this._proxy.GetSignalQualityRemote((result, err) => {
if (err) {
// it will return an error if the device is not connected
this.signal_quality = 0;
@ -167,7 +169,7 @@ var ModemGsm = new Lang.Class({
this.signal_quality = quality;
}
this.emit('notify::signal-quality');
}));
});
}
});
Signals.addSignalMethods(ModemGsm.prototype);
@ -175,12 +177,12 @@ Signals.addSignalMethods(ModemGsm.prototype);
var ModemCdma = new Lang.Class({
Name: 'ModemCdma',
_init: function(path) {
_init(path) {
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
this._proxy.connectSignal('SignalQuality', (proxy, sender, params) => {
this.signal_quality = params[0];
this.emit('notify::signal-quality');
@ -188,8 +190,8 @@ var ModemCdma = new Lang.Class({
// and we can finally call GetServingSystem
if (this.operator_name == null)
this._refreshServingSystem();
}));
this._proxy.GetSignalQualityRemote(Lang.bind(this, function(result, err) {
});
this._proxy.GetSignalQualityRemote((result, err) => {
if (err) {
// it will return an error if the device is not connected
this.signal_quality = 0;
@ -198,11 +200,11 @@ var ModemCdma = new Lang.Class({
this.signal_quality = quality;
}
this.emit('notify::signal-quality');
}));
});
},
_refreshServingSystem: function() {
this._proxy.GetServingSystemRemote(Lang.bind(this, function([result], err) {
_refreshServingSystem() {
this._proxy.GetServingSystemRemote(([result], err) => {
if (err) {
// it will return an error if the device is not connected
this.operator_name = null;
@ -212,7 +214,7 @@ var ModemCdma = new Lang.Class({
this.operator_name = _findProviderForSid(sid)
}
this.emit('notify::operator-name');
}));
});
}
});
Signals.addSignalMethods(ModemCdma.prototype);
@ -222,65 +224,68 @@ Signals.addSignalMethods(ModemCdma.prototype);
// Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------
const BroadbandModemInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem"> \
<property name="SignalQuality" type="(ub)" access="read" /> \
</interface> \
</node>';
const BroadbandModemInterface = `
<node>
<interface name="org.freedesktop.ModemManager1.Modem">
<property name="SignalQuality" type="(ub)" access="read" />
</interface>
</node>`;
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
const BroadbandModem3gppInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> \
<property name="OperatorCode" type="s" access="read" /> \
<property name="OperatorName" type="s" access="read" /> \
</interface> \
</node>';
const BroadbandModem3gppInterface = `
<node>
<interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp">
<property name="OperatorCode" type="s" access="read" />
<property name="OperatorName" type="s" access="read" />
</interface>
</node>`;
const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
const BroadbandModemCdmaInterface = '<node> \
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \
<property name="Sid" type="u" access="read" /> \
</interface> \
</node>';
const BroadbandModemCdmaInterface = `
<node>
<interface name="org.freedesktop.ModemManager1.Modem.ModemCdma">
<property name="Sid" type="u" access="read" />
</interface>
</node>`;
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
var BroadbandModem = new Lang.Class({
Name: 'BroadbandModem',
_init: function(path, capabilities) {
_init(path, capabilities) {
this._proxy = new BroadbandModemProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_3gpp = new BroadbandModem3gppProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._proxy_cdma = new BroadbandModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager1', path);
this._capabilities = capabilities;
this._proxy.connect('g-properties-changed', Lang.bind(this, function(proxy, properties) {
this._proxy.connect('g-properties-changed', (proxy, properties) => {
if ('SignalQuality' in properties.deep_unpack())
this._reloadSignalQuality();
}));
});
this._reloadSignalQuality();
this._proxy_3gpp.connect('g-properties-changed', Lang.bind(this, function(proxy, properties) {
this._proxy_3gpp.connect('g-properties-changed', (proxy, properties) => {
let unpacked = properties.deep_unpack();
if ('OperatorName' in unpacked || 'OperatorCode' in unpacked)
this._reload3gppOperatorName();
}));
});
this._reload3gppOperatorName();
this._proxy_cdma.connect('g-properties-changed', Lang.bind(this, function(proxy, properties) {
this._proxy_cdma.connect('g-properties-changed', (proxy, properties) => {
let unpacked = properties.deep_unpack();
if ('Nid' in unpacked || 'Sid' in unpacked)
this._reloadCdmaOperatorName();
}));
});
this._reloadCdmaOperatorName();
},
_reloadSignalQuality: function() {
_reloadSignalQuality() {
let [quality, recent] = this._proxy.SignalQuality;
this.signal_quality = quality;
this.emit('notify::signal-quality');
},
_reloadOperatorName: function() {
_reloadOperatorName() {
let new_name = "";
if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0)
new_name += this.operator_name_3gpp;
@ -295,14 +300,14 @@ var BroadbandModem = new Lang.Class({
this.emit('notify::operator-name');
},
_reload3gppOperatorName: function() {
_reload3gppOperatorName() {
let name = this._proxy_3gpp.OperatorName;
let code = this._proxy_3gpp.OperatorCode;
this.operator_name_3gpp = _findProviderForMccMnc(name, code);
this._reloadOperatorName();
},
_reloadCdmaOperatorName: function() {
_reloadCdmaOperatorName() {
let sid = this._proxy_cdma.Sid;
this.operator_name_cdma = _findProviderForSid(sid);
this._reloadOperatorName();

View File

@ -8,27 +8,28 @@ const Signals = imports.signals;
// Specified in the D-Bus specification here:
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
const ObjectManagerIface = '<node> \
<interface name="org.freedesktop.DBus.ObjectManager"> \
<method name="GetManagedObjects"> \
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/> \
</method> \
<signal name="InterfacesAdded"> \
<arg name="objectPath" type="o"/> \
<arg name="interfaces" type="a{sa{sv}}" /> \
</signal> \
<signal name="InterfacesRemoved"> \
<arg name="objectPath" type="o"/> \
<arg name="interfaces" type="as" /> \
</signal> \
</interface> \
</node>';
const ObjectManagerIface = `
<node>
<interface name="org.freedesktop.DBus.ObjectManager">
<method name="GetManagedObjects">
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/>
</method>
<signal name="InterfacesAdded">
<arg name="objectPath" type="o"/>
<arg name="interfaces" type="a{sa{sv}}" />
</signal>
<signal name="InterfacesRemoved">
<arg name="objectPath" type="o"/>
<arg name="interfaces" type="as" />
</signal>
</interface>
</node>`;
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
var ObjectManager = new Lang.Class({
Name: 'ObjectManager',
_init: function(params) {
_init(params) {
params = Params.parse(params, { connection: null,
name: null,
objectPath: null,
@ -61,10 +62,10 @@ var ObjectManager = new Lang.Class({
this._numLoadInhibitors = 1;
this._managerProxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, this._onManagerProxyLoaded));
this._onManagerProxyLoaded.bind(this));
},
_tryToCompleteLoad: function() {
_tryToCompleteLoad() {
if (this._numLoadInhibitors == 0)
return;
@ -75,7 +76,7 @@ var ObjectManager = new Lang.Class({
}
},
_addInterface: function(objectPath, interfaceName, onFinished) {
_addInterface(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
if (!info) {
@ -93,7 +94,7 @@ var ObjectManager = new Lang.Class({
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, function(initable, result) {
(initable, result) => {
let error = null;
try {
initable.init_finish(result);
@ -127,10 +128,10 @@ var ObjectManager = new Lang.Class({
if (onFinished)
onFinished();
}));
});
},
_removeInterface: function(objectPath, interfaceName) {
_removeInterface(objectPath, interfaceName) {
if (!this._objects[objectPath])
return;
@ -156,7 +157,7 @@ var ObjectManager = new Lang.Class({
}
},
_onManagerProxyLoaded: function(initable, result) {
_onManagerProxyLoaded(initable, result) {
let error = null;
try {
initable.init_finish(result);
@ -168,35 +169,35 @@ var ObjectManager = new Lang.Class({
}
this._managerProxy.connectSignal('InterfacesAdded',
Lang.bind(this, function(objectManager, sender, [objectPath, interfaces]) {
(objectManager, sender, [objectPath, interfaces]) => {
let interfaceNames = Object.keys(interfaces);
for (let i = 0; i < interfaceNames.length; i++)
this._addInterface(objectPath, interfaceNames[i]);
}));
});
this._managerProxy.connectSignal('InterfacesRemoved',
Lang.bind(this, function(objectManager, sender, [objectPath, interfaceNames]) {
(objectManager, sender, [objectPath, interfaceNames]) => {
for (let i = 0; i < interfaceNames.length; i++)
this._removeInterface(objectPath, interfaceNames[i]);
}));
});
if (Object.keys(this._interfaceInfos).length == 0) {
this._tryToCompleteLoad();
return;
}
this._managerProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
this._managerProxy.connect('notify::g-name-owner', () => {
if (this._managerProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
}));
});
if (this._managerProxy.g_name_owner)
this._onNameAppeared();
},
_onNameAppeared: function() {
this._managerProxy.GetManagedObjectsRemote(Lang.bind(this, function(result, error) {
_onNameAppeared() {
this._managerProxy.GetManagedObjectsRemote((result, error) => {
if (!result) {
if (error) {
logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
@ -226,14 +227,14 @@ var ObjectManager = new Lang.Class({
this._numLoadInhibitors++;
this._addInterface(objectPath,
interfaceName,
Lang.bind(this, this._tryToCompleteLoad));
this._tryToCompleteLoad.bind(this));
}
}
this._tryToCompleteLoad();
}));
});
},
_onNameVanished: function() {
_onNameVanished() {
let objectPaths = Object.keys(this._objects);
for (let i = 0; i < objectPaths.length; i++) {
let object = this._objects[objectPaths];
@ -248,14 +249,14 @@ var ObjectManager = new Lang.Class({
}
},
_registerInterfaces: function(interfaces) {
_registerInterfaces(interfaces) {
for (let i = 0; i < interfaces.length; i++) {
let info = Gio.DBusInterfaceInfo.new_for_xml(interfaces[i]);
this._interfaceInfos[info.name] = info;
}
},
getProxy: function(objectPath, interfaceName) {
getProxy(objectPath, interfaceName) {
let object = this._objects[objectPath];
if (!object)
@ -264,7 +265,7 @@ var ObjectManager = new Lang.Class({
return object[interfaceName];
},
getProxiesForInterface: function(interfaceName) {
getProxiesForInterface(interfaceName) {
let proxyList = this._interfaces[interfaceName];
if (!proxyList)
@ -273,7 +274,7 @@ var ObjectManager = new Lang.Class({
return proxyList;
},
getAllProxies: function() {
getAllProxies() {
let proxies = [];
let objectPaths = Object.keys(this._objects);

View File

@ -2,7 +2,7 @@
// parse:
// @params: caller-provided parameter object, or %null
// @defaults: function-provided defaults object
// @defaults-provided defaults object
// @allowExtras: whether or not to allow properties not in @default
//
// Examines @params and fills in default values from @defaults for

View File

@ -2,30 +2,31 @@
const Gio = imports.gi.Gio;
const PermissionStoreIface = '<node> \
<interface name="org.freedesktop.impl.portal.PermissionStore"> \
<method name="Lookup"> \
<arg name="table" type="s" direction="in"/> \
<arg name="id" type="s" direction="in"/> \
<arg name="permissions" type="a{sas}" direction="out"/> \
<arg name="data" type="v" direction="out"/> \
</method> \
<method name="Set"> \
<arg name="table" type="s" direction="in"/> \
<arg name="create" type="b" direction="in"/> \
<arg name="id" type="s" direction="in"/> \
<arg name="app_permissions" type="a{sas}" direction="in"/> \
<arg name="data" type="v" direction="in"/> \
</method> \
<signal name="Changed"> \
<arg name="table" type="s" direction="out"/> \
<arg name="id" type="s" direction="out"/> \
<arg name="deleted" type="b" direction="out"/> \
<arg name="data" type="v" direction="out"/> \
<arg name="permissions" type="a{sas}" direction="out"/> \
</signal> \
</interface> \
</node>';
const PermissionStoreIface = `
<node>
<interface name="org.freedesktop.impl.portal.PermissionStore">
<method name="Lookup">
<arg name="table" type="s" direction="in"/>
<arg name="id" type="s" direction="in"/>
<arg name="permissions" type="a{sas}" direction="out"/>
<arg name="data" type="v" direction="out"/>
</method>
<method name="Set">
<arg name="table" type="s" direction="in"/>
<arg name="create" type="b" direction="in"/>
<arg name="id" type="s" direction="in"/>
<arg name="app_permissions" type="a{sas}" direction="in"/>
<arg name="data" type="v" direction="in"/>
</method>
<signal name="Changed">
<arg name="table" type="s" direction="out"/>
<arg name="id" type="s" direction="out"/>
<arg name="deleted" type="b" direction="out"/>
<arg name="data" type="v" direction="out"/>
<arg name="permissions" type="a{sas}" direction="out"/>
</signal>
</interface>
</node>`;
const PermissionStoreProxy = Gio.DBusProxy.makeProxyWrapper(PermissionStoreIface);

View File

@ -7,14 +7,15 @@ const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager;
const SmartcardTokenIface = '<node> \
<interface name="org.gnome.SettingsDaemon.Smartcard.Token"> \
<property name="Name" type="s" access="read"/> \
<property name="Driver" type="o" access="read"/> \
<property name="IsInserted" type="b" access="read"/> \
<property name="UsedToLogin" type="b" access="read"/> \
</interface> \
</node>';
const SmartcardTokenIface = `
<node>
<interface name="org.gnome.SettingsDaemon.Smartcard.Token">
<property name="Name" type="s" access="read"/>
<property name="Driver" type="o" access="read"/>
<property name="IsInserted" type="b" access="read"/>
<property name="UsedToLogin" type="b" access="read"/>
</interface>
</node>`;
let _smartcardManager = null;
@ -27,34 +28,34 @@ function getSmartcardManager() {
var SmartcardManager = new Lang.Class({
Name: 'SmartcardManager',
_init: function() {
_init() {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
knownInterfaces: [ SmartcardTokenIface ],
onLoaded: Lang.bind(this, this._onLoaded) });
onLoaded: this._onLoaded.bind(this) });
this._insertedTokens = {};
this._loginToken = null;
},
_onLoaded: function() {
_onLoaded() {
let tokens = this._objectManager.getProxiesForInterface('org.gnome.SettingsDaemon.Smartcard.Token');
for (let i = 0; i < tokens.length; i++)
this._addToken(tokens[i]);
this._objectManager.connect('interface-added', Lang.bind(this, function(objectManager, interfaceName, proxy) {
this._objectManager.connect('interface-added', (objectManager, interfaceName, proxy) => {
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._addToken(proxy);
}));
});
this._objectManager.connect('interface-removed', Lang.bind(this, function(objectManager, interfaceName, proxy) {
this._objectManager.connect('interface-removed', (objectManager, interfaceName, proxy) => {
if (interfaceName == 'org.gnome.SettingsDaemon.Smartcard.Token')
this._removeToken(proxy);
}));
});
},
_updateToken: function(token) {
_updateToken(token) {
let objectPath = token.get_object_path();
delete this._insertedTokens[objectPath];
@ -66,28 +67,27 @@ var SmartcardManager = new Lang.Class({
this._loginToken = token;
},
_addToken: function(token) {
_addToken(token) {
this._updateToken(token);
token.connect('g-properties-changed',
Lang.bind(this, function(proxy, properties) {
if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token);
token.connect('g-properties-changed', (proxy, properties) => {
if ('IsInserted' in properties.deep_unpack()) {
this._updateToken(token);
if (token.IsInserted) {
this.emit('smartcard-inserted', token);
} else {
this.emit('smartcard-removed', token);
}
}
}));
if (token.IsInserted) {
this.emit('smartcard-inserted', token);
} else {
this.emit('smartcard-removed', token);
}
}
});
// Emit a smartcard-inserted at startup if it's already plugged in
if (token.IsInserted)
this.emit('smartcard-inserted', token);
},
_removeToken: function(token) {
_removeToken(token) {
let objectPath = token.get_object_path();
if (this._insertedTokens[objectPath] == token) {
@ -101,11 +101,11 @@ var SmartcardManager = new Lang.Class({
token.disconnectAll();
},
hasInsertedTokens: function() {
hasInsertedTokens() {
return Object.keys(this._insertedTokens).length > 0;
},
hasInsertedLoginToken: function() {
hasInsertedLoginToken() {
if (!this._loginToken)
return false;

View File

@ -22,11 +22,12 @@ const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
const SENSOR_BUS_NAME = 'net.hadess.SensorProxy';
const SENSOR_OBJECT_PATH = '/net/hadess/SensorProxy';
const SensorProxyInterface = '<node> \
<interface name="net.hadess.SensorProxy"> \
<property name="HasAccelerometer" type="b" access="read"/> \
</interface> \
</node>';
const SensorProxyInterface = `
<node>
<interface name="net.hadess.SensorProxy">
<property name="HasAccelerometer" type="b" access="read"/>
</interface>
</node>`;
const POWER_OFF_ACTION_ID = 'power-off';
const LOCK_SCREEN_ACTION_ID = 'lock-screen';
@ -87,7 +88,7 @@ const SystemActions = new Lang.Class({
null)
},
_init: function() {
_init() {
this.parent();
this._canHavePowerOff = true;
@ -218,7 +219,7 @@ const SystemActions = new Lang.Class({
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
},
_sensorProxyAppeared: function() {
_sensorProxyAppeared() {
this._sensorProxy = new SensorProxy(Gio.DBus.system, SENSOR_BUS_NAME, SENSOR_OBJECT_PATH,
(proxy, error) => {
if (error) {
@ -231,7 +232,7 @@ const SystemActions = new Lang.Class({
});
},
_updateOrientationLock: function() {
_updateOrientationLock() {
let available = false;
if (this._sensorProxy)
available = this._sensorProxy.HasAccelerometer &&
@ -242,7 +243,7 @@ const SystemActions = new Lang.Class({
this.notify('can-lock-orientation');
},
_updateOrientationLockIcon: function() {
_updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock');
let iconName = locked ? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic';
@ -251,14 +252,14 @@ const SystemActions = new Lang.Class({
this.notify('orientation-lock-icon');
},
_sessionUpdated: function() {
_sessionUpdated() {
this._updateLockScreen();
this._updatePowerOff();
this._updateSuspend();
this._updateMultiUser();
},
forceUpdate: function() {
forceUpdate() {
// Whether those actions are available or not depends on both lockdown
// settings and Polkit policy - we don't get change notifications for the
// latter, so their value may be outdated; force an update now
@ -266,7 +267,7 @@ const SystemActions = new Lang.Class({
this._updateHaveSuspend();
},
getMatchingActions: function(terms) {
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map((term) => { return term.toLowerCase(); });
@ -279,15 +280,15 @@ const SystemActions = new Lang.Class({
return results;
},
getName: function(id) {
getName(id) {
return this._actions.get(id).name;
},
getIconName: function(id) {
getIconName(id) {
return this._actions.get(id).iconName;
},
activateAction: function(id) {
activateAction(id) {
switch (id) {
case POWER_OFF_ACTION_ID:
this.activatePowerOff();
@ -317,7 +318,7 @@ const SystemActions = new Lang.Class({
this.notify('can-lock-screen');
},
_updateHaveShutdown: function() {
_updateHaveShutdown() {
this._session.CanShutdownRemote((result, error) => {
if (error)
return;
@ -327,7 +328,7 @@ const SystemActions = new Lang.Class({
});
},
_updatePowerOff: function() {
_updatePowerOff() {
let disabled = Main.sessionMode.isLocked ||
(Main.sessionMode.isGreeter &&
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
@ -335,7 +336,7 @@ const SystemActions = new Lang.Class({
this.notify('can-power-off');
},
_updateHaveSuspend: function() {
_updateHaveSuspend() {
this._loginManager.canSuspend(
(canSuspend, needsAuth) => {
this._canHaveSuspend = canSuspend;
@ -344,7 +345,7 @@ const SystemActions = new Lang.Class({
});
},
_updateSuspend: function() {
_updateSuspend() {
let disabled = (Main.sessionMode.isLocked &&
this._suspendNeedsAuth) ||
(Main.sessionMode.isGreeter &&
@ -353,12 +354,12 @@ const SystemActions = new Lang.Class({
this.notify('can-suspend');
},
_updateMultiUser: function() {
_updateMultiUser() {
this._updateLogout();
this._updateSwitchUser();
},
_updateSwitchUser: function() {
_updateSwitchUser() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
let multiUser = this._userManager.can_switch() && this._userManager.has_multiple_users;
let shouldShowInMode = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
@ -370,7 +371,7 @@ const SystemActions = new Lang.Class({
return visible;
},
_updateLogout: function() {
_updateLogout() {
let user = this._userManager.get_user(GLib.get_user_name());
let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY);
@ -388,7 +389,7 @@ const SystemActions = new Lang.Class({
return visible;
},
activateLockOrientation: function() {
activateLockOrientation() {
if (!this._actions.get(LOCK_ORIENTATION_ACTION_ID).available)
throw new Error('The lock-orientation action is not available!');
@ -396,27 +397,27 @@ const SystemActions = new Lang.Class({
this._orientationSettings.set_boolean('orientation-lock', !locked);
},
activateLockScreen: function() {
activateLockScreen() {
if (!this._actions.get(LOCK_SCREEN_ACTION_ID).available)
throw new Error('The lock-screen action is not available!');
Main.screenShield.lock(true);
},
activateSwitchUser: function() {
activateSwitchUser() {
if (!this._actions.get(SWITCH_USER_ACTION_ID).available)
throw new Error('The switch-user action is not available!');
if (Main.screenShield)
Main.screenShield.lock(false);
Clutter.threads_add_repaint_func_full(Clutter.RepaintFlags.POST_PAINT, function() {
Clutter.threads_add_repaint_func_full(Clutter.RepaintFlags.POST_PAINT, () => {
Gdm.goto_login_session_sync(null);
return false;
});
},
activateLogout: function() {
activateLogout() {
if (!this._actions.get(LOGOUT_ACTION_ID).available)
throw new Error('The logout action is not available!');
@ -424,14 +425,14 @@ const SystemActions = new Lang.Class({
this._session.LogoutRemote(0);
},
activatePowerOff: function() {
activatePowerOff() {
if (!this._actions.get(POWER_OFF_ACTION_ID).available)
throw new Error('The power-off action is not available!');
this._session.ShutdownRemote(0);
},
activateSuspend: function() {
activateSuspend() {
if (!this._actions.get(SUSPEND_ACTION_ID).available)
throw new Error('The suspend action is not available!');

View File

@ -17,7 +17,7 @@ const Params = imports.misc.params;
var SCROLL_TIME = 0.1;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)';
const _balancedParens = '\\([^\\s()<>]+\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
@ -136,7 +136,7 @@ function trySpawn(argv)
// Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function () {});
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, () => {});
}
// trySpawnCommandLine:
@ -291,12 +291,10 @@ function createTimeLabel(date, params) {
_desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
let label = new St.Label({ text: formatTime(date, params) });
let id = _desktopSettings.connect('changed::clock-format', function() {
let id = _desktopSettings.connect('changed::clock-format', () => {
label.text = formatTime(date, params);
});
label.connect('destroy', function() {
_desktopSettings.disconnect(id);
});
label.connect('destroy', () => { _desktopSettings.disconnect(id); });
return label;
}
@ -316,7 +314,7 @@ function createTimeLabel(date, params) {
function lowerBound(array, val, cmp) {
let min, max, mid, v;
cmp = cmp || function(a, b) { return a - b; };
cmp = cmp || ((a, b) => a - b);
if (array.length == 0)
return 0;
@ -354,7 +352,7 @@ var CloseButton = new Lang.Class({
Name: 'CloseButton',
Extends: St.Button,
_init: function(boxpointer) {
_init(boxpointer) {
this.parent({ style_class: 'notification-close'});
// This is a bit tricky. St.Bin has its own x-align/y-align properties
@ -371,10 +369,10 @@ var CloseButton = new Lang.Class({
this._boxPointer = boxpointer;
if (boxpointer)
this._boxPointer.connect('arrow-side-changed', Lang.bind(this, this._sync));
this._boxPointer.connect('arrow-side-changed', this._sync.bind(this));
},
_computeBoxPointerOffset: function() {
_computeBoxPointerOffset() {
if (!this._boxPointer || !this._boxPointer.actor.get_stage())
return 0;
@ -385,7 +383,7 @@ var CloseButton = new Lang.Class({
return 0;
},
_sync: function() {
_sync() {
let themeNode = this.get_theme_node();
let offY = this._computeBoxPointerOffset();
@ -393,7 +391,7 @@ var CloseButton = new Lang.Class({
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
},
vfunc_style_changed: function() {
vfunc_style_changed() {
this._sync();
this.parent();
},
@ -442,7 +440,7 @@ function ensureActorVisibleInScrollView(scrollView, actor) {
var AppSettingsMonitor = new Lang.Class({
Name: 'AppSettingsMonitor',
_init: function(appId, schemaId) {
_init(appId, schemaId) {
this._appId = appId;
this._schemaId = schemaId;
@ -454,7 +452,7 @@ var AppSettingsMonitor = new Lang.Class({
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
Lang.bind(this, this._onInstalledChanged));
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
},
@ -462,19 +460,19 @@ var AppSettingsMonitor = new Lang.Class({
return this._app != null && this._settings != null;
},
activateApp: function() {
activateApp() {
if (this._app)
this._app.activate();
},
watchSetting: function(key, callback) {
watchSetting(key, callback) {
let handler = { id: 0, key: key, callback: callback };
this._handlers.push(handler);
this._connectHandler(handler);
},
_connectHandler: function(handler) {
_connectHandler(handler) {
if (!this._settings || handler.id > 0)
return;
@ -483,13 +481,13 @@ var AppSettingsMonitor = new Lang.Class({
handler.callback(this._settings, handler.key);
},
_disconnectHandler: function(handler) {
_disconnectHandler(handler) {
if (this._settings && handler.id > 0)
this._settings.disconnect(handler.id);
handler.id = 0;
},
_onInstalledChanged: function() {
_onInstalledChanged() {
let hadApp = (this._app != null);
this._app = this._appSystem.lookup_app(this._appId);
let haveApp = (this._app != null);
@ -503,7 +501,7 @@ var AppSettingsMonitor = new Lang.Class({
this._setSettings(null);
},
_setSettings: function(settings) {
_setSettings(settings) {
this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
let hadSettings = (this._settings != null);
@ -516,7 +514,7 @@ var AppSettingsMonitor = new Lang.Class({
this.emit('available-changed');
},
_checkSettings: function() {
_checkSettings() {
let schema = this._schemaSource.lookup(this._schemaId, true);
if (schema) {
this._setSettings(new Gio.Settings({ settings_schema: schema }));

View File

@ -16,7 +16,7 @@ var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
var WeatherClient = new Lang.Class({
Name: 'WeatherClient',
_init: function() {
_init() {
this._loading = false;
this._locationValid = false;
this._lastUpdate = GLib.DateTime.new_from_unix_local(0);
@ -46,11 +46,11 @@ var WeatherClient = new Lang.Class({
});
});
this._permStore.connectSignal('Changed',
Lang.bind(this, this._onPermStoreChanged));
this._onPermStoreChanged.bind(this));
this._locationSettings = new Gio.Settings({ schema_id: 'org.gnome.system.location' });
this._locationSettings.connect('changed::enabled',
Lang.bind(this, this._updateAutoLocation));
this._updateAutoLocation.bind(this));
this._world = GWeather.Location.get_world();
@ -68,9 +68,9 @@ var WeatherClient = new Lang.Class({
'org.gnome.Weather.Application');
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
this._weatherAppMon.watchSetting('automatic-location',
Lang.bind(this, this._onAutomaticLocationChanged));
this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations',
Lang.bind(this, this._onLocationsChanged));
this._onLocationsChanged.bind(this));
},
get available() {
@ -89,11 +89,11 @@ var WeatherClient = new Lang.Class({
return this._weatherInfo;
},
activateApp: function() {
activateApp() {
this._weatherAppMon.activateApp();
},
update: function() {
update() {
if (!this._locationValid)
return;
@ -112,7 +112,7 @@ var WeatherClient = new Lang.Class({
this._weatherAuthorized;
},
_loadInfo: function() {
_loadInfo() {
let id = this._weatherInfo.connect('updated', () => {
this._weatherInfo.disconnect(id);
this._loading = false;
@ -124,7 +124,7 @@ var WeatherClient = new Lang.Class({
this._weatherInfo.update();
},
_locationsEqual: function(loc1, loc2) {
_locationsEqual(loc1, loc2) {
if (loc1 == loc2)
return true;
@ -134,7 +134,7 @@ var WeatherClient = new Lang.Class({
return loc1.equal(loc2);
},
_setLocation: function(location) {
_setLocation(location) {
if (this._locationsEqual(this._weatherInfo.location, location))
return;
@ -150,14 +150,14 @@ var WeatherClient = new Lang.Class({
this.emit('changed');
},
_updateLocationMonitoring: function() {
_updateLocationMonitoring() {
if (this._useAutoLocation) {
if (this._gclueLocationChangedId != 0 || this._gclueService == null)
return;
this._gclueLocationChangedId =
this._gclueService.connect('notify::location',
Lang.bind(this, this._onGClueLocationChanged));
this._onGClueLocationChanged.bind(this));
this._onGClueLocationChanged();
} else {
if (this._gclueLocationChangedId)
@ -166,7 +166,7 @@ var WeatherClient = new Lang.Class({
}
},
_startGClueService: function() {
_startGClueService() {
if (this._gclueStarting)
return;
@ -187,7 +187,7 @@ var WeatherClient = new Lang.Class({
});
},
_onGClueLocationChanged: function() {
_onGClueLocationChanged() {
let geoLocation = this._gclueService.location;
let location = GWeather.Location.new_detached(geoLocation.description,
null,
@ -196,7 +196,7 @@ var WeatherClient = new Lang.Class({
this._setLocation(location);
},
_onAutomaticLocationChanged: function(settings, key) {
_onAutomaticLocationChanged(settings, key) {
let useAutoLocation = settings.get_boolean(key);
if (this._autoLocationRequested == useAutoLocation)
return;
@ -206,7 +206,7 @@ var WeatherClient = new Lang.Class({
this._updateAutoLocation();
},
_updateAutoLocation: function() {
_updateAutoLocation() {
this._updateLocationMonitoring();
if (this._useAutoLocation)
@ -215,7 +215,7 @@ var WeatherClient = new Lang.Class({
this._setLocation(this._mostRecentLocation);
},
_onLocationsChanged: function(settings, key) {
_onLocationsChanged(settings, key) {
let serialized = settings.get_value(key).deep_unpack().shift();
let mostRecentLocation = null;
@ -231,7 +231,7 @@ var WeatherClient = new Lang.Class({
this._setLocation(this._mostRecentLocation);
},
_onPermStoreChanged: function(proxy, sender, params) {
_onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted, data, perms] = params;
if (table != 'gnome' || id != 'geolocation')

View File

@ -75,9 +75,9 @@ function run() {
// Enable recording of timestamps for different points in the frame cycle
global.frame_timestamps = true;
Main.overview.connect('shown', function() {
Scripting.scriptEvent('overviewShowDone');
});
Main.overview.connect('shown', () => {
Scripting.scriptEvent('overviewShowDone');
});
yield Scripting.sleep(1000);

View File

@ -42,35 +42,29 @@ function waitAndDraw(milliseconds) {
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame',
function(timeline, frame) {
global.stage.queue_redraw();
});
timeline.connect('new-frame', (timeline, frame) => {
global.stage.queue_redraw();
});
timeline.connect('completed',
function() {
timeline.stop();
if (cb)
cb();
});
timeline.connect('completed', () => {
timeline.stop();
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
return callback => { cb = callback; };
}
function waitSignal(object, signal) {
let cb;
let id = object.connect(signal, function() {
let id = object.connect(signal, () => {
object.disconnect(id);
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
return callback => { cb = callback; };
}
function extractBootTimestamp() {
@ -142,8 +136,7 @@ function run() {
global.frame_finish_timestamp = true;
for (let k = 0; k < 5; k++)
yield Scripting.createTestWindow(640, 480,
{ maximized: true });
yield Scripting.createTestWindow({ maximized: true });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
@ -164,8 +157,7 @@ function run() {
yield Scripting.destroyTestWindows();
Main.overview.hide();
yield Scripting.createTestWindow(640, 480,
{ maximized: true,
yield Scripting.createTestWindow({ maximized: true,
redraws: true});
yield Scripting.waitTestWindows();
@ -270,7 +262,7 @@ function script_redrawTestDone(time) {
function script_collectTimings(time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort(function(a, b) { return a - b });
times.sort((a, b) => a - b);
let len = times.length;
let median;

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>misc/config.js</file>
<file>portalHelper/main.js</file>
</gresource>
</gresources>

View File

@ -30,31 +30,32 @@ const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
const HelperDBusInterface = '<node> \
<interface name="org.gnome.Shell.PortalHelper"> \
<method name="Authenticate"> \
<arg type="o" direction="in" name="connection" /> \
<arg type="s" direction="in" name="url" /> \
<arg type="u" direction="in" name="timestamp" /> \
</method> \
<method name="Close"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<method name="Refresh"> \
<arg type="o" direction="in" name="connection" /> \
</method> \
<signal name="Done"> \
<arg type="o" name="connection" /> \
<arg type="u" name="result" /> \
</signal> \
</interface> \
</node>';
const HelperDBusInterface = `
<node>
<interface name="org.gnome.Shell.PortalHelper">
<method name="Authenticate">
<arg type="o" direction="in" name="connection" />
<arg type="s" direction="in" name="url" />
<arg type="u" direction="in" name="timestamp" />
</method>
<method name="Close">
<arg type="o" direction="in" name="connection" />
</method>
<method name="Refresh">
<arg type="o" direction="in" name="connection" />
</method>
<signal name="Done">
<arg type="o" name="connection" />
<arg type="u" name="result" />
</signal>
</interface>
</node>`;
var PortalHeaderBar = new Lang.Class({
Name: 'PortalHeaderBar',
Extends: Gtk.HeaderBar,
_init: function() {
_init() {
this.parent({ show_close_button: true });
// See ephy-title-box.c in epiphany for the layout
@ -92,11 +93,11 @@ var PortalHeaderBar = new Lang.Class({
vbox.show_all();
},
setSubtitle: function(label) {
setSubtitle(label) {
this.subtitleLabel.set_text(label);
},
setSecurityIcon: function(securityLevel) {
setSecurityIcon(securityLevel) {
switch (securityLevel) {
case PortalHelperSecurityLevel.NOT_YET_DETERMINED:
this._lockImage.hide();
@ -119,10 +120,10 @@ var PortalWindow = new Lang.Class({
Name: 'PortalWindow',
Extends: Gtk.ApplicationWindow,
_init: function(application, url, timestamp, doneCallback) {
_init(application, url, timestamp, doneCallback) {
this.parent({ application: application });
this.connect('delete-event', Lang.bind(this, this.destroyWindow));
this.connect('delete-event', this.destroyWindow.bind(this));
this._headerBar = new PortalHeaderBar();
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.NOT_YET_DETERMINED);
this.set_titlebar(this._headerBar);
@ -146,12 +147,12 @@ var PortalWindow = new Lang.Class({
this._webContext.set_network_proxy_settings(WebKit.NetworkProxyMode.NO_PROXY, null);
this._webView = WebKit.WebView.new_with_context(this._webContext);
this._webView.connect('decide-policy', Lang.bind(this, this._onDecidePolicy));
this._webView.connect('load-changed', Lang.bind(this, this._onLoadChanged));
this._webView.connect('insecure-content-detected', Lang.bind(this, this._onInsecureContentDetected));
this._webView.connect('load-failed-with-tls-errors', Lang.bind(this, this._onLoadFailedWithTlsErrors));
this._webView.connect('decide-policy', this._onDecidePolicy.bind(this));
this._webView.connect('load-changed', this._onLoadChanged.bind(this));
this._webView.connect('insecure-content-detected', this._onInsecureContentDetected.bind(this));
this._webView.connect('load-failed-with-tls-errors', this._onLoadFailedWithTlsErrors.bind(this));
this._webView.load_uri(url);
this._webView.connect('notify::uri', Lang.bind(this, this._syncUri));
this._webView.connect('notify::uri', this._syncUri.bind(this));
this._syncUri();
this.add(this._webView);
@ -163,11 +164,11 @@ var PortalWindow = new Lang.Class({
this.application.set_accels_for_action('app.quit', ['<Primary>q', '<Primary>w']);
},
destroyWindow: function() {
destroyWindow() {
this.destroy();
},
_syncUri: function() {
_syncUri() {
let uri = this._webView.uri;
if (uri)
this._headerBar.setSubtitle(GLib.uri_unescape_string(uri, null));
@ -175,12 +176,12 @@ var PortalWindow = new Lang.Class({
this._headerBar.setSubtitle('');
},
refresh: function() {
refresh() {
this._everSeenRedirect = false;
this._webView.load_uri(this._originalUrl);
},
vfunc_delete_event: function(event) {
vfunc_delete_event(event) {
if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK);
else
@ -188,7 +189,7 @@ var PortalWindow = new Lang.Class({
return false;
},
_onLoadChanged: function(view, loadEvent) {
_onLoadChanged(view, loadEvent) {
if (loadEvent == WebKit.LoadEvent.STARTED) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.NOT_YET_DETERMINED);
} else if (loadEvent == WebKit.LoadEvent.COMMITTED) {
@ -202,11 +203,11 @@ var PortalWindow = new Lang.Class({
}
},
_onInsecureContentDetected: function () {
_onInsecureContentDetected() {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
},
_onLoadFailedWithTlsErrors: function (view, failingURI, certificate, errors) {
_onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
let uri = new Soup.URI(failingURI);
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());
@ -214,7 +215,7 @@ var PortalWindow = new Lang.Class({
return true;
},
_onDecidePolicy: function(view, decision, type) {
_onDecidePolicy(view, decision, type) {
if (type == WebKit.PolicyDecisionType.NEW_WINDOW_ACTION) {
let navigationAction = decision.get_navigation_action();
if (navigationAction.is_user_gesture()) {
@ -286,7 +287,7 @@ var WebPortalHelper = new Lang.Class({
Name: 'WebPortalHelper',
Extends: Gtk.Application,
_init: function() {
_init() {
this.parent({ application_id: 'org.gnome.Shell.PortalHelper',
flags: Gio.ApplicationFlags.IS_SERVICE,
inactivity_timeout: 30000 });
@ -299,30 +300,30 @@ var WebPortalHelper = new Lang.Class({
this.add_action(action);
},
vfunc_dbus_register: function(connection, path) {
vfunc_dbus_register(connection, path) {
this._dbusImpl.export(connection, path);
this.parent(connection, path);
return true;
},
vfunc_dbus_unregister: function(connection, path) {
vfunc_dbus_unregister(connection, path) {
this._dbusImpl.unexport_from_connection(connection);
this.parent(connection, path);
},
vfunc_activate: function() {
vfunc_activate() {
// If launched manually (for example for testing), force a dummy authentication
// session with the default url
this.Authenticate('/org/gnome/dummy', '', 0);
},
Authenticate: function(connection, url, timestamp) {
Authenticate(connection, url, timestamp) {
this._queue.push({ connection: connection, url: url, timestamp: timestamp });
this._processQueue();
},
Close: function(connection) {
Close(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
@ -337,7 +338,7 @@ var WebPortalHelper = new Lang.Class({
this._processQueue();
},
Refresh: function(connection) {
Refresh(connection) {
for (let i = 0; i < this._queue.length; i++) {
let obj = this._queue[i];
@ -349,7 +350,7 @@ var WebPortalHelper = new Lang.Class({
}
},
_processQueue: function() {
_processQueue() {
if (this._queue.length == 0)
return;
@ -357,9 +358,9 @@ var WebPortalHelper = new Lang.Class({
if (top.window != null)
return;
top.window = new PortalWindow(this, top.url, top.timestamp, Lang.bind(this, function(result) {
top.window = new PortalWindow(this, top.url, top.timestamp, result => {
this._dbusImpl.emit_signal('Done', new GLib.Variant('(ou)', [top.connection, result]));
}));
});
},
});

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/params.js</file>
</gresource>
</gresources>

View File

@ -10,27 +10,29 @@ const CheckBox = imports.ui.checkBox;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
const RequestIface = '<node> \
<interface name="org.freedesktop.impl.portal.Request"> \
<method name="Close"/> \
</interface> \
</node>';
const RequestIface = `
<node>
<interface name="org.freedesktop.impl.portal.Request">
<method name="Close"/>
</interface>
</node>`;
const AccessIface = '<node> \
<interface name="org.freedesktop.impl.portal.Access"> \
<method name="AccessDialog"> \
<arg type="o" name="handle" direction="in"/> \
<arg type="s" name="app_id" direction="in"/> \
<arg type="s" name="parent_window" direction="in"/> \
<arg type="s" name="title" direction="in"/> \
<arg type="s" name="subtitle" direction="in"/> \
<arg type="s" name="body" direction="in"/> \
<arg type="a{sv}" name="options" direction="in"/> \
<arg type="u" name="response" direction="out"/> \
<arg type="a{sv}" name="results" direction="out"/> \
</method> \
</interface> \
</node>';
const AccessIface = `
<node>
<interface name="org.freedesktop.impl.portal.Access">
<method name="AccessDialog">
<arg type="o" name="handle" direction="in"/>
<arg type="s" name="app_id" direction="in"/>
<arg type="s" name="parent_window" direction="in"/>
<arg type="s" name="title" direction="in"/>
<arg type="s" name="subtitle" direction="in"/>
<arg type="s" name="body" direction="in"/>
<arg type="a{sv}" name="options" direction="in"/>
<arg type="u" name="response" direction="out"/>
<arg type="a{sv}" name="results" direction="out"/>
</method>
</interface>
</node>`;
var DialogResponse = {
OK: 0,
@ -42,7 +44,7 @@ var AccessDialog = new Lang.Class({
Name: 'AccessDialog',
Extends: ModalDialog.ModalDialog,
_init: function(invocation, handle, title, subtitle, body, options) {
_init(invocation, handle, title, subtitle, body, options) {
this.parent({ styleClass: 'access-dialog' });
this._invocation = invocation;
@ -57,7 +59,7 @@ var AccessDialog = new Lang.Class({
this._buildLayout(title, subtitle, body, options);
},
_buildLayout: function(title, subtitle, body, options) {
_buildLayout(title, subtitle, body, options) {
// No support for non-modal system dialogs, so ignore the option
//let modal = options['modal'] || true;
let denyLabel = options['deny_label'] || _("Deny Access");
@ -97,14 +99,14 @@ var AccessDialog = new Lang.Class({
}});
},
open: function() {
open() {
this.parent();
let connection = this._invocation.get_connection();
this._requestExported = this._request.export(connection, this._handle);
},
CloseAsync: function(invocation, params) {
CloseAsync(invocation, params) {
if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
@ -115,7 +117,7 @@ var AccessDialog = new Lang.Class({
this._sendResponse(DialogResponse.CLOSED);
},
_sendResponse: function(response) {
_sendResponse(response) {
if (this._requestExported)
this._request.unexport();
this._requestExported = false;
@ -140,7 +142,7 @@ var AccessDialog = new Lang.Class({
var AccessDialogDBus = new Lang.Class({
Name: 'AccessDialogDBus',
_init: function() {
_init() {
this._accessDialog = null;
this._windowTracker = Shell.WindowTracker.get_default();
@ -151,7 +153,7 @@ var AccessDialogDBus = new Lang.Class({
Gio.DBus.session.own_name('org.freedesktop.impl.portal.desktop.gnome', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
AccessDialogAsync: function(params, invocation) {
AccessDialogAsync(params, invocation) {
if (this._accessDialog) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.LIMITS_EXCEEDED,

View File

@ -62,7 +62,7 @@ var AppSwitcherPopup = new Lang.Class({
Name: 'AppSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init : function() {
_init() {
this.parent();
this._thumbnails = null;
@ -80,7 +80,7 @@ var AppSwitcherPopup = new Lang.Class({
this._items = this._switcherList.icons;
},
_allocate: function (actor, box, flags) {
_allocate(actor, box, flags) {
this.parent(actor, box, flags);
// Allocate the thumbnails
@ -118,7 +118,7 @@ var AppSwitcherPopup = new Lang.Class({
}
},
_initialSelection: function(backward, binding) {
_initialSelection(backward, binding) {
if (binding == 'switch-group') {
if (backward) {
this._select(0, this._items[0].cachedWindows.length - 1);
@ -141,14 +141,14 @@ var AppSwitcherPopup = new Lang.Class({
}
},
_nextWindow : function() {
_nextWindow() {
// We actually want the second window if we're in the unset state
if (this._currentWindow == -1)
this._currentWindow = 0;
return SwitcherPopup.mod(this._currentWindow + 1,
this._items[this._selectedIndex].cachedWindows.length);
},
_previousWindow : function() {
_previousWindow() {
// Also assume second window here
if (this._currentWindow == -1)
this._currentWindow = 1;
@ -156,7 +156,7 @@ var AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length);
},
_closeAppWindow: function(appIndex, windowIndex) {
_closeAppWindow(appIndex, windowIndex) {
let appIcon = this._items[appIndex];
if (!appIcon)
return;
@ -168,7 +168,7 @@ var AppSwitcherPopup = new Lang.Class({
window.delete(global.get_current_time());
},
_quitApplication: function(appIndex) {
_quitApplication(appIndex) {
let appIcon = this._items[appIndex];
if (!appIcon)
return;
@ -176,7 +176,7 @@ var AppSwitcherPopup = new Lang.Class({
appIcon.app.request_quit();
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
if (!this._thumbnailsFocused)
this._select(this._selectedIndex, 0);
@ -215,7 +215,7 @@ var AppSwitcherPopup = new Lang.Class({
return Clutter.EVENT_STOP;
},
_scrollHandler: function(direction) {
_scrollHandler(direction) {
if (direction == Clutter.ScrollDirection.UP) {
if (this._thumbnailsFocused) {
if (this._currentWindow == 0 || this._currentWindow == -1)
@ -245,7 +245,7 @@ var AppSwitcherPopup = new Lang.Class({
}
},
_itemActivatedHandler: function(n) {
_itemActivatedHandler(n) {
// If the user clicks on the selected app, activate the
// selected window; otherwise (eg, they click on an app while
// !mouseActive) activate the clicked-on app.
@ -255,24 +255,24 @@ var AppSwitcherPopup = new Lang.Class({
this._select(n);
},
_itemEnteredHandler: function(n) {
_itemEnteredHandler(n) {
this._select(n);
},
_windowActivated : function(thumbnailList, n) {
_windowActivated(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
Main.activateWindow(appIcon.cachedWindows[n]);
this.destroy();
},
_windowEntered : function(thumbnailList, n) {
_windowEntered(thumbnailList, n) {
if (!this.mouseActive)
return;
this._select(this._selectedIndex, n);
},
_windowRemoved : function(thumbnailList, n) {
_windowRemoved(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
if (!appIcon)
return;
@ -283,7 +283,7 @@ var AppSwitcherPopup = new Lang.Class({
}
},
_finish : function(timestamp) {
_finish(timestamp) {
let appIcon = this._items[this._selectedIndex];
if (this._currentWindow < 0)
appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp);
@ -293,7 +293,7 @@ var AppSwitcherPopup = new Lang.Class({
this.parent();
},
_onDestroy : function() {
_onDestroy() {
this.parent();
if (this._thumbnails)
@ -327,7 +327,7 @@ var AppSwitcherPopup = new Lang.Class({
* then @app will be highlighted, and @window outlined, and the
* app list will have the keyboard focus.
*/
_select : function(app, window, forceAppFocus) {
_select(app, window, forceAppFocus) {
if (app != this._selectedIndex || window == null) {
if (this._thumbnails)
this._destroyThumbnails();
@ -353,12 +353,12 @@ var AppSwitcherPopup = new Lang.Class({
!forceAppFocus) {
this._thumbnailTimeoutId = Mainloop.timeout_add (
THUMBNAIL_POPUP_TIME,
Lang.bind(this, this._timeoutPopupThumbnails));
this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
}
},
_timeoutPopupThumbnails: function() {
_timeoutPopupThumbnails() {
if (!this._thumbnails)
this._createThumbnails();
this._thumbnailTimeoutId = 0;
@ -366,27 +366,27 @@ var AppSwitcherPopup = new Lang.Class({
return GLib.SOURCE_REMOVE;
},
_destroyThumbnails : function() {
_destroyThumbnails() {
let thumbnailsActor = this._thumbnails.actor;
Tweener.addTween(thumbnailsActor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
})
onComplete: () => {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
}
});
this._thumbnails = null;
if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
},
_createThumbnails : function() {
_createThumbnails() {
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
this._thumbnails.connect('item-activated', Lang.bind(this, this._windowActivated));
this._thumbnails.connect('item-entered', Lang.bind(this, this._windowEntered));
this._thumbnails.connect('item-removed', Lang.bind(this, this._windowRemoved));
this._thumbnails.connect('item-activated', this._windowActivated.bind(this));
this._thumbnails.connect('item-entered', this._windowEntered.bind(this));
this._thumbnails.connect('item-removed', this._windowRemoved.bind(this));
this._thumbnails.actor.connect('destroy', () => {
this._thumbnails = null;
this._thumbnailsFocused = false;
@ -403,7 +403,7 @@ var AppSwitcherPopup = new Lang.Class({
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
onComplete: () => { this.thumbnailsVisible = true; }
});
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
@ -413,7 +413,7 @@ var AppSwitcherPopup = new Lang.Class({
var CyclerHighlight = new Lang.Class({
Name: 'CyclerHighlight',
_init: function() {
_init() {
this._window = null;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout() });
@ -431,8 +431,8 @@ var CyclerHighlight = new Lang.Class({
this.actor.add_constraint(constraint);
this.actor.connect('notify::allocation',
Lang.bind(this, this._onAllocationChanged));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._onAllocationChanged.bind(this));
this.actor.connect('destroy', this._onDestroy.bind(this));
},
set window(w) {
@ -453,7 +453,7 @@ var CyclerHighlight = new Lang.Class({
this._clone.source = windowActor;
},
_onAllocationChanged: function() {
_onAllocationChanged() {
if (!this._window) {
this._highlight.set_size(0, 0);
this._highlight.hide();
@ -466,7 +466,7 @@ var CyclerHighlight = new Lang.Class({
}
},
_onDestroy: function() {
_onDestroy() {
this.window = null;
}
});
@ -476,7 +476,7 @@ var CyclerPopup = new Lang.Class({
Extends: SwitcherPopup.SwitcherPopup,
Abstract: true,
_init : function() {
_init() {
this.parent();
this._items = this._getWindows();
@ -490,19 +490,20 @@ var CyclerPopup = new Lang.Class({
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
this._switcherList = { actor: new St.Widget(),
highlight: Lang.bind(this, this._highlightItem),
connect: function() {} };
highlight: this._highlightItem.bind(this),
connect() {} };
},
_highlightItem: function(index, justOutline) {
_highlightItem(index, justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null);
},
_finish: function() {
_finish() {
let window = this._items[this._selectedIndex];
let ws = window.get_workspace();
let activeWs = global.screen.get_active_workspace();
let workspaceManager = global.workspace_manager;
let activeWs = workspaceManager.get_active_workspace();
if (window.minimized) {
Main.wm.skipNextEffect(window.get_compositor_private());
@ -524,7 +525,7 @@ var CyclerPopup = new Lang.Class({
this.parent();
},
_onDestroy: function() {
_onDestroy() {
this._highlight.actor.destroy();
this.parent();
@ -536,12 +537,12 @@ var GroupCyclerPopup = new Lang.Class({
Name: 'GroupCyclerPopup',
Extends: CyclerPopup,
_getWindows: function() {
_getWindows() {
let app = Shell.WindowTracker.get_default().focus_app;
return app ? app.get_windows() : [];
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_GROUP)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_GROUP_BACKWARD)
@ -557,7 +558,7 @@ var WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function() {
_init() {
this.parent();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
@ -571,12 +572,19 @@ var WindowSwitcherPopup = new Lang.Class({
this._items = this._switcherList.icons;
},
_getWindowList: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
_getWindowList() {
let workspace = null;
if (this._settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
return getWindows(workspace);
},
_closeWindow: function(windowIndex) {
_closeWindow(windowIndex) {
let windowIcon = this._items[windowIndex];
if (!windowIcon)
return;
@ -584,7 +592,7 @@ var WindowSwitcherPopup = new Lang.Class({
windowIcon.window.delete(global.get_current_time());
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
@ -603,7 +611,7 @@ var WindowSwitcherPopup = new Lang.Class({
return Clutter.EVENT_STOP;
},
_finish: function() {
_finish() {
Main.activateWindow(this._items[this._selectedIndex].window);
this.parent();
@ -614,17 +622,24 @@ var WindowCyclerPopup = new Lang.Class({
Name: 'WindowCyclerPopup',
Extends: CyclerPopup,
_init: function() {
_init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
this.parent();
},
_getWindows: function() {
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
_getWindows() {
let workspace = null;
if (this._settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
return getWindows(workspace);
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.CYCLE_WINDOWS)
this._select(this._next());
else if (action == Meta.KeyBindingAction.CYCLE_WINDOWS_BACKWARD)
@ -639,7 +654,7 @@ var WindowCyclerPopup = new Lang.Class({
var AppIcon = new Lang.Class({
Name: 'AppIcon',
_init: function(app) {
_init(app) {
this.app = app;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
vertical: true });
@ -651,7 +666,7 @@ var AppIcon = new Lang.Class({
this.actor.add(this.label, { x_fill: false });
},
set_size: function(size) {
set_size(size) {
this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon;
}
@ -661,7 +676,7 @@ var AppSwitcher = new Lang.Class({
Name: 'AppSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init : function(apps, altTabPopup) {
_init(apps, altTabPopup) {
this.parent(true);
this.icons = [];
@ -669,8 +684,14 @@ var AppSwitcher = new Lang.Class({
let windowTracker = Shell.WindowTracker.get_default();
let settings = new Gio.Settings({ schema_id: 'org.gnome.shell.app-switcher' });
let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace()
: null;
let workspace = null;
if (settings.get_boolean('current-workspace-only')) {
let workspaceManager = global.workspace_manager;
workspace = workspaceManager.get_active_workspace();
}
let allWindows = global.display.get_tab_list(Meta.TabList.NORMAL, workspace);
// Construct the AppIcons, add to the popup
@ -678,9 +699,9 @@ var AppSwitcher = new Lang.Class({
let appIcon = new AppIcon(apps[i]);
// Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it
appIcon.cachedWindows = allWindows.filter(function(w) {
return windowTracker.get_window_app (w) == appIcon.app;
});
appIcon.cachedWindows = allWindows.filter(
w => windowTracker.get_window_app (w) == appIcon.app
);
if (appIcon.cachedWindows.length > 0)
this._addIcon(appIcon);
}
@ -690,10 +711,10 @@ var AppSwitcher = new Lang.Class({
this._altTabPopup = altTabPopup;
this._mouseTimeOutId = 0;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('destroy', this._onDestroy.bind(this));
},
_onDestroy: function() {
_onDestroy() {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
@ -702,7 +723,7 @@ var AppSwitcher = new Lang.Class({
});
},
_setIconSize: function() {
_setIconSize() {
let j = 0;
while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++;
@ -721,9 +742,7 @@ var AppSwitcher = new Lang.Class({
let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(function(s) {
return s * scaleFactor;
});
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
if (this._items.length == 1) {
this._iconSize = baseIconSizes[0];
@ -744,12 +763,12 @@ var AppSwitcher = new Lang.Class({
}
},
_getPreferredHeight: function (actor, forWidth, alloc) {
_getPreferredHeight(actor, forWidth, alloc) {
this._setIconSize();
this.parent(actor, forWidth, alloc);
},
_allocate: function (actor, box, flags) {
_allocate(actor, box, flags) {
// Allocate the main list items
this.parent(actor, box, flags);
@ -770,22 +789,22 @@ var AppSwitcher = new Lang.Class({
// We override SwitcherList's _onItemEnter method to delay
// activation when the thumbnail list is open
_onItemEnter: function (index) {
_onItemEnter(index) {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
Lang.bind(this, function () {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
}));
() => {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else
this._itemEntered(index);
},
_enterItem: function(index) {
_enterItem(index) {
let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor))
@ -799,7 +818,7 @@ var AppSwitcher = new Lang.Class({
// in justOutline mode). Apps with multiple windows will normally
// show a dim arrow, but show a bright arrow when they are
// highlighted.
highlight : function(n, justOutline) {
highlight(n, justOutline) {
if (this.icons[this._curApp]) {
if (this.icons[this._curApp].cachedWindows.length == 1)
this._arrows[this._curApp].hide();
@ -818,7 +837,7 @@ var AppSwitcher = new Lang.Class({
}
},
_addIcon : function(appIcon) {
_addIcon(appIcon) {
this.icons.push(appIcon);
let item = this.addItem(appIcon.actor, appIcon.label);
@ -829,7 +848,7 @@ var AppSwitcher = new Lang.Class({
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', function() { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
this._list.add_actor(arrow);
this._arrows.push(arrow);
@ -839,7 +858,7 @@ var AppSwitcher = new Lang.Class({
item.add_accessible_state (Atk.StateType.EXPANDABLE);
},
_removeIcon: function(app) {
_removeIcon(app) {
let index = this.icons.findIndex(icon => {
return icon.app == app;
});
@ -855,7 +874,7 @@ var ThumbnailList = new Lang.Class({
Name: 'ThumbnailList',
Extends: SwitcherPopup.SwitcherList,
_init : function(windows) {
_init(windows) {
this.parent(false);
this._labels = new Array();
@ -891,7 +910,7 @@ var ThumbnailList = new Lang.Class({
this.actor.connect('destroy', this._onDestroy.bind(this));
},
addClones : function (availHeight) {
addClones(availHeight) {
if (!this._thumbnailBins.length)
return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding();
@ -914,7 +933,9 @@ var ThumbnailList = new Lang.Class({
this._thumbnailBins[i].set_height(binHeight);
this._thumbnailBins[i].add_actor(clone);
clone._destroyId = mutterWindow.connect('destroy', Lang.bind(this, this._removeThumbnail, clone));
clone._destroyId = mutterWindow.connect('destroy', source => {
this._removeThumbnail(source, clone);
});
this._clones.push(clone);
}
@ -922,7 +943,7 @@ var ThumbnailList = new Lang.Class({
this._thumbnailBins = new Array();
},
_removeThumbnail: function(source, clone) {
_removeThumbnail(source, clone) {
let index = this._clones.indexOf(clone);
if (index === -1)
return;
@ -938,7 +959,7 @@ var ThumbnailList = new Lang.Class({
this.actor.destroy();
},
_onDestroy: function() {
_onDestroy() {
this._clones.forEach(clone => {
if (clone.source)
clone.source.disconnect(clone._destroyId);
@ -950,7 +971,7 @@ var ThumbnailList = new Lang.Class({
var WindowIcon = new Lang.Class({
Name: 'WindowIcon',
_init: function(window, mode) {
_init(window, mode) {
this.window = window;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -993,7 +1014,7 @@ var WindowIcon = new Lang.Class({
this._icon.set_size(size * scaleFactor, size * scaleFactor);
},
_createAppIcon: function(app, size) {
_createAppIcon(app, size) {
let appIcon = app ? app.create_icon_texture(size)
: new St.Icon({ icon_name: 'icon-missing',
icon_size: size });
@ -1008,7 +1029,7 @@ var WindowList = new Lang.Class({
Name: 'WindowList',
Extends: SwitcherPopup.SwitcherList,
_init : function(windows, mode) {
_init(windows, mode) {
this.parent(true);
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
@ -1033,13 +1054,13 @@ var WindowList = new Lang.Class({
this.actor.connect('destroy', () => { this._onDestroy(); });
},
_onDestroy: function() {
_onDestroy() {
this.icons.forEach(icon => {
icon.window.disconnect(icon._unmanagedSignalId);
});
},
_getPreferredHeight: function(actor, forWidth, alloc) {
_getPreferredHeight(actor, forWidth, alloc) {
this.parent(actor, forWidth, alloc);
let spacing = this.actor.get_theme_node().get_padding(St.Side.BOTTOM);
@ -1048,7 +1069,7 @@ var WindowList = new Lang.Class({
alloc.natural_size += labelNat + spacing;
},
_allocateTop: function(actor, box, flags) {
_allocateTop(actor, box, flags) {
let childBox = new Clutter.ActorBox();
childBox.x1 = box.x1;
childBox.x2 = box.x2;
@ -1061,13 +1082,13 @@ var WindowList = new Lang.Class({
this.parent(actor, box, flags);
},
highlight: function(index, justOutline) {
highlight(index, justOutline) {
this.parent(index, justOutline);
this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
},
_removeWindow: function(window) {
_removeWindow(window) {
let index = this.icons.findIndex(icon => {
return icon.window == window;
});

View File

@ -12,9 +12,9 @@ var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var Animation = new Lang.Class({
Name: 'Animation',
_init: function(file, width, height, speed) {
_init(file, width, height, speed) {
this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('destroy', this._onDestroy.bind(this));
this._speed = speed;
this._isLoaded = false;
@ -24,23 +24,23 @@ var Animation = new Lang.Class({
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = St.TextureCache.get_default().load_sliced_image (file, width, height, scaleFactor,
Lang.bind(this, this._animationsLoaded));
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
},
play: function() {
play() {
if (this._isLoaded && this._timeoutId == 0) {
if (this._frame == 0)
this._showFrame(0);
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_LOW, this._speed, Lang.bind(this, this._update));
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_LOW, this._speed, this._update.bind(this));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._update');
}
this._isPlaying = true;
},
stop: function() {
stop() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
@ -49,7 +49,7 @@ var Animation = new Lang.Class({
this._isPlaying = false;
},
_showFrame: function(frame) {
_showFrame(frame) {
let oldFrameActor = this._animations.get_child_at_index(this._frame);
if (oldFrameActor)
oldFrameActor.hide();
@ -61,19 +61,19 @@ var Animation = new Lang.Class({
newFrameActor.show();
},
_update: function() {
_update() {
this._showFrame(this._frame + 1);
return GLib.SOURCE_CONTINUE;
},
_animationsLoaded: function() {
_animationsLoaded() {
this._isLoaded = this._animations.get_n_children() > 0;
if (this._isPlaying)
this.play();
},
_onDestroy: function() {
_onDestroy() {
this.stop();
}
});
@ -82,7 +82,7 @@ var AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
Extends: Animation,
_init: function(file, size) {
_init(file, size) {
this.parent(file, size, size, ANIMATED_ICON_UPDATE_TIMEOUT);
}
});

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ const RENAMED_DESKTOP_IDS = {
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'empathy.desktop': 'org.gnome.Empathy.desktop',
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'gcalctool.desktop': 'org.gnome.Calculator.desktop',
'geary.desktop': 'org.gnome.Geary.desktop',
@ -34,6 +35,7 @@ const RENAMED_DESKTOP_IDS = {
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'gnome-tetravex.desktop',
@ -49,24 +51,24 @@ var AppFavorites = new Lang.Class({
FAVORITE_APPS_KEY: 'favorite-apps',
_init: function() {
_init() {
this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
this.reload();
},
_onFavsChanged: function() {
_onFavsChanged() {
this.reload();
this.emit('changed');
},
reload: function() {
reload() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
let appSys = Shell.AppSystem.get_default();
// Map old desktop file names to the current ones
let updated = false;
ids = ids.map(function (id) {
ids = ids.map(id => {
let newId = RENAMED_DESKTOP_IDS[id];
if (newId !== undefined &&
appSys.lookup_app(newId) != null) {
@ -79,11 +81,8 @@ var AppFavorites = new Lang.Class({
if (updated)
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let apps = ids.map(function (id) {
return appSys.lookup_app(id);
}).filter(function (app) {
return app != null;
});
let apps = ids.map(id => appSys.lookup_app(id))
.filter(app => app != null);
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
@ -91,29 +90,29 @@ var AppFavorites = new Lang.Class({
}
},
_getIds: function() {
_getIds() {
let ret = [];
for (let id in this._favorites)
ret.push(id);
return ret;
},
getFavoriteMap: function() {
getFavoriteMap() {
return this._favorites;
},
getFavorites: function() {
getFavorites() {
let ret = [];
for (let id in this._favorites)
ret.push(this._favorites[id]);
return ret;
},
isFavorite: function(appId) {
isFavorite(appId) {
return appId in this._favorites;
},
_addFavorite: function(appId, pos) {
_addFavorite(appId, pos) {
if (appId in this._favorites)
return false;
@ -132,7 +131,7 @@ var AppFavorites = new Lang.Class({
return true;
},
addFavoriteAtPos: function(appId, pos) {
addFavoriteAtPos(appId, pos) {
if (!this._addFavorite(appId, pos))
return;
@ -140,31 +139,31 @@ var AppFavorites = new Lang.Class({
Main.overview.setMessage(_("%s has been added to your favorites.").format(app.get_name()),
{ forFeedback: true,
undoCallback: Lang.bind(this, function () {
this._removeFavorite(appId);
})
undoCallback: () => {
this._removeFavorite(appId);
}
});
},
addFavorite: function(appId) {
addFavorite(appId) {
this.addFavoriteAtPos(appId, -1);
},
moveFavoriteToPos: function(appId, pos) {
moveFavoriteToPos(appId, pos) {
this._removeFavorite(appId);
this._addFavorite(appId, pos);
},
_removeFavorite: function(appId) {
_removeFavorite(appId) {
if (!appId in this._favorites)
return false;
let ids = this._getIds().filter(function (id) { return id != appId; });
let ids = this._getIds().filter(id => id != appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true;
},
removeFavorite: function(appId) {
removeFavorite(appId) {
let ids = this._getIds();
let pos = ids.indexOf(appId);
@ -174,9 +173,9 @@ var AppFavorites = new Lang.Class({
Main.overview.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
{ forFeedback: true,
undoCallback: Lang.bind(this, function () {
this._addFavorite(appId, pos);
})
undoCallback: () => {
this._addFavorite(appId, pos);
}
});
}
});

View File

@ -15,24 +15,25 @@ var AudioDevice = {
MICROPHONE: 1 << 2
};
const AudioDeviceSelectionIface = '<node> \
<interface name="org.gnome.Shell.AudioDeviceSelection"> \
<method name="Open"> \
<arg name="devices" direction="in" type="as" /> \
</method> \
<method name="Close"> \
</method> \
<signal name="DeviceSelected"> \
<arg name="device" type="s" /> \
</signal> \
</interface> \
</node>';
const AudioDeviceSelectionIface = `
<node>
<interface name="org.gnome.Shell.AudioDeviceSelection">
<method name="Open">
<arg name="devices" direction="in" type="as" />
</method>
<method name="Close">
</method>
<signal name="DeviceSelected">
<arg name="device" type="s" />
</signal>
</interface>
</node>`;
var AudioDeviceSelectionDialog = new Lang.Class({
Name: 'AudioDeviceSelectionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(devices) {
_init(devices) {
this.parent({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {};
@ -50,11 +51,11 @@ var AudioDeviceSelectionDialog = new Lang.Class({
throw new Error('Too few devices for a selection');
},
destroy: function() {
destroy() {
this.parent();
},
_buildLayout: function(devices) {
_buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER });
@ -65,14 +66,14 @@ var AudioDeviceSelectionDialog = new Lang.Class({
this._selectionBox = new St.BoxLayout({ style_class: 'audio-selection-box' });
this.contentLayout.add(this._selectionBox, { expand: true });
this.addButton({ action: Lang.bind(this, this._openSettings),
this.addButton({ action: this._openSettings.bind(this),
label: _("Sound Settings") });
this.addButton({ action: Lang.bind(this, this.close),
this.addButton({ action: this.close.bind(this),
label: _("Cancel"),
key: Clutter.Escape });
},
_getDeviceLabel: function(device) {
_getDeviceLabel(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
@ -85,7 +86,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
}
},
_getDeviceIcon: function(device) {
_getDeviceIcon(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
@ -98,16 +99,14 @@ var AudioDeviceSelectionDialog = new Lang.Class({
}
},
_addDevice: function(device) {
_addDevice(device) {
let box = new St.BoxLayout({ style_class: 'audio-selection-device-box',
vertical: true });
box.connect('notify::height',
function() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
function() {
box.width = box.height;
});
box.connect('notify::height', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
box.width = box.height;
});
});
let icon = new St.Icon({ style_class: 'audio-selection-device-icon',
icon_name: this._getDeviceIcon(device) });
@ -123,15 +122,14 @@ var AudioDeviceSelectionDialog = new Lang.Class({
child: box });
this._selectionBox.add(button);
button.connect('clicked', Lang.bind(this,
function() {
this.emit('device-selected', device);
this.close();
Main.overview.hide();
}));
button.connect('clicked', () => {
this.emit('device-selected', device);
this.close();
Main.overview.hide();
});
},
_openSettings: function() {
_openSettings() {
let desktopFile = 'gnome-sound-panel.desktop'
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
@ -149,7 +147,7 @@ var AudioDeviceSelectionDialog = new Lang.Class({
var AudioDeviceSelectionDBus = new Lang.Class({
Name: 'AudioDeviceSelectionDBus',
_init: function() {
_init() {
this._audioSelectionDialog = null;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(AudioDeviceSelectionIface, this);
@ -158,17 +156,16 @@ var AudioDeviceSelectionDBus = new Lang.Class({
Gio.DBus.session.own_name('org.gnome.Shell.AudioDeviceSelection', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
_onDialogClosed: function() {
_onDialogClosed() {
this._audioSelectionDialog = null;
},
_onDeviceSelected: function(dialog, device) {
_onDeviceSelected(dialog, device) {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
let deviceName = Object.keys(AudioDevice).filter(
function(dev) {
return AudioDevice[dev] == device;
})[0].toLowerCase();
dev => AudioDevice[dev] == device
)[0].toLowerCase();
connection.emit_signal(this._audioSelectionDialog._sender,
this._dbusImpl.get_object_path(),
info ? info.name : null,
@ -176,7 +173,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
GLib.Variant.new('(s)', [deviceName]));
},
OpenAsync: function(params, invocation) {
OpenAsync(params, invocation) {
if (this._audioSelectionDialog) {
invocation.return_value(null);
return;
@ -184,9 +181,7 @@ var AudioDeviceSelectionDBus = new Lang.Class({
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(function(n) {
devices |= AudioDevice[n.toUpperCase()];
});
deviceNames.forEach(n => { devices |= AudioDevice[n.toUpperCase()]; });
let dialog;
try {
@ -197,16 +192,16 @@ var AudioDeviceSelectionDBus = new Lang.Class({
}
dialog._sender = invocation.get_sender();
dialog.connect('closed', Lang.bind(this, this._onDialogClosed));
dialog.connect('closed', this._onDialogClosed.bind(this));
dialog.connect('device-selected',
Lang.bind(this, this._onDeviceSelected));
this._onDeviceSelected.bind(this));
dialog.open();
this._audioSelectionDialog = dialog;
invocation.return_value(null);
},
CloseAsync: function(params, invocation) {
CloseAsync(params, invocation) {
if (this._audioSelectionDialog &&
this._audioSelectionDialog._sender == invocation.get_sender())
this._audioSelectionDialog.close();

View File

@ -141,31 +141,31 @@ function _fileEqual0(file1, file2) {
var BackgroundCache = new Lang.Class({
Name: 'BackgroundCache',
_init: function() {
_init() {
this._fileMonitors = {};
this._backgroundSources = {};
this._animations = {};
},
monitorFile: function(file) {
monitorFile(file) {
let key = file.hash();
if (this._fileMonitors[key])
return;
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed',
Lang.bind(this, function(obj, file, otherFile, eventType) {
(obj, file, otherFile, eventType) => {
// Ignore CHANGED and CREATED events, since in both cases
// we'll get a CHANGES_DONE_HINT event when done.
if (eventType != Gio.FileMonitorEvent.CHANGED &&
eventType != Gio.FileMonitorEvent.CREATED)
this.emit('file-changed', file);
}));
});
this._fileMonitors[key] = monitor;
},
getAnimation: function(params) {
getAnimation(params) {
params = Params.parse(params, { file: null,
settingsSchema: null,
onLoaded: null });
@ -173,10 +173,10 @@ var BackgroundCache = new Lang.Class({
let animation = this._animations[params.settingsSchema];
if (animation && _fileEqual0(animation.file, params.file)) {
if (params.onLoaded) {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
params.onLoaded(this._animations[params.settingsSchema]);
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
}
return;
@ -184,20 +184,20 @@ var BackgroundCache = new Lang.Class({
animation = new Animation({ file: params.file });
animation.load(Lang.bind(this, function() {
this._animations[params.settingsSchema] = animation;
animation.load(() => {
this._animations[params.settingsSchema] = animation;
if (params.onLoaded) {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
params.onLoaded(this._animations[params.settingsSchema]);
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
}
}));
if (params.onLoaded) {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
params.onLoaded(this._animations[params.settingsSchema]);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
}
});
},
getBackgroundSource: function(layoutManager, settingsSchema) {
getBackgroundSource(layoutManager, settingsSchema) {
// The layoutManager is always the same one; we pass in it since
// Main.layoutManager may not be set yet
@ -211,7 +211,7 @@ var BackgroundCache = new Lang.Class({
return this._backgroundSources[settingsSchema];
},
releaseBackgroundSource: function(settingsSchema) {
releaseBackgroundSource(settingsSchema) {
if (settingsSchema in this._backgroundSources) {
let source = this._backgroundSources[settingsSchema];
source._useCount--;
@ -233,14 +233,14 @@ function getBackgroundCache() {
var Background = new Lang.Class({
Name: 'Background',
_init: function(params) {
_init(params) {
params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager,
settings: null,
file: null,
style: null });
this.background = new Meta.Background({ meta_screen: global.screen });
this.background = new Meta.Background({ meta_display: global.display });
this.background._delegate = this;
this._settings = params.settings;
@ -254,10 +254,10 @@ var Background = new Lang.Class({
this._clock = new GnomeDesktop.WallClock();
this._timezoneChangedId = this._clock.connect('notify::timezone',
Lang.bind(this, function() {
() => {
if (this._animation)
this._loadAnimation(this._animation.file);
}));
});
let loginManager = LoginManager.getLoginManager();
this._prepareForSleepId = loginManager.connect('prepare-for-sleep',
@ -267,14 +267,14 @@ var Background = new Lang.Class({
this._refreshAnimation();
});
this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
this.emit('changed');
}));
this._settingsChangedSignalId = this._settings.connect('changed', () => {
this.emit('changed');
});
this._load();
},
destroy: function() {
destroy() {
this._cancellable.cancel();
this._removeAnimationTimeout();
@ -300,12 +300,12 @@ var Background = new Lang.Class({
this._settingsChangedSignalId = 0;
},
updateResolution: function() {
updateResolution() {
if (this._animation)
this._refreshAnimation();
},
_refreshAnimation: function() {
_refreshAnimation() {
if (!this._animation)
return;
@ -313,20 +313,20 @@ var Background = new Lang.Class({
this._updateAnimation();
},
_setLoaded: function() {
_setLoaded() {
if (this.isLoaded)
return;
this.isLoaded = true;
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this.emit('loaded');
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
},
_loadPattern: function() {
_loadPattern() {
let colorString, res, color, secondColor;
colorString = this._settings.get_string(PRIMARY_COLOR_KEY);
@ -342,37 +342,37 @@ var Background = new Lang.Class({
this.background.set_gradient(shadingType, color, secondColor);
},
_watchFile: function(file) {
_watchFile(file) {
let key = file.hash();
if (this._fileWatches[key])
return;
this._cache.monitorFile(file);
let signalId = this._cache.connect('file-changed',
Lang.bind(this, function(cache, changedFile) {
(cache, changedFile) => {
if (changedFile.equal(file)) {
let imageCache = Meta.BackgroundImageCache.get_default();
imageCache.purge(changedFile);
this.emit('changed');
}
}));
});
this._fileWatches[key] = signalId;
},
_removeAnimationTimeout: function() {
_removeAnimationTimeout() {
if (this._updateAnimationTimeoutId) {
GLib.source_remove(this._updateAnimationTimeoutId);
this._updateAnimationTimeoutId = 0;
}
},
_updateAnimation: function() {
_updateAnimation() {
this._updateAnimationTimeoutId = 0;
this._animation.update(this._layoutManager.monitors[this._monitorIndex]);
let files = this._animation.keyFrameFiles;
let finish = Lang.bind(this, function() {
let finish = () => {
this._setLoaded();
if (files.length > 1) {
this.background.set_blend(files[0], files[1],
@ -384,7 +384,7 @@ var Background = new Lang.Class({
this.background.set_file(null, this._style);
}
this._queueUpdateAnimation();
});
};
let cache = Meta.BackgroundImageCache.get_default();
let numPendingImages = files.length;
@ -396,18 +396,17 @@ var Background = new Lang.Class({
if (numPendingImages == 0)
finish();
} else {
let id = image.connect('loaded',
Lang.bind(this, function() {
image.disconnect(id);
numPendingImages--;
if (numPendingImages == 0)
finish();
}));
let id = image.connect('loaded', () => {
image.disconnect(id);
numPendingImages--;
if (numPendingImages == 0)
finish();
});
}
}
},
_queueUpdateAnimation: function() {
_queueUpdateAnimation() {
if (this._updateAnimationTimeoutId != 0)
return;
@ -428,18 +427,18 @@ var Background = new Lang.Class({
this._updateAnimationTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
interval,
Lang.bind(this, function() {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
}));
() => {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
},
_loadAnimation: function(file) {
_loadAnimation(file) {
this._cache.getAnimation({ file: file,
settingsSchema: this._settings.schema_id,
onLoaded: Lang.bind(this, function(animation) {
onLoaded: animation => {
this._animation = animation;
if (!this._animation || this._cancellable.is_cancelled()) {
@ -449,11 +448,11 @@ var Background = new Lang.Class({
this._updateAnimation();
this._watchFile(file);
})
}
});
},
_loadImage: function(file) {
_loadImage(file) {
this.background.set_file(file, this._style);
this._watchFile(file);
@ -462,22 +461,21 @@ var Background = new Lang.Class({
if (image.is_loaded())
this._setLoaded();
else {
let id = image.connect('loaded',
Lang.bind(this, function() {
this._setLoaded();
image.disconnect(id);
}));
let id = image.connect('loaded', () => {
this._setLoaded();
image.disconnect(id);
});
}
},
_loadFile: function(file) {
_loadFile(file) {
if (file.get_basename().endsWith('.xml'))
this._loadAnimation(file);
else
this._loadImage(file);
},
_load: function () {
_load() {
this._cache = getBackgroundCache();
this._loadPattern();
@ -497,16 +495,16 @@ let _systemBackground;
var SystemBackground = new Lang.Class({
Name: 'SystemBackground',
_init: function() {
_init() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/noise-texture.png');
if (_systemBackground == null) {
_systemBackground = new Meta.Background({ meta_screen: global.screen });
_systemBackground = new Meta.Background({ meta_display: global.display });
_systemBackground.set_color(DEFAULT_BACKGROUND_COLOR);
_systemBackground.set_file(file, GDesktopEnums.BackgroundStyle.WALLPAPER);
}
this.actor = new Meta.BackgroundActor({ meta_screen: global.screen,
this.actor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: 0,
background: _systemBackground });
@ -514,18 +512,17 @@ var SystemBackground = new Lang.Class({
let image = cache.load(file);
if (image.is_loaded()) {
image = null;
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this.emit('loaded');
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(id, '[gnome-shell] SystemBackground.loaded');
} else {
let id = image.connect('loaded',
Lang.bind(this, function() {
this.emit('loaded');
image.disconnect(id);
image = null;
}));
let id = image.connect('loaded', () => {
this.emit('loaded');
image.disconnect(id);
image = null;
});
}
},
});
@ -534,18 +531,20 @@ Signals.addSignalMethods(SystemBackground.prototype);
var BackgroundSource = new Lang.Class({
Name: 'BackgroundSource',
_init: function(layoutManager, settingsSchema) {
_init(layoutManager, settingsSchema) {
// Allow override the background image setting for performance testing
this._layoutManager = layoutManager;
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
this._settings = new Gio.Settings({ schema_id: settingsSchema });
this._backgrounds = [];
this._monitorsChangedId = global.screen.connect('monitors-changed',
Lang.bind(this, this._onMonitorsChanged));
let monitorManager = Meta.MonitorManager.get();
this._monitorsChangedId =
monitorManager.connect('monitors-changed',
this._onMonitorsChanged.bind(this));
},
_onMonitorsChanged: function() {
_onMonitorsChanged() {
for (let monitorIndex in this._backgrounds) {
let background = this._backgrounds[monitorIndex];
@ -559,7 +558,7 @@ var BackgroundSource = new Lang.Class({
}
},
getBackground: function(monitorIndex) {
getBackground(monitorIndex) {
let file = null;
let style;
@ -594,11 +593,11 @@ var BackgroundSource = new Lang.Class({
style: style
});
background._changedId = background.connect('changed', Lang.bind(this, function() {
background._changedId = background.connect('changed', () => {
background.disconnect(background._changedId);
background.destroy();
delete this._backgrounds[monitorIndex];
}));
});
this._backgrounds[monitorIndex] = background;
}
@ -606,8 +605,9 @@ var BackgroundSource = new Lang.Class({
return this._backgrounds[monitorIndex];
},
destroy: function() {
global.screen.disconnect(this._monitorsChangedId);
destroy() {
let monitorManager = Meta.MonitorManager.get();
monitorManager.disconnect(this._monitorsChangedId);
for (let monitorIndex in this._backgrounds) {
let background = this._backgrounds[monitorIndex];
@ -622,7 +622,7 @@ var BackgroundSource = new Lang.Class({
var Animation = new Lang.Class({
Name: 'Animation',
_init: function(params) {
_init(params) {
params = Params.parse(params, { file: null });
this.file = params.file;
@ -632,19 +632,17 @@ var Animation = new Lang.Class({
this.loaded = false;
},
load: function(callback) {
load(callback) {
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
this._show.load_async(null,
Lang.bind(this,
function(object, result) {
this.loaded = true;
if (callback)
callback();
}));
this._show.load_async(null, (object, result) => {
this.loaded = true;
if (callback)
callback();
});
},
update: function(monitor) {
update(monitor) {
this.keyFrameFiles = [];
if (!this._show)
@ -670,7 +668,7 @@ Signals.addSignalMethods(Animation.prototype);
var BackgroundManager = new Lang.Class({
Name: 'BackgroundManager',
_init: function(params) {
_init(params) {
params = Params.parse(params, { container: null,
layoutManager: Main.layoutManager,
monitorIndex: null,
@ -692,7 +690,7 @@ var BackgroundManager = new Lang.Class({
this._newBackgroundActor = null;
},
destroy: function() {
destroy() {
let cache = getBackgroundCache();
cache.releaseBackgroundSource(this._settingsSchema);
this._backgroundSource = null;
@ -708,7 +706,7 @@ var BackgroundManager = new Lang.Class({
}
},
_swapBackgroundActor: function() {
_swapBackgroundActor() {
let oldBackgroundActor = this.backgroundActor;
this.backgroundActor = this._newBackgroundActor;
this._newBackgroundActor = null;
@ -718,14 +716,14 @@ var BackgroundManager = new Lang.Class({
{ opacity: 0,
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: function() {
onComplete() {
oldBackgroundActor.background.run_dispose();
oldBackgroundActor.destroy();
}
});
},
_updateBackgroundActor: function() {
_updateBackgroundActor() {
if (this._newBackgroundActor) {
/* Skip displaying existing background queued for load */
this._newBackgroundActor.destroy();
@ -745,19 +743,18 @@ var BackgroundManager = new Lang.Class({
this._swapBackgroundActor();
} else {
newBackgroundActor.loadedSignalId = background.connect('loaded',
Lang.bind(this, function() {
() => {
background.disconnect(newBackgroundActor.loadedSignalId);
newBackgroundActor.loadedSignalId = 0;
this._swapBackgroundActor();
}));
});
}
},
_createBackgroundActor: function() {
_createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ meta_screen: global.screen,
let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,
@ -775,19 +772,19 @@ var BackgroundManager = new Lang.Class({
backgroundActor.lower_bottom();
}
let changeSignalId = background.connect('changed', Lang.bind(this, function() {
let changeSignalId = background.connect('changed', () => {
background.disconnect(changeSignalId);
changeSignalId = null;
this._updateBackgroundActor();
}));
});
backgroundActor.connect('destroy', Lang.bind(this, function() {
backgroundActor.connect('destroy', () => {
if (changeSignalId)
background.disconnect(changeSignalId);
if (backgroundActor.loadedSignalId)
background.disconnect(backgroundActor.loadedSignalId);
}));
});
return backgroundActor;
},

View File

@ -13,7 +13,7 @@ var BackgroundMenu = new Lang.Class({
Name: 'BackgroundMenu',
Extends: PopupMenu.PopupMenu,
_init: function(layoutManager) {
_init(layoutManager) {
this.parent(layoutManager.dummyCursor, 0, St.Side.TOP);
this.addSettingsAction(_("Change Background…"), 'gnome-background-panel.desktop');
@ -40,7 +40,7 @@ function addBackgroundMenu(actor, layoutManager) {
}
let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', function(action, actor, state) {
clickAction.connect('long-press', (action, actor, state) => {
if (state == Clutter.LongPressState.QUERY)
return ((action.get_button() == 0 ||
action.get_button() == 1) &&
@ -52,7 +52,7 @@ function addBackgroundMenu(actor, layoutManager) {
}
return true;
});
clickAction.connect('clicked', function(action) {
clickAction.connect('clicked', action => {
if (action.get_button() == 3) {
let [x, y] = action.get_coords();
openMenu(x, y);
@ -60,11 +60,11 @@ function addBackgroundMenu(actor, layoutManager) {
});
actor.add_action(clickAction);
let grabOpBeginId = global.display.connect('grab-op-begin', function () {
let grabOpBeginId = global.display.connect('grab-op-begin', () => {
clickAction.release();
});
actor.connect('destroy', function() {
actor.connect('destroy', () => {
actor._backgroundMenu.destroy();
actor._backgroundMenu = null;
actor._backgroundManager = null;

210
js/ui/barLevel.js Normal file
View File

@ -0,0 +1,210 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Atk = imports.gi.Atk;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals;
var BarLevel = new Lang.Class({
Name: "BarLevel",
_init(value, params) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
this._maxValue = 1;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this._overdriveStart = 1;
this._barLevelWidth = 0;
if (params == undefined)
params = {}
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false,
reactive: params['reactive'] || false,
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this));
},
setValue(value) {
if (isNaN(value))
throw TypeError('The bar level value must be a number');
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
setMaximumValue(value) {
if (isNaN(value))
throw TypeError('The bar level max value must be a number');
this._maxValue = Math.max(value, 1);
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint();
},
setOverdriveStart(value) {
if (isNaN(value))
throw TypeError('The overdrive limit value must be a number');
if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`);
this._overdriveStart = value;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
_barLevelRepaint(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
let fgColor = themeNode.get_foreground_color();
let barLevelColor = themeNode.get_color('-barlevel-background-color');
let barLevelActiveColor = themeNode.get_color('-barlevel-active-background-color');
let barLevelOverdriveColor = themeNode.get_color('-barlevel-overdrive-color');
let barLevelBorderWidth = Math.min(themeNode.get_length('-barlevel-border-width'), 1);
let [hasBorderColor, barLevelBorderColor] =
themeNode.lookup_color('-barlevel-border-color', false);
if (!hasBorderColor)
barLevelBorderColor = barLevelColor;
let [hasActiveBorderColor, barLevelActiveBorderColor] =
themeNode.lookup_color('-barlevel-active-border-color', false);
if (!hasActiveBorderColor)
barLevelActiveBorderColor = barLevelActiveColor;
let [hasOverdriveBorderColor, barLevelOverdriveBorderColor] =
themeNode.lookup_color('-barlevel-overdrive-border-color', false);
if (!hasOverdriveBorderColor)
barLevelOverdriveBorderColor = barLevelOverdriveColor;
const TAU = Math.PI * 2;
let endX = 0;
if (this._maxValue > 0)
endX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._value / this._maxValue;
let overdriveSeparatorX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._overdriveStart / this._maxValue;
let overdriveActive = this._overdriveStart !== this._maxValue;
let overdriveSeparatorWidth = 0;
if (overdriveActive)
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
/* background bar */
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* normal progress bar */
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
cr.lineTo(x, (height - barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* overdrive progress barLevel */
x = Math.min(endX, overdriveSeparatorX) + overdriveSeparatorWidth / 2;
if (this._value > this._overdriveStart) {
cr.moveTo(x, (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(x, (height - barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelOverdriveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
}
/* end progress bar arc */
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* draw overdrive separator */
if (overdriveActive) {
cr.moveTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, fgColor);
else
Clutter.cairo_set_source_color(cr, barLevelColor);
cr.fill();
}
cr.$dispose();
},
_getCurrentValue(actor) {
return this._value;
},
_getOverdriveStart(actor) {
return this._overdriveStart;
},
_getMinimumValue(actor) {
return 0;
},
_getMaximumValue(actor) {
return this._maxValue;
},
_setCurrentValue(actor, value) {
this._value = value;
},
_valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value");
},
get value() {
return this._value;
}
});
Signals.addSignalMethods(BarLevel.prototype);

View File

@ -35,7 +35,7 @@ var POPUP_ANIMATION_TIME = 0.15;
var BoxPointer = new Lang.Class({
Name: 'BoxPointer',
_init: function(arrowSide, binProperties) {
_init(arrowSide, binProperties) {
this._arrowSide = arrowSide;
this._userArrowSide = arrowSide;
this._arrowOrigin = 0;
@ -44,13 +44,14 @@ var BoxPointer = new Lang.Class({
y_fill: true });
this._container = new Shell.GenericContainer();
this.actor.set_child(this._container);
this._container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._container.connect('allocate', Lang.bind(this, this._allocate));
this.actor.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._container.connect('get-preferred-width', this._getPreferredWidth.bind(this));
this._container.connect('get-preferred-height', this._getPreferredHeight.bind(this));
this._container.connect('allocate', this._allocate.bind(this));
this.bin = new St.Bin(binProperties);
this._container.add_actor(this.bin);
this._border = new St.DrawingArea();
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
this._border.connect('repaint', this._drawBorder.bind(this));
this._container.add_actor(this._border);
this.bin.raise(this._border);
this._xOffset = 0;
@ -66,20 +67,20 @@ var BoxPointer = new Lang.Class({
return this._arrowSide;
},
_muteInput: function() {
_muteInput() {
if (this._capturedEventId == 0)
this._capturedEventId = this.actor.connect('captured-event',
function() { return Clutter.EVENT_STOP; });
() => Clutter.EVENT_STOP);
},
_unmuteInput: function() {
_unmuteInput() {
if (this._capturedEventId != 0) {
this.actor.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
},
show: function(animate, onComplete) {
show(animate, onComplete) {
let themeNode = this.actor.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
@ -112,15 +113,15 @@ var BoxPointer = new Lang.Class({
xOffset: 0,
yOffset: 0,
transition: 'linear',
onComplete: Lang.bind(this, function() {
onComplete: () => {
this._unmuteInput();
if (onComplete)
onComplete();
}),
},
time: animationTime });
},
hide: function(animate, onComplete) {
hide(animate, onComplete) {
if (!this.actor.visible)
return;
@ -156,18 +157,18 @@ var BoxPointer = new Lang.Class({
yOffset: yOffset,
transition: 'linear',
time: animationTime,
onComplete: Lang.bind(this, function () {
onComplete: () => {
this.actor.hide();
this.opacity = 0;
this.xOffset = 0;
this.yOffset = 0;
if (onComplete)
onComplete();
})
}
});
},
_adjustAllocationForArrow: function(isWidth, alloc) {
_adjustAllocationForArrow(isWidth, alloc) {
let themeNode = this.actor.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
alloc.min_size += borderWidth * 2;
@ -180,14 +181,14 @@ var BoxPointer = new Lang.Class({
}
},
_getPreferredWidth: function(actor, forHeight, alloc) {
_getPreferredWidth(actor, forHeight, alloc) {
let [minInternalSize, natInternalSize] = this.bin.get_preferred_width(forHeight);
alloc.min_size = minInternalSize;
alloc.natural_size = natInternalSize;
this._adjustAllocationForArrow(true, alloc);
},
_getPreferredHeight: function(actor, forWidth, alloc) {
_getPreferredHeight(actor, forWidth, alloc) {
let themeNode = this.actor.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth - 2 * borderWidth);
@ -196,7 +197,7 @@ var BoxPointer = new Lang.Class({
this._adjustAllocationForArrow(false, alloc);
},
_allocate: function(actor, box, flags) {
_allocate(actor, box, flags) {
let themeNode = this.actor.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let rise = themeNode.get_length('-arrow-rise');
@ -236,7 +237,7 @@ var BoxPointer = new Lang.Class({
}
},
_drawBorder: function(area) {
_drawBorder(area) {
let themeNode = this.actor.get_theme_node();
if (this._arrowActor) {
@ -418,7 +419,7 @@ var BoxPointer = new Lang.Class({
cr.$dispose();
},
setPosition: function(sourceActor, alignment) {
setPosition(sourceActor, alignment) {
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
@ -430,7 +431,7 @@ var BoxPointer = new Lang.Class({
this._updateFlip();
},
setSourceAlignment: function(alignment) {
setSourceAlignment(alignment) {
this._sourceAlignment = alignment;
if (!this._sourceActor)
@ -439,7 +440,7 @@ var BoxPointer = new Lang.Class({
this.setPosition(this._sourceActor, this._arrowAlignment);
},
_reposition: function() {
_reposition() {
let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment;
@ -556,7 +557,7 @@ var BoxPointer = new Lang.Class({
// @origin: Coordinate specifying middle of the arrow, along
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
// the left for St.Side.TOP and St.Side.BOTTOM.
setArrowOrigin: function(origin) {
setArrowOrigin(origin) {
if (this._arrowOrigin != origin) {
this._arrowOrigin = origin;
this._border.queue_repaint();
@ -566,14 +567,14 @@ var BoxPointer = new Lang.Class({
// @actor: an actor relative to which the arrow is positioned.
// Differently from setPosition, this will not move the boxpointer itself,
// on the arrow
setArrowActor: function(actor) {
setArrowActor(actor) {
if (this._arrowActor != actor) {
this._arrowActor = actor;
this._border.queue_repaint();
}
},
_shiftActor : function() {
_shiftActor() {
// Since the position of the BoxPointer depends on the allocated size
// of the BoxPointer and the position of the source actor, trying
// to position the BoxPointer via the x/y properties will result in
@ -584,7 +585,7 @@ var BoxPointer = new Lang.Class({
-(this._yPosition + this._yOffset));
},
_calculateArrowSide: function(arrowSide) {
_calculateArrowSide(arrowSide) {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let [minWidth, minHeight, boxWidth, boxHeight] = this._container.get_preferred_size();
let monitorActor = this.sourceActor;
@ -618,15 +619,15 @@ var BoxPointer = new Lang.Class({
return arrowSide;
},
_updateFlip: function() {
_updateFlip() {
let arrowSide = this._calculateArrowSide(this._userArrowSide);
if (this._arrowSide != arrowSide) {
this._arrowSide = arrowSide;
this._reposition();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._container.queue_relayout();
return false;
}));
});
this.emit('arrow-side-changed');
}
@ -658,18 +659,18 @@ var BoxPointer = new Lang.Class({
return this.actor.opacity;
},
updateArrowSide: function(side) {
updateArrowSide(side) {
this._arrowSide = side;
this._border.queue_repaint();
this.emit('arrow-side-changed');
},
getPadding: function(side) {
getPadding(side) {
return this.bin.get_theme_node().get_padding(side);
},
getArrowHeight: function() {
getArrowHeight() {
return this.actor.get_theme_node().get_length('-arrow-rise');
}
});

View File

@ -21,7 +21,7 @@ var ELLIPSIS_CHAR = '\u2026';
var MESSAGE_ICON_SIZE = -1; // pick up from CSS
var NC_ = function(context, str) { return context + '\u0004' + str; };
var NC_ = (context, str) => context + '\u0004' + str;
function sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear());
@ -92,7 +92,7 @@ function _getCalendarDayAbbreviation(dayNumber) {
var CalendarEvent = new Lang.Class({
Name: 'CalendarEvent',
_init: function(id, date, end, summary, allDay) {
_init(id, date, end, summary, allDay) {
this.id = id;
this.date = date;
this.end = end;
@ -108,44 +108,45 @@ var CalendarEvent = new Lang.Class({
var EmptyEventSource = new Lang.Class({
Name: 'EmptyEventSource',
_init: function() {
_init() {
this.isLoading = false;
this.isDummy = true;
this.hasCalendars = false;
},
destroy: function() {
destroy() {
},
ignoreEvent: function(event) {
ignoreEvent(event) {
},
requestRange: function(begin, end) {
requestRange(begin, end) {
},
getEvents: function(begin, end) {
getEvents(begin, end) {
let result = [];
return result;
},
hasEvents: function(day) {
hasEvents(day) {
return false;
}
});
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = '<node> \
<interface name="org.gnome.Shell.CalendarServer"> \
<method name="GetEvents"> \
<arg type="x" direction="in" /> \
<arg type="x" direction="in" /> \
<arg type="b" direction="in" /> \
<arg type="a(sssbxxa{sv})" direction="out" /> \
</method> \
<property name="HasCalendars" type="b" access="read" /> \
<signal name="Changed" /> \
</interface> \
</node>';
const CalendarServerIface = `
<node>
<interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<property name="HasCalendars" type="b" access="read" />
<signal name="Changed" />
</interface>
</node>`;
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
@ -179,7 +180,7 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
var DBusEventSource = new Lang.Class({
Name: 'DBusEventSource',
_init: function() {
_init() {
this._resetCache();
this.isLoading = false;
this.isDummy = false;
@ -188,14 +189,13 @@ var DBusEventSource = new Lang.Class({
let savedState = global.get_persistent_state('as', 'ignored_events');
if (savedState)
savedState.deep_unpack().forEach(Lang.bind(this,
function(eventId) {
this._ignoredEvents.set(eventId, true);
}));
savedState.deep_unpack().forEach(eventId => {
this._ignoredEvents.set(eventId, true);
});
this._initialized = false;
this._dbusProxy = new CalendarServer();
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(object, result) {
this._dbusProxy.init_async(GLib.PRIORITY_DEFAULT, null, (object, result) => {
let loaded = false;
try {
@ -216,28 +216,28 @@ var DBusEventSource = new Lang.Class({
}
}
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
this._dbusProxy.connectSignal('Changed', this._onChanged.bind(this));
this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
this._dbusProxy.connect('notify::g-name-owner', () => {
if (this._dbusProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
}));
});
this._dbusProxy.connect('g-properties-changed', Lang.bind(this, function() {
this._dbusProxy.connect('g-properties-changed', () => {
this.emit('notify::has-calendars');
}));
});
this._initialized = loaded;
if (loaded) {
this.emit('notify::has-calendars');
this._onNameAppeared();
}
}));
});
},
destroy: function() {
destroy() {
this._dbusProxy.run_dispose();
},
@ -248,28 +248,28 @@ var DBusEventSource = new Lang.Class({
return false;
},
_resetCache: function() {
_resetCache() {
this._events = [];
this._lastRequestBegin = null;
this._lastRequestEnd = null;
},
_onNameAppeared: function(owner) {
_onNameAppeared(owner) {
this._initialized = true;
this._resetCache();
this._loadEvents(true);
},
_onNameVanished: function(oldOwner) {
_onNameVanished(oldOwner) {
this._resetCache();
this.emit('changed');
},
_onChanged: function() {
_onChanged() {
this._loadEvents(false);
},
_onEventsReceived: function(results, error) {
_onEventsReceived(results, error) {
let newEvents = [];
let appointments = results ? results[0] : null;
if (appointments != null) {
@ -283,9 +283,7 @@ var DBusEventSource = new Lang.Class({
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort(function(event1, event2) {
return event1.date.getTime() - event2.date.getTime();
});
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
}
this._events = newEvents;
@ -293,7 +291,7 @@ var DBusEventSource = new Lang.Class({
this.emit('changed');
},
_loadEvents: function(forceReload) {
_loadEvents(forceReload) {
// Ignore while loading
if (!this._initialized)
return;
@ -302,12 +300,12 @@ var DBusEventSource = new Lang.Class({
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
Lang.bind(this, this._onEventsReceived),
this._onEventsReceived.bind(this),
Gio.DBusCallFlags.NONE);
}
},
ignoreEvent: function(event) {
ignoreEvent(event) {
if (this._ignoredEvents.get(event.id))
return;
@ -317,7 +315,7 @@ var DBusEventSource = new Lang.Class({
this.emit('changed');
},
requestRange: function(begin, end) {
requestRange(begin, end) {
if (!(_datesEqual(begin, this._lastRequestBegin) && _datesEqual(end, this._lastRequestEnd))) {
this.isLoading = true;
this._lastRequestBegin = begin;
@ -328,7 +326,7 @@ var DBusEventSource = new Lang.Class({
}
},
getEvents: function(begin, end) {
getEvents(begin, end) {
let result = [];
for(let n = 0; n < this._events.length; n++) {
let event = this._events[n];
@ -340,7 +338,7 @@ var DBusEventSource = new Lang.Class({
result.push(event);
}
}
result.sort(function(event1, event2) {
result.sort((event1, event2) => {
// sort events by end time on ending day
let d1 = event1.date < begin && event1.end <= end ? event1.end : event1.date;
let d2 = event2.date < begin && event2.end <= end ? event2.end : event2.date;
@ -349,7 +347,7 @@ var DBusEventSource = new Lang.Class({
return result;
},
hasEvents: function(day) {
hasEvents(day) {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
@ -366,11 +364,11 @@ Signals.addSignalMethods(DBusEventSource.prototype);
var Calendar = new Lang.Class({
Name: 'Calendar',
_init: function() {
_init() {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, this._onSettingsChange.bind(this));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
/**
@ -401,25 +399,25 @@ var Calendar = new Lang.Class({
reactive: true });
this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll));
this._onScroll.bind(this));
this._buildHeader ();
},
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
setEventSource: function(eventSource) {
setEventSource(eventSource) {
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, function() {
this._eventSource.connect('changed', () => {
this._rebuildCalendar();
this._update();
}));
});
this._rebuildCalendar();
this._update();
},
// Sets the calendar to show a specific date
setDate: function(date) {
setDate(date) {
if (sameDay(date, this._selectedDate))
return;
@ -428,14 +426,14 @@ var Calendar = new Lang.Class({
this.emit('selected-date-changed', new Date(this._selectedDate));
},
updateTimeZone: function() {
updateTimeZone() {
// The calendar need to be rebuilt after a time zone update because
// the date might have changed.
this._rebuildCalendar();
this._update();
},
_buildHeader: function() {
_buildHeader() {
let layout = this.actor.layout_manager;
let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_all_children();
@ -449,7 +447,7 @@ var Calendar = new Lang.Class({
accessible_name: _("Previous month"),
can_focus: true });
this._topBox.add(this._backButton);
this._backButton.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this));
this._monthLabel = new St.Label({style_class: 'calendar-month-label',
can_focus: true });
@ -459,7 +457,7 @@ var Calendar = new Lang.Class({
accessible_name: _("Next month"),
can_focus: true });
this._topBox.add(this._forwardButton);
this._forwardButton.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));
this._forwardButton.connect('clicked', this._onNextMonthButtonClicked.bind(this));
// Add weekday labels...
//
@ -490,7 +488,7 @@ var Calendar = new Lang.Class({
this._firstDayIndex = this.actor.get_n_children();
},
_onScroll : function(actor, event) {
_onScroll(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT:
@ -504,7 +502,7 @@ var Calendar = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_onPrevMonthButtonClicked: function() {
_onPrevMonthButtonClicked() {
let newDate = new Date(this._selectedDate);
let oldMonth = newDate.getMonth();
if (oldMonth == 0) {
@ -528,7 +526,7 @@ var Calendar = new Lang.Class({
this.setDate(newDate);
},
_onNextMonthButtonClicked: function() {
_onNextMonthButtonClicked() {
let newDate = new Date(this._selectedDate);
let oldMonth = newDate.getMonth();
if (oldMonth == 11) {
@ -552,14 +550,14 @@ var Calendar = new Lang.Class({
this.setDate(newDate);
},
_onSettingsChange: function() {
_onSettingsChange() {
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
this._buildHeader();
this._rebuildCalendar();
this._update();
},
_rebuildCalendar: function() {
_rebuildCalendar() {
let now = new Date();
// Remove everything but the topBox and the weekday labels
@ -617,11 +615,11 @@ var Calendar = new Lang.Class({
button.reactive = false;
button._date = new Date(iter);
button.connect('clicked', Lang.bind(this, function() {
button.connect('clicked', () => {
this._shouldDateGrabFocus = true;
this.setDate(button._date);
this._shouldDateGrabFocus = false;
}));
});
let hasEvents = this._eventSource.hasEvents(iter);
let styleClass = 'calendar-day-base calendar-day';
@ -680,7 +678,7 @@ var Calendar = new Lang.Class({
this._eventSource.requestRange(beginDate, iter);
},
_update: function() {
_update() {
let now = new Date();
if (sameYear(this._selectedDate, now))
@ -691,7 +689,7 @@ var Calendar = new Lang.Class({
if (!this._calendarBegin || !sameMonth(this._selectedDate, this._calendarBegin) || !sameDay(now, this._markedAsToday))
this._rebuildCalendar();
this._buttons.forEach(Lang.bind(this, function(button) {
this._buttons.forEach(button => {
if (sameDay(button._date, this._selectedDate)) {
button.add_style_pseudo_class('selected');
if (this._shouldDateGrabFocus)
@ -699,7 +697,7 @@ var Calendar = new Lang.Class({
}
else
button.remove_style_pseudo_class('selected');
}));
});
}
});
Signals.addSignalMethods(Calendar.prototype);
@ -708,7 +706,7 @@ var EventMessage = new Lang.Class({
Name: 'EventMessage',
Extends: MessageList.Message,
_init: function(event, date) {
_init(event, date) {
this._event = event;
this._date = date;
@ -723,7 +721,7 @@ var EventMessage = new Lang.Class({
});
},
_formatEventTime: function() {
_formatEventTime() {
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
let allDay = (this._event.allDay || (this._event.date <= periodBegin &&
@ -756,7 +754,7 @@ var EventMessage = new Lang.Class({
return title;
},
canClose: function() {
canClose() {
return isToday(this._date);
}
});
@ -765,7 +763,7 @@ var NotificationMessage = new Lang.Class({
Name: 'NotificationMessage',
Extends: MessageList.Message,
_init: function(notification) {
_init(notification) {
this.notification = notification;
this.parent(notification.title, notification.bannerBodyText);
@ -773,21 +771,19 @@ var NotificationMessage = new Lang.Class({
this.setIcon(this._getIcon());
this.connect('close', Lang.bind(this,
function() {
this._closed = true;
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
}));
this._destroyId = notification.connect('destroy', Lang.bind(this,
function() {
if (!this._closed)
this.close();
}));
this.connect('close', () => {
this._closed = true;
this.notification.destroy(MessageTray.NotificationDestroyedReason.DISMISSED);
});
this._destroyId = notification.connect('destroy', () => {
if (!this._closed)
this.close();
});
this._updatedId = notification.connect('updated',
Lang.bind(this, this._onUpdated));
this._onUpdated.bind(this));
},
_getIcon: function() {
_getIcon() {
if (this.notification.gicon)
return new St.Icon({ gicon: this.notification.gicon,
icon_size: MESSAGE_ICON_SIZE });
@ -795,18 +791,18 @@ var NotificationMessage = new Lang.Class({
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
},
_onUpdated: function(n, clear) {
_onUpdated(n, clear) {
this.setIcon(this._getIcon());
this.setTitle(n.title);
this.setBody(n.bannerBodyText);
this.setUseBodyMarkup(n.bannerBodyMarkup);
},
_onClicked: function() {
_onClicked() {
this.notification.activate();
},
_onDestroy: function() {
_onDestroy() {
if (this._updatedId)
this.notification.disconnect(this._updatedId);
this._updatedId = 0;
@ -821,11 +817,13 @@ var EventsSection = new Lang.Class({
Name: 'EventsSection',
Extends: MessageList.MessageListSection,
_init: function() {
_init() {
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._reloadEvents));
this._desktopSettings.connect('changed', this._reloadEvents.bind(this));
this._eventSource = new EmptyEventSource();
this._messageById = new Map();
this.parent();
this._title = new St.Button({ style_class: 'events-section-title',
@ -834,28 +832,28 @@ var EventsSection = new Lang.Class({
can_focus: true });
this.actor.insert_child_below(this._title, null);
this._title.connect('clicked', Lang.bind(this, this._onTitleClicked));
this._title.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
Shell.AppSystem.get_default().connect('installed-changed',
Lang.bind(this, this._appInstalledChanged));
this._appInstalledChanged.bind(this));
this._appInstalledChanged();
},
_ignoreEvent: function(event) {
_ignoreEvent(event) {
this._eventSource.ignoreEvent(event);
},
setEventSource: function(eventSource) {
setEventSource(eventSource) {
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, this._reloadEvents));
this._eventSource.connect('changed', this._reloadEvents.bind(this));
},
get allowed() {
return Main.sessionMode.showCalendarEvents;
},
_updateTitle: function() {
_updateTitle() {
this._title.visible = !isToday(this._date);
if (!this._title.visible)
@ -874,45 +872,57 @@ var EventsSection = new Lang.Class({
this._title.label = this._date.toLocaleFormat(dayFormat);
},
_reloadEvents: function() {
_reloadEvents() {
if (this._eventSource.isLoading)
return;
this._reloading = true;
this._list.destroy_all_children();
let periodBegin = _getBeginningOfDay(this._date);
let periodEnd = _getEndOfDay(this._date);
let events = this._eventSource.getEvents(periodBegin, periodEnd);
let ids = events.map(e => e.id);
this._messageById.forEach((message, id) => {
if (ids.includes(id))
return;
this._messageById.delete(id);
this.removeMessage(message);
});
for (let i = 0; i < events.length; i++) {
let event = events[i];
let message = new EventMessage(event, this._date);
message.connect('close', Lang.bind(this, function() {
this._ignoreEvent(event);
}));
this.addMessage(message, false);
let message = this._messageById.get(event.id);
if (!message) {
message = new EventMessage(event, this._date);
message.connect('close', () => {
this._ignoreEvent(event);
});
this._messageById.set(event.id, message);
this.addMessage(message, false);
} else {
this.moveMessage(message, i, false);
}
}
this._reloading = false;
this._sync();
},
_appInstalledChanged: function() {
_appInstalledChanged() {
this._calendarApp = undefined;
this._title.reactive = (this._getCalendarApp() != null);
},
_getCalendarApp: function() {
_getCalendarApp() {
if (this._calendarApp !== undefined)
return this._calendarApp;
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
if (apps && (apps.length > 0)) {
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
let defaultInRecommended = apps.some(function(a) { return a.equal(app); });
let defaultInRecommended = apps.some(a => a.equal(app));
this._calendarApp = defaultInRecommended ? app : apps[0];
} else {
this._calendarApp = null;
@ -920,7 +930,7 @@ var EventsSection = new Lang.Class({
return this._calendarApp;
},
_onTitleClicked: function() {
_onTitleClicked() {
Main.overview.hide();
Main.panel.closeCalendar();
@ -930,17 +940,17 @@ var EventsSection = new Lang.Class({
app.launch([], global.create_app_launch_context(0, -1));
},
setDate: function(date) {
setDate(date) {
this.parent(date);
this._updateTitle();
this._reloadEvents();
},
_shouldShow: function() {
_shouldShow() {
return !this.empty || !isToday(this._date);
},
_sync: function() {
_sync() {
if (this._reloading)
return;
@ -952,18 +962,18 @@ var NotificationSection = new Lang.Class({
Name: 'NotificationSection',
Extends: MessageList.MessageListSection,
_init: function() {
_init() {
this.parent();
this._sources = new Map();
this._nUrgent = 0;
Main.messageTray.connect('source-added', Lang.bind(this, this._sourceAdded));
Main.messageTray.getSources().forEach(Lang.bind(this, function(source) {
Main.messageTray.connect('source-added', this._sourceAdded.bind(this));
Main.messageTray.getSources().forEach(source => {
this._sourceAdded(Main.messageTray, source);
}));
});
this.actor.connect('notify::mapped', Lang.bind(this, this._onMapped));
this.actor.connect('notify::mapped', this._onMapped.bind(this));
},
get allowed() {
@ -971,7 +981,7 @@ var NotificationSection = new Lang.Class({
!Main.sessionMode.isGreeter;
},
_createTimeLabel: function(datetime) {
_createTimeLabel(datetime) {
let label = new St.Label({ style_class: 'event-time',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.END });
@ -982,39 +992,37 @@ var NotificationSection = new Lang.Class({
return label;
},
_sourceAdded: function(tray, source) {
_sourceAdded(tray, source) {
let obj = {
destroyId: 0,
notificationAddedId: 0,
};
obj.destroyId = source.connect('destroy', Lang.bind(this, function(source) {
obj.destroyId = source.connect('destroy', source => {
this._onSourceDestroy(source, obj);
}));
});
obj.notificationAddedId = source.connect('notification-added',
Lang.bind(this, this._onNotificationAdded));
this._onNotificationAdded.bind(this));
this._sources.set(source, obj);
},
_onNotificationAdded: function(source, notification) {
_onNotificationAdded(source, notification) {
let message = new NotificationMessage(notification);
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
let isUrgent = notification.urgency == MessageTray.Urgency.CRITICAL;
let updatedId = notification.connect('updated', Lang.bind(this,
function() {
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped);
}));
let destroyId = notification.connect('destroy', Lang.bind(this,
function() {
notification.disconnect(destroyId);
notification.disconnect(updatedId);
if (isUrgent)
this._nUrgent--;
}));
let updatedId = notification.connect('updated', () => {
message.setSecondaryActor(this._createTimeLabel(notification.datetime));
this.moveMessage(message, isUrgent ? 0 : this._nUrgent, this.actor.mapped);
});
let destroyId = notification.connect('destroy', () => {
notification.disconnect(destroyId);
notification.disconnect(updatedId);
if (isUrgent)
this._nUrgent--;
});
if (isUrgent) {
// Keep track of urgent notifications to keep them on top
@ -1030,14 +1038,14 @@ var NotificationSection = new Lang.Class({
this.addMessageAtIndex(message, index, this.actor.mapped);
},
_onSourceDestroy: function(source, obj) {
_onSourceDestroy(source, obj) {
source.disconnect(obj.destroyId);
source.disconnect(obj.notificationAddedId);
this._sources.delete(source);
},
_onMapped: function() {
_onMapped() {
if (!this.actor.mapped)
return;
@ -1046,7 +1054,7 @@ var NotificationSection = new Lang.Class({
message.notification.acknowledged = true;
},
_shouldShow: function() {
_shouldShow() {
return !this.empty && isToday(this._date);
}
});
@ -1054,7 +1062,7 @@ var NotificationSection = new Lang.Class({
var Placeholder = new Lang.Class({
Name: 'Placeholder',
_init: function() {
_init() {
this.actor = new St.BoxLayout({ style_class: 'message-list-placeholder',
vertical: true });
@ -1074,14 +1082,14 @@ var Placeholder = new Lang.Class({
this._sync();
},
setDate: function(date) {
setDate(date) {
if (sameDay(this._date, date))
return;
this._date = date;
this._sync();
},
_sync: function() {
_sync() {
let today = isToday(this._date);
if (today && this._icon.gicon == this._todayIcon)
return;
@ -1101,7 +1109,7 @@ var Placeholder = new Lang.Class({
var CalendarMessageList = new Lang.Class({
Name: 'CalendarMessageList',
_init: function() {
_init() {
this.actor = new St.Widget({ style_class: 'message-list',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
@ -1146,10 +1154,10 @@ var CalendarMessageList = new Lang.Class({
this._eventsSection = new EventsSection();
this._addSection(this._eventsSection);
Main.sessionMode.connect('updated', Lang.bind(this, this._sync));
Main.sessionMode.connect('updated', this._sync.bind(this));
},
_addSection: function(section) {
_addSection(section) {
let obj = {
destroyId: 0,
visibleId: 0,
@ -1157,25 +1165,24 @@ var CalendarMessageList = new Lang.Class({
canClearChangedId: 0,
keyFocusId: 0
};
obj.destroyId = section.actor.connect('destroy', Lang.bind(this,
function() {
this._removeSection(section);
}));
obj.destroyId = section.actor.connect('destroy', () => {
this._removeSection(section);
});
obj.visibleId = section.actor.connect('notify::visible',
Lang.bind(this, this._sync));
this._sync.bind(this));
obj.emptyChangedId = section.connect('empty-changed',
Lang.bind(this, this._sync));
this._sync.bind(this));
obj.canClearChangedId = section.connect('can-clear-changed',
Lang.bind(this, this._sync));
this._sync.bind(this));
obj.keyFocusId = section.connect('key-focus-in',
Lang.bind(this, this._onKeyFocusIn));
this._onKeyFocusIn.bind(this));
this._sections.set(section, obj);
this._sectionList.add_actor(section.actor);
this._sync();
},
_removeSection: function(section) {
_removeSection(section) {
let obj = this._sections.get(section);
section.actor.disconnect(obj.destroyId);
section.actor.disconnect(obj.visibleId);
@ -1188,36 +1195,30 @@ var CalendarMessageList = new Lang.Class({
this._sync();
},
_onKeyFocusIn: function(section, actor) {
_onKeyFocusIn(section, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
_sync: function() {
_sync() {
let sections = [...this._sections.keys()];
let visible = sections.some(function(s) {
return s.allowed;
});
let visible = sections.some(s => s.allowed);
this.actor.visible = visible;
if (!visible)
return;
let empty = sections.every(function(s) {
return s.empty || !s.actor.visible;
});
let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty;
this._clearButton.visible = !empty;
let canClear = sections.some(function(s) {
return s.canClear && s.actor.visible;
});
let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear;
},
setEventSource: function(eventSource) {
setEventSource(eventSource) {
this._eventsSection.setEventSource(eventSource);
},
setDate: function(date) {
setDate(date) {
for (let section of this._sections.keys())
section.setDate(date);
this._placeholder.setDate(date);

View File

@ -7,7 +7,7 @@ const Lang = imports.lang;
var CheckBox = new Lang.Class({
Name: 'CheckBox',
_init: function(label) {
_init(label) {
let container = new St.BoxLayout();
this.actor = new St.Button({ style_class: 'check-box',
child: container,
@ -30,11 +30,11 @@ var CheckBox = new Lang.Class({
this.setLabel(label);
},
setLabel: function(label) {
setLabel(label) {
this._label.set_text(label);
},
getLabelActor: function() {
getLabelActor() {
return this._label;
}
});

View File

@ -2,6 +2,7 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
@ -13,6 +14,7 @@ const Tweener = imports.ui.tweener;
var FROZEN_WINDOW_BRIGHTNESS = -0.3
var DIALOG_TRANSITION_TIME = 0.15
var ALIVE_TIMEOUT = 5000;
var CloseDialog = new Lang.Class({
Name: 'CloseDialog',
@ -22,10 +24,11 @@ var CloseDialog = new Lang.Class({
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
},
_init: function (window) {
_init(window) {
this.parent();
this._window = window;
this._dialog = null;
this._timeoutId = 0;
},
get window() {
@ -36,7 +39,7 @@ var CloseDialog = new Lang.Class({
this._window = window;
},
_createDialogContent: function () {
_createDialogContent() {
let tracker = Shell.WindowTracker.get_default();
let windowApp = tracker.get_window_app(this._window);
@ -48,7 +51,7 @@ var CloseDialog = new Lang.Class({
return new Dialog.MessageDialogContent({ icon, title, subtitle });
},
_initDialog: function () {
_initDialog() {
if (this._dialog)
return;
@ -59,16 +62,16 @@ var CloseDialog = new Lang.Class({
this._dialog.addContent(this._createDialogContent());
this._dialog.addButton({ label: _('Force Quit'),
action: Lang.bind(this, this._onClose),
action: this._onClose.bind(this),
default: true });
this._dialog.addButton({ label: _('Wait'),
action: Lang.bind(this, this._onWait),
action: this._onWait.bind(this),
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
},
_addWindowEffect: function () {
_addWindowEffect() {
// We set the effect on the surface actor, so the dialog itself
// (which is a child of the MetaWindowActor) does not get the
// effect applied itself.
@ -79,24 +82,32 @@ var CloseDialog = new Lang.Class({
surfaceActor.add_effect_with_name("gnome-shell-frozen-window", effect);
},
_removeWindowEffect: function () {
_removeWindowEffect() {
let windowActor = this._window.get_compositor_private();
let surfaceActor = windowActor.get_first_child();
surfaceActor.remove_effect_by_name("gnome-shell-frozen-window");
},
_onWait: function () {
_onWait() {
this.response(Meta.CloseDialogResponse.WAIT);
},
_onClose: function () {
_onClose() {
this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
},
vfunc_show: function () {
vfunc_show() {
if (this._dialog != null)
return;
Meta.disable_unredirect_for_display(global.display);
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ALIVE_TIMEOUT,
() => {
this._window.check_alive(global.display.get_current_time_roundtrip());
return GLib.SOURCE_CONTINUE;
});
this._addWindowEffect();
this._initDialog();
@ -107,16 +118,21 @@ var CloseDialog = new Lang.Class({
{ scale_y: 1,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: Lang.bind(this, function () {
onComplete: () => {
Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
})
}
});
},
vfunc_hide: function () {
vfunc_hide() {
if (this._dialog == null)
return;
Meta.enable_unredirect_for_display(global.display);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
let dialog = this._dialog;
this._dialog = null;
this._removeWindowEffect();
@ -125,13 +141,13 @@ var CloseDialog = new Lang.Class({
{ scale_y: 0,
transition: 'linear',
time: DIALOG_TRANSITION_TIME,
onComplete: Lang.bind(this, function () {
onComplete: () => {
dialog.destroy();
})
}
});
},
vfunc_focus: function () {
vfunc_focus() {
if (this._dialog)
this._dialog.grab_key_focus();
}

View File

@ -5,38 +5,38 @@ const Main = imports.ui.main;
var ComponentManager = new Lang.Class({
Name: 'ComponentManager',
_init: function() {
_init() {
this._allComponents = {};
this._enabledComponents = [];
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
},
_sessionUpdated: function() {
_sessionUpdated() {
let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter(Lang.bind(this, function(name) {
return this._enabledComponents.indexOf(name) == -1;
})).forEach(Lang.bind(this, function(name) {
newEnabledComponents.filter(
name => this._enabledComponents.indexOf(name) == -1
).forEach(name => {
this._enableComponent(name);
}));
});
this._enabledComponents.filter(Lang.bind(this, function(name) {
return newEnabledComponents.indexOf(name) == -1;
})).forEach(Lang.bind(this, function(name) {
this._enabledComponents.filter(
name => newEnabledComponents.indexOf(name) == -1
).forEach(name => {
this._disableComponent(name);
}));
});
this._enabledComponents = newEnabledComponents;
},
_importComponent: function(name) {
_importComponent(name) {
let module = imports.ui.components[name];
return module.Component;
},
_ensureComponent: function(name) {
_ensureComponent(name) {
let component = this._allComponents[name];
if (component)
return component;
@ -50,13 +50,13 @@ var ComponentManager = new Lang.Class({
return component;
},
_enableComponent: function(name) {
_enableComponent(name) {
let component = this._ensureComponent(name);
if (component)
component.enable();
},
_disableComponent: function(name) {
_disableComponent(name) {
let component = this._allComponents[name];
if (component == null)
return;

View File

@ -22,31 +22,31 @@ var AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
var AutomountManager = new Lang.Class({
Name: 'AutomountManager',
_init: function() {
_init() {
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
this._volumeQueue = [];
this._session = new GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded',
Lang.bind(this, this._InhibitorsChanged));
this._InhibitorsChanged.bind(this));
this._session.connectSignal('InhibitorRemoved',
Lang.bind(this, this._InhibitorsChanged));
this._InhibitorsChanged.bind(this));
this._inhibited = false;
this._volumeMonitor = Gio.VolumeMonitor.get();
},
enable: function() {
this._volumeAddedId = this._volumeMonitor.connect('volume-added', Lang.bind(this, this._onVolumeAdded));
this._volumeRemovedId = this._volumeMonitor.connect('volume-removed', Lang.bind(this, this._onVolumeRemoved));
this._driveConnectedId = this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._onDriveConnected));
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._onDriveDisconnected));
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', Lang.bind(this, this._onDriveEjectButton));
enable() {
this._volumeAddedId = this._volumeMonitor.connect('volume-added', this._onVolumeAdded.bind(this));
this._volumeRemovedId = this._volumeMonitor.connect('volume-removed', this._onVolumeRemoved.bind(this));
this._driveConnectedId = this._volumeMonitor.connect('drive-connected', this._onDriveConnected.bind(this));
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', this._onDriveDisconnected.bind(this));
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', this._onDriveEjectButton.bind(this));
this._mountAllId = Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
},
disable: function() {
disable() {
this._volumeMonitor.disconnect(this._volumeAddedId);
this._volumeMonitor.disconnect(this._volumeRemovedId);
this._volumeMonitor.disconnect(this._driveConnectedId);
@ -59,29 +59,28 @@ var AutomountManager = new Lang.Class({
}
},
_InhibitorsChanged: function(object, senderName, [inhibtor]) {
_InhibitorsChanged(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
Lang.bind(this,
function(result, error) {
if (!error) {
this._inhibited = result[0];
}
}));
(result, error) => {
if (!error) {
this._inhibited = result[0];
}
});
},
_startupMountAll: function() {
_startupMountAll() {
let volumes = this._volumeMonitor.get_volumes();
volumes.forEach(Lang.bind(this, function(volume) {
volumes.forEach(volume => {
this._checkAndMountVolume(volume, { checkSession: false,
useMountOp: false,
allowAutorun: false });
}));
});
this._mountAllId = 0;
return GLib.SOURCE_REMOVE;
},
_onDriveConnected: function() {
_onDriveConnected() {
// if we're not in the current ConsoleKit session,
// or screensaver is active, don't play sounds
if (!this._session.SessionIsActive)
@ -92,7 +91,7 @@ var AutomountManager = new Lang.Class({
null);
},
_onDriveDisconnected: function() {
_onDriveDisconnected() {
// if we're not in the current ConsoleKit session,
// or screensaver is active, don't play sounds
if (!this._session.SessionIsActive)
@ -103,7 +102,7 @@ var AutomountManager = new Lang.Class({
null);
},
_onDriveEjectButton: function(monitor, drive) {
_onDriveEjectButton(monitor, drive) {
// TODO: this code path is not tested, as the GVfs volume monitor
// doesn't emit this signal just yet.
if (!this._session.SessionIsActive)
@ -114,31 +113,31 @@ var AutomountManager = new Lang.Class({
if (drive.can_stop()) {
drive.stop
(Gio.MountUnmountFlags.FORCE, null, null,
Lang.bind(this, function(drive, res) {
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
log("Unable to stop the drive after drive-eject-button " + e.toString());
}
}));
});
} else if (drive.can_eject()) {
drive.eject_with_operation
(Gio.MountUnmountFlags.FORCE, null, null,
Lang.bind(this, function(drive, res) {
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
log("Unable to eject the drive after drive-eject-button " + e.toString());
}
}));
});
}
},
_onVolumeAdded: function(monitor, volume) {
_onVolumeAdded(monitor, volume) {
this._checkAndMountVolume(volume);
},
_checkAndMountVolume: function(volume, params) {
_checkAndMountVolume(volume, params) {
params = Params.parse(params, { checkSession: true,
useMountOp: true,
allowAutorun: true });
@ -178,7 +177,7 @@ var AutomountManager = new Lang.Class({
}
},
_mountVolume: function(volume, operation, allowAutorun) {
_mountVolume(volume, operation, allowAutorun) {
if (allowAutorun)
this._allowAutorun(volume);
@ -186,10 +185,10 @@ var AutomountManager = new Lang.Class({
volume._operation = operation;
volume.mount(0, mountOp, null,
Lang.bind(this, this._onVolumeMounted));
this._onVolumeMounted.bind(this));
},
_onVolumeMounted: function(volume, res) {
_onVolumeMounted(volume, res) {
this._allowAutorunExpire(volume);
try {
@ -210,14 +209,12 @@ var AutomountManager = new Lang.Class({
}
},
_onVolumeRemoved: function(monitor, volume) {
_onVolumeRemoved(monitor, volume) {
this._volumeQueue =
this._volumeQueue.filter(function(element) {
return (element != volume);
});
this._volumeQueue.filter(element => (element != volume));
},
_reaskPassword: function(volume) {
_reaskPassword(volume) {
let existingDialog = volume._operation ? volume._operation.borrowDialog() : null;
let operation =
new ShellMountOperation.ShellMountOperation(volume,
@ -225,17 +222,17 @@ var AutomountManager = new Lang.Class({
this._mountVolume(volume, operation);
},
_closeOperation: function(volume) {
_closeOperation(volume) {
if (volume._operation)
volume._operation.close();
},
_allowAutorun: function(volume) {
_allowAutorun(volume) {
volume.allowAutorun = true;
},
_allowAutorunExpire: function(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, function() {
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false;
return GLib.SOURCE_REMOVE;
});

View File

@ -74,14 +74,15 @@ function startAppForMount(app, mount) {
/******************************************/
const HotplugSnifferIface = '<node> \
<interface name="org.gnome.Shell.HotplugSniffer"> \
<method name="SniffURI"> \
<arg type="s" direction="in" /> \
<arg type="as" direction="out" /> \
</method> \
</interface> \
</node>';
const HotplugSnifferIface = `
<node>
<interface name="org.gnome.Shell.HotplugSniffer">
<method name="SniffURI">
<arg type="s" direction="in" />
<arg type="as" direction="out" />
</method>
</interface>
</node>`;
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {
@ -93,26 +94,25 @@ function HotplugSniffer() {
var ContentTypeDiscoverer = new Lang.Class({
Name: 'ContentTypeDiscoverer',
_init: function(callback) {
_init(callback) {
this._callback = callback;
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
},
guessContentTypes: function(mount) {
guessContentTypes(mount) {
let autorunEnabled = !this._settings.get_boolean(SETTING_DISABLE_AUTORUN);
let shouldScan = autorunEnabled && !isMountNonLocal(mount);
if (shouldScan) {
// guess mount's content types using GIO
mount.guess_content_type(false, null,
Lang.bind(this,
this._onContentTypeGuessed));
this._onContentTypeGuessed.bind(this));
} else {
this._emitCallback(mount, []);
}
},
_onContentTypeGuessed: function(mount, res) {
_onContentTypeGuessed(mount, res) {
let contentTypes = [];
try {
@ -129,23 +129,23 @@ var ContentTypeDiscoverer = new Lang.Class({
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(),
Lang.bind(this, function([contentTypes]) {
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
}));
});
}
},
_emitCallback: function(mount, contentTypes) {
_emitCallback(mount, contentTypes) {
if (!contentTypes)
contentTypes = [];
// we're not interested in win32 software content types here
contentTypes = contentTypes.filter(function(type) {
return (type != 'x-content/win32-software');
});
contentTypes = contentTypes.filter(
type => (type != 'x-content/win32-software')
);
let apps = [];
contentTypes.forEach(function(type) {
contentTypes.forEach(type => {
let app = Gio.app_info_get_default_for_type(type, false);
if (app)
@ -162,36 +162,36 @@ var ContentTypeDiscoverer = new Lang.Class({
var AutorunManager = new Lang.Class({
Name: 'AutorunManager',
_init: function() {
_init() {
this._session = new GnomeSession.SessionManager();
this._volumeMonitor = Gio.VolumeMonitor.get();
this._dispatcher = new AutorunDispatcher(this);
},
enable: function() {
this._mountAddedId = this._volumeMonitor.connect('mount-added', Lang.bind(this, this._onMountAdded));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._onMountRemoved));
enable() {
this._mountAddedId = this._volumeMonitor.connect('mount-added', this._onMountAdded.bind(this));
this._mountRemovedId = this._volumeMonitor.connect('mount-removed', this._onMountRemoved.bind(this));
},
disable: function() {
disable() {
this._volumeMonitor.disconnect(this._mountAddedId);
this._volumeMonitor.disconnect(this._mountRemovedId);
},
_onMountAdded: function(monitor, mount) {
_onMountAdded(monitor, mount) {
// don't do anything if our session is not the currently
// active one
if (!this._session.SessionIsActive)
return;
let discoverer = new ContentTypeDiscoverer(Lang.bind(this, function(mount, apps, contentTypes) {
let discoverer = new ContentTypeDiscoverer((mount, apps, contentTypes) => {
this._dispatcher.addMount(mount, apps, contentTypes);
}));
});
discoverer.guessContentTypes(mount);
},
_onMountRemoved: function(monitor, mount) {
_onMountRemoved(monitor, mount) {
this._dispatcher.removeMount(mount);
}
});
@ -199,13 +199,13 @@ var AutorunManager = new Lang.Class({
var AutorunDispatcher = new Lang.Class({
Name: 'AutorunDispatcher',
_init: function(manager) {
_init(manager) {
this._manager = manager;
this._sources = [];
this._settings = new Gio.Settings({ schema_id: SETTINGS_SCHEMA });
},
_getAutorunSettingForType: function(contentType) {
_getAutorunSettingForType(contentType) {
let runApp = this._settings.get_strv(SETTING_START_APP);
if (runApp.indexOf(contentType) != -1)
return AutorunSetting.RUN;
@ -221,11 +221,8 @@ var AutorunDispatcher = new Lang.Class({
return AutorunSetting.ASK;
},
_getSourceForMount: function(mount) {
let filtered =
this._sources.filter(function (source) {
return (source.mount == mount);
});
_getSourceForMount(mount) {
let filtered = this._sources.filter(source => (source.mount == mount));
// we always make sure not to add two sources for the same
// mount in addMount(), so it's safe to assume filtered.length
@ -236,7 +233,7 @@ var AutorunDispatcher = new Lang.Class({
return null;
},
_addSource: function(mount, apps) {
_addSource(mount, apps) {
// if we already have a source showing for this
// mount, return
if (this._getSourceForMount(mount))
@ -246,7 +243,7 @@ var AutorunDispatcher = new Lang.Class({
this._sources.push(new AutorunSource(this._manager, mount, apps));
},
addMount: function(mount, apps, contentTypes) {
addMount(mount, apps, contentTypes) {
// if autorun is disabled globally, return
if (this._settings.get_boolean(SETTING_DISABLE_AUTORUN))
return;
@ -284,7 +281,7 @@ var AutorunDispatcher = new Lang.Class({
this._addSource(mount, apps);
},
removeMount: function(mount) {
removeMount(mount) {
let source = this._getSourceForMount(mount);
// if we aren't tracking this mount, don't do anything
@ -300,7 +297,7 @@ var AutorunSource = new Lang.Class({
Name: 'AutorunSource',
Extends: MessageTray.Source,
_init: function(manager, mount, apps) {
_init(manager, mount, apps) {
this._manager = manager;
this.mount = mount;
this.apps = apps;
@ -314,11 +311,11 @@ var AutorunSource = new Lang.Class({
this.notify(this._notification);
},
getIcon: function() {
getIcon() {
return this.mount.get_icon();
},
_createPolicy: function() {
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy('org.gnome.Nautilus');
}
});
@ -327,27 +324,27 @@ var AutorunNotification = new Lang.Class({
Name: 'AutorunNotification',
Extends: MessageTray.Notification,
_init: function(manager, source) {
_init(manager, source) {
this.parent(source, source.title);
this._manager = manager;
this._mount = source.mount;
},
createBanner: function() {
createBanner() {
let banner = new MessageTray.NotificationBanner(this);
this.source.apps.forEach(Lang.bind(this, function (app) {
this.source.apps.forEach(app => {
let actor = this._buttonForApp(app);
if (actor)
banner.addButton(actor);
}));
});
return banner;
},
_buttonForApp: function(app) {
_buttonForApp(app) {
let box = new St.BoxLayout();
let icon = new St.Icon({ gicon: app.get_icon(),
style_class: 'hotplug-notification-item-icon' });
@ -366,15 +363,15 @@ var AutorunNotification = new Lang.Class({
button_mask: St.ButtonMask.ONE,
style_class: 'hotplug-notification-item button' });
button.connect('clicked', Lang.bind(this, function() {
button.connect('clicked', () => {
startAppForMount(app, this._mount);
this.destroy();
}));
});
return button;
},
activate: function() {
activate() {
this.parent();
let app = Gio.app_info_get_default_for_type('inode/directory', false);

View File

@ -24,13 +24,13 @@ var KeyringDialog = new Lang.Class({
Name: 'KeyringDialog',
Extends: ModalDialog.ModalDialog,
_init: function() {
_init() {
this.parent({ styleClass: 'prompt-dialog' });
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', Lang.bind(this, this._onShowPassword));
this.prompt.connect('show-confirm', Lang.bind(this, this._onShowConfirm));
this.prompt.connect('prompt-close', Lang.bind(this, this._onHidePrompt));
this.prompt.connect('show-password', this._onShowPassword.bind(this));
this.prompt.connect('show-confirm', this._onShowConfirm.bind(this));
this.prompt.connect('prompt-close', this._onHidePrompt.bind(this));
let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
this._content = new Dialog.MessageDialogContent({ icon });
@ -55,17 +55,17 @@ var KeyringDialog = new Lang.Class({
this._controlTable = null;
this._cancelButton = this.addButton({ label: '',
action: Lang.bind(this, this._onCancelButton),
action: this._onCancelButton.bind(this),
key: Clutter.Escape });
this._continueButton = this.addButton({ label: '',
action: Lang.bind(this, this._onContinueButton),
action: this._onContinueButton.bind(this),
default: true });
this.prompt.bind_property('cancel-label', this._cancelButton, 'label', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('continue-label', this._continueButton, 'label', GObject.BindingFlags.SYNC_CREATE);
},
_setWorking: function(working) {
_setWorking(working) {
if (!this._workSpinner)
return;
@ -84,7 +84,7 @@ var KeyringDialog = new Lang.Class({
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
onComplete() {
if (this._workSpinner)
this._workSpinner.stop();
}
@ -92,7 +92,7 @@ var KeyringDialog = new Lang.Class({
}
},
_buildControlTable: function() {
_buildControlTable() {
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout });
@ -112,7 +112,7 @@ var KeyringDialog = new Lang.Class({
x_expand: true });
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
let spinnerIcon = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
this._workSpinner = new Animation.AnimatedIcon(spinnerIcon, WORK_SPINNER_ICON_SIZE);
@ -144,7 +144,7 @@ var KeyringDialog = new Lang.Class({
x_expand: true });
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
this._confirmEntry.clutter_text.connect('activate', this._onConfirmActivate.bind(this));
if (rtl) {
layout.attach(this._confirmEntry, 0, row, 1, 1);
layout.attach(label, 1, row, 1, 1);
@ -185,7 +185,7 @@ var KeyringDialog = new Lang.Class({
this._content.messageBox.add(table, { x_fill: true, y_fill: true });
},
_updateSensitivity: function(sensitive) {
_updateSensitivity(sensitive) {
if (this._passwordEntry) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
@ -201,7 +201,7 @@ var KeyringDialog = new Lang.Class({
this._setWorking(!sensitive);
},
_ensureOpen: function() {
_ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is
// already open - it just returns true without side-effects
if (this.open())
@ -219,41 +219,41 @@ var KeyringDialog = new Lang.Class({
return false;
},
_onShowPassword: function(prompt) {
_onShowPassword(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._passwordEntry.grab_key_focus();
},
_onShowConfirm: function(prompt) {
_onShowConfirm(prompt) {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._continueButton.grab_key_focus();
},
_onHidePrompt: function(prompt) {
_onHidePrompt(prompt) {
this.close();
},
_onPasswordActivate: function() {
_onPasswordActivate() {
if (this.prompt.confirm_visible)
this._confirmEntry.grab_key_focus();
else
this._onContinueButton();
},
_onConfirmActivate: function() {
_onConfirmActivate() {
this._onContinueButton();
},
_onContinueButton: function() {
_onContinueButton() {
this._updateSensitivity(false);
this.prompt.complete();
},
_onCancelButton: function() {
_onCancelButton() {
this.prompt.cancel();
},
});
@ -261,15 +261,13 @@ var KeyringDialog = new Lang.Class({
var KeyringDummyDialog = new Lang.Class({
Name: 'KeyringDummyDialog',
_init: function() {
_init() {
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password',
Lang.bind(this, this._cancelPrompt));
this.prompt.connect('show-confirm', Lang.bind(this,
this._cancelPrompt));
this.prompt.connect('show-password', this._cancelPrompt.bind(this));
this.prompt.connect('show-confirm', this._cancelPrompt.bind(this));
},
_cancelPrompt: function() {
_cancelPrompt() {
this.prompt.cancel();
}
});
@ -277,22 +275,21 @@ var KeyringDummyDialog = new Lang.Class({
var KeyringPrompter = new Lang.Class({
Name: 'KeyringPrompter',
_init: function() {
_init() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', Lang.bind(this,
function() {
let dialog = this._enabled ? new KeyringDialog()
: new KeyringDummyDialog();
this._currentPrompt = dialog.prompt;
return this._currentPrompt;
}));
this._prompter.connect('new-prompt', () => {
let dialog = this._enabled ? new KeyringDialog()
: new KeyringDummyDialog();
this._currentPrompt = dialog.prompt;
return this._currentPrompt;
});
this._dbusId = null;
this._registered = false;
this._enabled = false;
this._currentPrompt = null;
},
enable: function() {
enable() {
if (!this._registered) {
this._prompter.register(Gio.DBus.session);
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
@ -302,7 +299,7 @@ var KeyringPrompter = new Lang.Class({
this._enabled = true;
},
disable: function() {
disable() {
this._enabled = false;
if (this._prompter.prompting)

View File

@ -25,7 +25,7 @@ var NetworkSecretDialog = new Lang.Class({
Name: 'NetworkSecretDialog',
Extends: ModalDialog.ModalDialog,
_init: function(agent, requestId, connection, settingName, hints, contentOverride) {
_init(agent, requestId, connection, settingName, hints, contentOverride) {
this.parent({ styleClass: 'prompt-dialog' });
this._agent = agent;
@ -82,15 +82,15 @@ var NetworkSecretDialog = new Lang.Class({
initialFocusSet = true;
}
secret.entry.clutter_text.connect('activate', Lang.bind(this, this._onOk));
secret.entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
secret.entry.clutter_text.connect('activate', this._onOk.bind(this));
secret.entry.clutter_text.connect('text-changed', () => {
secret.value = secret.entry.get_text();
if (secret.validate)
secret.valid = secret.validate(secret);
else
secret.valid = secret.value.length > 0;
this._updateOkButton();
}));
});
} else
secret.valid = true;
@ -110,12 +110,12 @@ var NetworkSecretDialog = new Lang.Class({
contentBox.messageBox.add(secretTable);
this._okButton = { label: _("Connect"),
action: Lang.bind(this, this._onOk),
action: this._onOk.bind(this),
default: true
};
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
},
this._okButton]);
@ -123,7 +123,7 @@ var NetworkSecretDialog = new Lang.Class({
this._updateOkButton();
},
_updateOkButton: function() {
_updateOkButton() {
let valid = true;
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
@ -134,7 +134,7 @@ var NetworkSecretDialog = new Lang.Class({
this._okButton.button.can_focus = valid;
},
_onOk: function() {
_onOk() {
let valid = true;
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
@ -150,12 +150,12 @@ var NetworkSecretDialog = new Lang.Class({
// do nothing if not valid
},
cancel: function() {
cancel() {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
this.close(global.get_current_time());
},
_validateWpaPsk: function(secret) {
_validateWpaPsk(secret) {
let value = secret.value;
if (value.length == 64) {
// must be composed of hexadecimal digits only
@ -171,7 +171,7 @@ var NetworkSecretDialog = new Lang.Class({
return (value.length >= 8 && value.length <= 63);
},
_validateStaticWep: function(secret) {
_validateStaticWep(secret) {
let value = secret.value;
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
@ -196,7 +196,7 @@ var NetworkSecretDialog = new Lang.Class({
return true;
},
_getWirelessSecrets: function(secrets, wirelessSetting) {
_getWirelessSecrets(secrets, wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
switch (wirelessSecuritySetting.key_mgmt) {
// First the easy ones
@ -227,7 +227,7 @@ var NetworkSecretDialog = new Lang.Class({
}
},
_get8021xSecrets: function(secrets) {
_get8021xSecrets(secrets) {
let ieee8021xSetting = this._connection.get_setting_802_1x();
let phase2method;
@ -256,7 +256,7 @@ var NetworkSecretDialog = new Lang.Class({
}
},
_getPPPoESecrets: function(secrets) {
_getPPPoESecrets(secrets) {
let pppoeSetting = this._connection.get_setting_pppoe();
secrets.push({ label: _("Username: "), key: 'username',
value: pppoeSetting.username || '', password: false });
@ -266,7 +266,7 @@ var NetworkSecretDialog = new Lang.Class({
value: pppoeSetting.password || '', password: true });
},
_getMobileSecrets: function(secrets, connectionType) {
_getMobileSecrets(secrets, connectionType) {
let setting;
if (connectionType == 'bluetooth')
setting = this._connection.get_setting_cdma() || this._connection.get_setting_gsm();
@ -276,7 +276,7 @@ var NetworkSecretDialog = new Lang.Class({
value: setting.value || '', password: true });
},
_getContent: function() {
_getContent() {
let connectionSetting = this._connection.get_setting_connection();
let connectionType = connectionSetting.get_connection_type();
let wirelessSetting;
@ -332,7 +332,7 @@ var NetworkSecretDialog = new Lang.Class({
var VPNRequestHandler = new Lang.Class({
Name: 'VPNRequestHandler',
_init: function(agent, requestId, authHelper, serviceType, connection, hints, flags) {
_init(agent, requestId, authHelper, serviceType, connection, hints, flags) {
this._agent = agent;
this._requestId = requestId;
this._connection = connection;
@ -384,7 +384,7 @@ var VPNRequestHandler = new Lang.Class({
this._readStdoutOldStyle();
this._childWatch = GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid,
Lang.bind(this, this._vpnChildFinished));
this._vpnChildFinished.bind(this));
this._writeConnection();
} catch(e) {
@ -394,7 +394,7 @@ var VPNRequestHandler = new Lang.Class({
}
},
cancel: function(respond) {
cancel(respond) {
if (respond)
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
@ -410,7 +410,7 @@ var VPNRequestHandler = new Lang.Class({
this.destroy();
},
destroy: function() {
destroy() {
if (this._destroyed)
return;
@ -424,7 +424,7 @@ var VPNRequestHandler = new Lang.Class({
this._destroyed = true;
},
_vpnChildFinished: function(pid, status, requestObj) {
_vpnChildFinished(pid, status, requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions
@ -445,7 +445,7 @@ var VPNRequestHandler = new Lang.Class({
this.destroy();
},
_vpnChildProcessLineOldStyle: function(line) {
_vpnChildProcessLineOldStyle(line) {
if (this._previousLine != undefined) {
// Two consecutive newlines mean that the child should be closed
// (the actual newlines are eaten by Gio.DataInputStream)
@ -463,8 +463,8 @@ var VPNRequestHandler = new Lang.Class({
}
},
_readStdoutOldStyle: function() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len] = this._dataStdout.read_line_finish_utf8(result);
if (line == null) {
@ -477,11 +477,11 @@ var VPNRequestHandler = new Lang.Class({
// try to read more!
this._readStdoutOldStyle();
}));
});
},
_readStdoutNewStyle: function() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, Lang.bind(this, function(stream, result) {
_readStdoutNewStyle() {
this._dataStdout.fill_async(-1, GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let cnt = this._dataStdout.fill_finish(result);
if (cnt == 0) {
@ -495,10 +495,10 @@ var VPNRequestHandler = new Lang.Class({
// Try to read more
this._dataStdout.set_buffer_size(2 * this._dataStdout.get_buffer_size());
this._readStdoutNewStyle();
}));
});
},
_showNewStyleDialog: function() {
_showNewStyleDialog() {
let keyfile = new GLib.KeyFile();
let data;
let contentOverride;
@ -506,8 +506,12 @@ var VPNRequestHandler = new Lang.Class({
try {
data = this._dataStdout.peek_buffer();
keyfile.load_from_data(data.toString(), data.length,
GLib.KeyFileFlags.NONE);
if (data instanceof Uint8Array)
data = imports.byteArray.toGBytes(data);
else
data = data.toGBytes();
keyfile.load_from_bytes(data, GLib.KeyFileFlags.NONE);
if (keyfile.get_integer(VPN_UI_GROUP, 'Version') != 2)
throw new Error('Invalid plugin keyfile version, is %d');
@ -558,18 +562,18 @@ var VPNRequestHandler = new Lang.Class({
}
},
_writeConnection: function() {
_writeConnection() {
let vpnSetting = this._connection.get_setting_vpn();
try {
vpnSetting.foreach_data_item(Lang.bind(this, function(key, value) {
vpnSetting.foreach_data_item((key, value) => {
this._stdin.write('DATA_KEY=' + key + '\n', null);
this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
}));
vpnSetting.foreach_secret(Lang.bind(this, function(key, value) {
});
vpnSetting.foreach_secret((key, value) => {
this._stdin.write('SECRET_KEY=' + key + '\n', null);
this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
}));
});
this._stdin.write('DONE\n\n', null);
} catch(e) {
logError(e, 'internal error while writing connection to helper');
@ -584,7 +588,7 @@ Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
_init: function() {
_init() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false
@ -602,26 +606,31 @@ var NetworkAgent = new Lang.Class({
log('Failed to create monitor for VPN plugin dir: ' + e.message);
}
this._native.connect('new-request', Lang.bind(this, this._newRequest));
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
try {
this._native.init(null);
} catch(e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
this._native.connect('new-request', this._newRequest.bind(this));
this._native.connect('cancel-request', this._cancelRequest.bind(this));
this._initialized = false;
this._native.init_async(GLib.PRIORITY_DEFAULT, null, (o, res) => {
try {
this._native.init_finish(res);
this._initialized = true;
} catch(e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
});
},
enable: function() {
enable() {
if (!this._native)
return;
this._native.auto_register = true;
if (!this._native.registered)
if (this._initialized && !this._native.registered)
this._native.register_async(null, null);
},
disable: function() {
disable() {
let requestId;
for (requestId in this._dialogs)
@ -640,11 +649,11 @@ var NetworkAgent = new Lang.Class({
return;
this._native.auto_register = false;
if (this._native.registered)
if (this._initialized && this._native.registered)
this._native.unregister_async(null, null);
},
_showNotification: function(requestId, connection, settingName, hints, flags) {
_showNotification(requestId, connection, settingName, hints, flags) {
let source = new MessageTray.Source(_("Network Manager"), 'network-transmit-receive');
source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
@ -655,7 +664,7 @@ var NetworkAgent = new Lang.Class({
switch (connectionType) {
case '802-11-wireless':
let wirelessSetting = connection.get_setting_wireless();
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid());
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
title = _("Authentication required by wireless network");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break;
@ -688,44 +697,44 @@ var NetworkAgent = new Lang.Class({
let notification = new MessageTray.Notification(source, title, body);
notification.connect('activated', Lang.bind(this, function() {
notification.connect('activated', () => {
notification.answered = true;
this._handleRequest(requestId, connection, settingName, hints, flags);
}));
});
this._notifications[requestId] = notification;
notification.connect('destroy', Lang.bind(this, function() {
notification.connect('destroy', () => {
if (!notification.answered)
this._native.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
delete this._notifications[requestId];
}));
});
Main.messageTray.add(source);
source.notify(notification);
},
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
_newRequest(agent, requestId, connection, settingName, hints, flags) {
if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED))
this._showNotification(requestId, connection, settingName, hints, flags);
else
this._handleRequest(requestId, connection, settingName, hints, flags);
},
_handleRequest: function(requestId, connection, settingName, hints, flags) {
_handleRequest(requestId, connection, settingName, hints, flags) {
if (settingName == 'vpn') {
this._vpnRequest(requestId, connection, hints, flags);
return;
}
let dialog = new NetworkSecretDialog(this._native, requestId, connection, settingName, hints);
dialog.connect('destroy', Lang.bind(this, function() {
dialog.connect('destroy', () => {
delete this._dialogs[requestId];
}));
});
this._dialogs[requestId] = dialog;
dialog.open(global.get_current_time());
},
_cancelRequest: function(agent, requestId) {
_cancelRequest(agent, requestId) {
if (this._dialogs[requestId]) {
this._dialogs[requestId].close(global.get_current_time());
this._dialogs[requestId].destroy();
@ -736,7 +745,7 @@ var NetworkAgent = new Lang.Class({
}
},
_vpnRequest: function(requestId, connection, hints, flags) {
_vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn();
let serviceType = vpnSetting.service_type;
@ -752,70 +761,42 @@ var NetworkAgent = new Lang.Class({
}
let vpnRequest = new VPNRequestHandler(this._native, requestId, binary, serviceType, connection, hints, flags);
vpnRequest.connect('destroy', Lang.bind(this, function() {
vpnRequest.connect('destroy', () => {
delete this._vpnRequests[requestId];
}));
});
this._vpnRequests[requestId] = vpnRequest;
},
_buildVPNServiceCache: function() {
_buildVPNServiceCache() {
if (this._vpnCacheBuilt)
return;
this._vpnCacheBuilt = true;
this._vpnBinaries = { };
try {
let fileEnum = this._pluginDir.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NONE, null);
let info;
NM.VpnPluginInfo.list_load().forEach(plugin => {
let service = plugin.get_service();
let fileName = plugin.get_auth_dialog();
let supportsHints = plugin.supports_hints();
let externalUIMode = false;
while ((info = fileEnum.next_file(null))) {
let name = info.get_name();
if (name.substr(-5) != '.name')
continue;
try {
let keyfile = new GLib.KeyFile();
keyfile.load_from_file(this._pluginDir.get_child(name).get_path(), GLib.KeyFileFlags.NONE);
let service = keyfile.get_string('VPN Connection', 'service');
let binary = keyfile.get_string('GNOME', 'auth-dialog');
let externalUIMode = false;
let hints = false;
try {
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
} catch(e) { } // ignore errors if key does not exist
try {
hints = keyfile.get_boolean('GNOME', 'supports-hints');
} catch(e) { } // ignore errors if key does not exist
let path = binary;
if (!GLib.path_is_absolute(path)) {
path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
}
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE)) {
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints };
try {
let aliases = keyfile.get_string_list('VPN Connection', 'aliases');
for (let alias of aliases) {
this._vpnBinaries[alias] = { fileName: path, externalUIMode: externalUIMode, supportsHints: hints };
}
} catch(e) { } // ignore errors if key does not exist
} else {
throw new Error('VPN plugin at %s is not executable'.format(path));
}
} catch(e) {
log('Error \'%s\' while processing VPN keyfile \'%s\''.
format(e.message, this._pluginDir.get_child(name).get_path()));
continue;
}
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
if (prop) {
prop = prop.trim().toLowerCase();
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
}
} catch(e) {
logError(e, 'error while enumerating VPN auth helpers');
}
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
let binary = { fileName, externalUIMode, supportsHints };
this._vpnBinaries[service] = binary;
plugin.get_aliases().forEach(alias => {
this._vpnBinaries[alias] = binary;
});
} else {
log('VPN plugin at %s is not executable'.format(fileName));
}
});
}
});
var Component = NetworkAgent;

View File

@ -16,6 +16,7 @@ const PolkitAgent = imports.gi.PolkitAgent;
const Animation = imports.ui.animation;
const Components = imports.ui.components;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
@ -31,7 +32,7 @@ var AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
_init: function(actionId, body, cookie, userNames) {
_init(actionId, body, cookie, userNames) {
this.parent({ styleClass: 'prompt-dialog' });
this.actionId = actionId;
@ -39,6 +40,10 @@ var AuthenticationDialog = new Lang.Class({
this.userNames = userNames;
this._wasDismissed = false;
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
this._group.visible = !Main.sessionMode.isLocked;
});
let icon = new Gio.ThemedIcon({ name: 'dialog-password-symbolic' });
let title = _("Authentication Required");
@ -60,9 +65,9 @@ var AuthenticationDialog = new Lang.Class({
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name()
this._userLoadedId = this._user.connect('notify::is_loaded',
Lang.bind(this, this._onUserChanged));
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
Lang.bind(this, this._onUserChanged));
this._onUserChanged.bind(this));
// Special case 'root'
let userIsRoot = false;
@ -108,7 +113,7 @@ var AuthenticationDialog = new Lang.Class({
text: "",
can_focus: true});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordBox.add(this._passwordEntry,
{ expand: true });
@ -146,10 +151,10 @@ var AuthenticationDialog = new Lang.Class({
this._nullMessageLabel.show();
this._cancelButton = this.addButton({ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
action: this.cancel.bind(this),
key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"),
action: Lang.bind(this, this._onAuthenticateButtonPressed),
action: this._onAuthenticateButtonPressed.bind(this),
default: true });
this._doneEmitted = false;
@ -158,7 +163,7 @@ var AuthenticationDialog = new Lang.Class({
this._cookie = cookie;
},
_setWorking: function(working) {
_setWorking(working) {
Tweener.removeTweens(this._workSpinner.actor);
if (working) {
this._workSpinner.play();
@ -174,7 +179,7 @@ var AuthenticationDialog = new Lang.Class({
time: WORK_SPINNER_ANIMATION_TIME,
transition: 'linear',
onCompleteScope: this,
onComplete: function() {
onComplete() {
if (this._workSpinner)
this._workSpinner.stop();
}
@ -182,18 +187,26 @@ var AuthenticationDialog = new Lang.Class({
}
},
performAuthentication: function() {
performAuthentication() {
this.destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie });
this._session.connect('completed', Lang.bind(this, this._onSessionCompleted));
this._session.connect('request', Lang.bind(this, this._onSessionRequest));
this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
this._session.connect('completed', this._onSessionCompleted.bind(this));
this._session.connect('request', this._onSessionRequest.bind(this));
this._session.connect('show-error', this._onSessionShowError.bind(this));
this._session.connect('show-info', this._onSessionShowInfo.bind(this));
this._session.initiate();
},
_ensureOpen: function() {
close(timestamp) {
this.parent(timestamp);
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
},
_ensureOpen() {
// NOTE: ModalDialog.open() is safe to call if the dialog is
// already open - it just returns true without side-effects
if (!this.open(global.get_current_time())) {
@ -215,14 +228,14 @@ var AuthenticationDialog = new Lang.Class({
}
},
_emitDone: function(dismissed) {
_emitDone(dismissed) {
if (!this._doneEmitted) {
this._doneEmitted = true;
this.emit('done', dismissed);
}
},
_updateSensitivity: function(sensitive) {
_updateSensitivity(sensitive) {
this._passwordEntry.reactive = sensitive;
this._passwordEntry.clutter_text.editable = sensitive;
@ -231,7 +244,7 @@ var AuthenticationDialog = new Lang.Class({
this._setWorking(!sensitive);
},
_onEntryActivate: function() {
_onEntryActivate() {
let response = this._passwordEntry.get_text();
this._updateSensitivity(false);
this._session.response(response);
@ -242,11 +255,11 @@ var AuthenticationDialog = new Lang.Class({
this._nullMessageLabel.show();
},
_onAuthenticateButtonPressed: function() {
_onAuthenticateButtonPressed() {
this._onEntryActivate();
},
_onSessionCompleted: function(session, gainedAuthorization) {
_onSessionCompleted(session, gainedAuthorization) {
if (this._completed || this._doneEmitted)
return;
@ -278,7 +291,7 @@ var AuthenticationDialog = new Lang.Class({
}
},
_onSessionRequest: function(session, request, echo_on) {
_onSessionRequest(session, request, echo_on) {
// Cheap localization trick
if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:"));
@ -297,7 +310,7 @@ var AuthenticationDialog = new Lang.Class({
this._ensureOpen();
},
_onSessionShowError: function(session, text) {
_onSessionShowError(session, text) {
this._passwordEntry.set_text('');
this._errorMessageLabel.set_text(text);
this._errorMessageLabel.show();
@ -306,7 +319,7 @@ var AuthenticationDialog = new Lang.Class({
this._ensureOpen();
},
_onSessionShowInfo: function(session, text) {
_onSessionShowInfo(session, text) {
this._passwordEntry.set_text('');
this._infoMessageLabel.set_text(text);
this._infoMessageLabel.show();
@ -315,7 +328,7 @@ var AuthenticationDialog = new Lang.Class({
this._ensureOpen();
},
destroySession: function() {
destroySession() {
if (this._session) {
if (!this._completed)
this._session.cancel();
@ -324,14 +337,14 @@ var AuthenticationDialog = new Lang.Class({
}
},
_onUserChanged: function() {
_onUserChanged() {
if (this._user.is_loaded && this._userAvatar) {
this._userAvatar.update();
this._userAvatar.actor.show();
}
},
cancel: function() {
cancel() {
this._wasDismissed = true;
this.close(global.get_current_time());
this._emitDone(true);
@ -342,15 +355,16 @@ Signals.addSignalMethods(AuthenticationDialog.prototype);
var AuthenticationAgent = new Lang.Class({
Name: 'AuthenticationAgent',
_init: function() {
_init() {
this._currentDialog = null;
this._handle = null;
this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate));
this._native.connect('cancel', Lang.bind(this, this._onCancel));
this._native.connect('initiate', this._onInitiate.bind(this));
this._native.connect('cancel', this._onCancel.bind(this));
this._sessionUpdatedId = 0;
},
enable: function() {
enable() {
try {
this._native.register();
} catch(e) {
@ -358,7 +372,7 @@ var AuthenticationAgent = new Lang.Class({
}
},
disable: function() {
disable() {
try {
this._native.unregister();
} catch(e) {
@ -366,7 +380,18 @@ var AuthenticationAgent = new Lang.Class({
}
},
_onInitiate: function(nativeAgent, actionId, message, iconName, cookie, userNames) {
_onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) {
// Don't pop up a dialog while locked
if (Main.sessionMode.isLocked) {
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
this._onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames);
});
return;
}
this._currentDialog = new AuthenticationDialog(actionId, message, cookie, userNames);
// We actually don't want to open the dialog until we know for
@ -379,23 +404,27 @@ var AuthenticationAgent = new Lang.Class({
// See https://bugzilla.gnome.org/show_bug.cgi?id=643062 for more
// discussion.
this._currentDialog.connect('done', Lang.bind(this, this._onDialogDone));
this._currentDialog.connect('done', this._onDialogDone.bind(this));
this._currentDialog.performAuthentication();
},
_onCancel: function(nativeAgent) {
_onCancel(nativeAgent) {
this._completeRequest(false);
},
_onDialogDone: function(dialog, dismissed) {
_onDialogDone(dialog, dismissed) {
this._completeRequest(dismissed);
},
_completeRequest: function(dismissed) {
_completeRequest(dismissed) {
this._currentDialog.close();
this._currentDialog.destroySession();
this._currentDialog = null;
if (this._sessionUpdatedId)
Main.sessionMode.disconnect(this._sessionUpdatedId);
this._sessionUpdatedId = 0;
this._native.complete(dismissed);
},
});

View File

@ -47,7 +47,7 @@ var NotificationDirection = {
RECEIVED: 'chat-received'
};
var N_ = function(s) { return s; };
var N_ = s => s;
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text();
@ -82,7 +82,7 @@ function makeMessageFromTplEvent(event) {
var TelepathyComponent = new Lang.Class({
Name: 'TelepathyComponent',
_init: function() {
_init() {
this._client = null;
if (!HAVE_TP)
@ -91,7 +91,7 @@ var TelepathyComponent = new Lang.Class({
this._client = new TelepathyClient();
},
enable: function() {
enable() {
if (!this._client)
return;
@ -105,7 +105,7 @@ var TelepathyComponent = new Lang.Class({
this._client.account_manager.prepare_async(null, null);
},
disable: function() {
disable() {
if (!this._client)
return;
@ -117,7 +117,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
Name: 'TelepathyClient',
Extends: Tp.BaseClient,
_init: function() {
_init() {
// channel path -> ChatSource
this._chatSources = {};
this._chatState = Tp.ChannelChatState.ACTIVE;
@ -157,10 +157,10 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
// Allow other clients (such as Empathy) to pre-empt our channels if
// needed
this.set_delegated_channels_callback(
Lang.bind(this, this._delegatedChannelsCb));
this._delegatedChannelsCb.bind(this));
},
vfunc_observe_channels: function(account, conn, channels,
vfunc_observe_channels(account, conn, channels,
dispatchOp, requests, context) {
let len = channels.length;
for (let i = 0; i < len; i++) {
@ -181,26 +181,25 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
context.accept();
},
_createChatSource: function(account, conn, channel, contact) {
_createChatSource(account, conn, channel, contact) {
if (this._chatSources[channel.get_object_path()])
return;
let source = new ChatSource(account, conn, channel, contact, this);
this._chatSources[channel.get_object_path()] = source;
source.connect('destroy', Lang.bind(this,
function() {
delete this._chatSources[channel.get_object_path()];
}));
source.connect('destroy', () => {
delete this._chatSources[channel.get_object_path()];
});
},
vfunc_handle_channels: function(account, conn, channels, requests,
vfunc_handle_channels(account, conn, channels, requests,
user_action_time, context) {
this._handlingChannels(account, conn, channels, true);
context.accept();
},
_handlingChannels: function(account, conn, channels, notify) {
_handlingChannels(account, conn, channels, notify) {
let len = channels.length;
for (let i = 0; i < len; i++) {
let channel = channels[i];
@ -234,7 +233,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
}
},
vfunc_add_dispatch_operation: function(account, conn, channels,
vfunc_add_dispatch_operation(account, conn, channels,
dispatchOp, context) {
let channel = channels[0];
let chanType = channel.get_channel_type();
@ -252,7 +251,7 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
message: 'Unsupported channel type' }));
},
_approveTextChannel: function(account, conn, channel, dispatchOp, context) {
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
@ -262,19 +261,19 @@ var TelepathyClient = HAVE_TP ? new Lang.Class({
}
// Approve private text channels right away as we are going to handle it
dispatchOp.claim_with_async(this, Lang.bind(this, function(dispatchOp, result) {
dispatchOp.claim_with_async(this, (dispatchOp, result) => {
try {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: ' + err);
}
}));
});
context.accept();
},
_delegatedChannelsCb: function(client, channels) {
_delegatedChannelsCb(client, channels) {
// Nothing to do as we don't make a distinction between observed and
// handled channels.
},
@ -284,7 +283,7 @@ var ChatSource = new Lang.Class({
Name: 'ChatSource',
Extends: MessageTray.Source,
_init: function(account, conn, channel, contact, client) {
_init(account, conn, channel, contact, client) {
this._account = account;
this._contact = contact;
this._client = client;
@ -296,19 +295,19 @@ var ChatSource = new Lang.Class({
this._conn = conn;
this._channel = channel;
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
this._closedId = this._channel.connect('invalidated', this._channelClosed.bind(this));
this._notifyTimeoutId = 0;
this._presence = contact.get_presence_type();
this._sentId = this._channel.connect('message-sent', Lang.bind(this, this._messageSent));
this._receivedId = this._channel.connect('message-received', Lang.bind(this, this._messageReceived));
this._pendingId = this._channel.connect('pending-message-removed', Lang.bind(this, this._pendingRemoved));
this._sentId = this._channel.connect('message-sent', this._messageSent.bind(this));
this._receivedId = this._channel.connect('message-received', this._messageReceived.bind(this));
this._pendingId = this._channel.connect('pending-message-removed', this._pendingRemoved.bind(this));
this._notifyAliasId = this._contact.connect('notify::alias', Lang.bind(this, this._updateAlias));
this._notifyAvatarId = this._contact.connect('notify::avatar-file', Lang.bind(this, this._updateAvatarIcon));
this._presenceChangedId = this._contact.connect('presence-changed', Lang.bind(this, this._presenceChanged));
this._notifyAliasId = this._contact.connect('notify::alias', this._updateAlias.bind(this));
this._notifyAvatarId = this._contact.connect('notify::avatar-file', this._updateAvatarIcon.bind(this));
this._presenceChangedId = this._contact.connect('presence-changed', this._presenceChanged.bind(this));
// Add ourselves as a source.
Main.messageTray.add(this);
@ -316,45 +315,42 @@ var ChatSource = new Lang.Class({
this._getLogMessages();
},
_ensureNotification: function() {
_ensureNotification() {
if (this._notification)
return;
this._notification = new ChatNotification(this);
this._notification.connect('activated', Lang.bind(this, this.open));
this._notification.connect('updated', Lang.bind(this,
function() {
if (this._banner && this._banner.expanded)
this._ackMessages();
}));
this._notification.connect('destroy', Lang.bind(this,
function() {
this._notification = null;
}));
this._notification.connect('activated', this.open.bind(this));
this._notification.connect('updated', () => {
if (this._banner && this._banner.expanded)
this._ackMessages();
});
this._notification.connect('destroy', () => {
this._notification = null;
});
this.pushNotification(this._notification);
},
_createPolicy: function() {
_createPolicy() {
if (this._account.protocol_name == 'irc')
return new MessageTray.NotificationApplicationPolicy('org.gnome.Polari');
return new MessageTray.NotificationApplicationPolicy('empathy');
},
createBanner: function() {
createBanner() {
this._banner = new ChatNotificationBanner(this._notification);
// We ack messages when the user expands the new notification
let id = this._banner.connect('expanded', Lang.bind(this, this._ackMessages));
this._banner.actor.connect('destroy', Lang.bind(this,
function() {
this._banner.disconnect(id);
this._banner = null;
}));
let id = this._banner.connect('expanded', this._ackMessages.bind(this));
this._banner.actor.connect('destroy', () => {
this._banner.disconnect(id);
this._banner = null;
});
return this._banner;
},
_updateAlias: function() {
_updateAlias() {
let oldAlias = this.title;
let newAlias = this._contact.get_alias();
@ -366,7 +362,7 @@ var ChatSource = new Lang.Class({
this._notification.appendAliasChange(oldAlias, newAlias);
},
getIcon: function() {
getIcon() {
let file = this._contact.get_avatar_file();
if (file) {
return new Gio.FileIcon({ file: file });
@ -375,7 +371,7 @@ var ChatSource = new Lang.Class({
}
},
getSecondaryIcon: function() {
getSecondaryIcon() {
let iconName;
let presenceType = this._contact.get_presence_type();
@ -404,7 +400,7 @@ var ChatSource = new Lang.Class({
return new Gio.ThemedIcon({ name: iconName });
},
_updateAvatarIcon: function() {
_updateAvatarIcon() {
this.iconUpdated();
if (this._notifiction)
this._notification.update(this._notification.title,
@ -412,7 +408,7 @@ var ChatSource = new Lang.Class({
{ gicon: this.getIcon() });
},
open: function() {
open() {
Main.overview.hide();
Main.panel.closeCalendar();
@ -437,16 +433,16 @@ var ChatSource = new Lang.Class({
}
},
_getLogMessages: function() {
_getLogMessages() {
let logManager = Tpl.LogManager.dup_singleton();
let entity = Tpl.Entity.new_from_tp_contact(this._contact, Tpl.EntityType.CONTACT);
logManager.get_filtered_events_async(this._account, entity,
Tpl.EventTypeMask.TEXT, SCROLLBACK_HISTORY_LINES,
null, Lang.bind(this, this._displayPendingMessages));
null, this._displayPendingMessages.bind(this));
},
_displayPendingMessages: function(logManager, result) {
_displayPendingMessages(logManager, result) {
let [success, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(makeMessageFromTplEvent);
@ -499,12 +495,12 @@ var ChatSource = new Lang.Class({
this.notify();
},
destroy: function(reason) {
destroy(reason) {
if (this._client.is_handling_channel(this._channel)) {
this._ackMessages();
// The chat box has been destroyed so it can't
// handle the channel any more.
this._channel.close_async(function(channel, result) {
this._channel.close_async((channel, result) => {
channel.close_finish(result);
});
} else {
@ -534,7 +530,7 @@ var ChatSource = new Lang.Class({
this.parent(reason);
},
_channelClosed: function() {
_channelClosed() {
this.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
},
@ -551,7 +547,7 @@ var ChatSource = new Lang.Class({
return this.count > 0;
},
_messageReceived: function(channel, message) {
_messageReceived(channel, message) {
if (message.get_message_type() == Tp.ChannelTextMessageType.DELIVERY_REPORT)
return;
@ -567,11 +563,11 @@ var ChatSource = new Lang.Class({
if (this._notifyTimeoutId != 0)
Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = Mainloop.timeout_add(500,
Lang.bind(this, this._notifyTimeout));
this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
},
_notifyTimeout: function() {
_notifyTimeout() {
if (this._pendingMessages.length != 0)
this.notify();
@ -582,17 +578,17 @@ var ChatSource = new Lang.Class({
// This is called for both messages we send from
// our client and other clients as well.
_messageSent: function(channel, message, flags, token) {
_messageSent(channel, message, flags, token) {
this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
},
notify: function() {
notify() {
this.parent(this._notification);
},
respond: function(text) {
respond(text) {
let type;
if (text.slice(0, 4) == '/me ') {
type = Tp.ChannelTextMessageType.ACTION;
@ -602,12 +598,12 @@ var ChatSource = new Lang.Class({
}
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0, Lang.bind(this, function (src, result) {
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
}));
});
},
setChatState: function(state) {
setChatState(state) {
// We don't want to send COMPOSING every time a letter is typed into
// the entry. We send the state only when it changes. Telepathy/Empathy
// might change it behind our back if the user is using both
@ -620,14 +616,14 @@ var ChatSource = new Lang.Class({
}
},
_presenceChanged: function (contact, presence, status, message) {
_presenceChanged(contact, presence, status, message) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,
{ secondaryGIcon: this.getSecondaryIcon() });
},
_pendingRemoved: function(channel, message) {
_pendingRemoved(channel, message) {
let idx = this._pendingMessages.indexOf(message);
if (idx >= 0) {
@ -640,7 +636,7 @@ var ChatSource = new Lang.Class({
this._banner.hide();
},
_ackMessages: function() {
_ackMessages() {
// Don't clear our messages here, tp-glib will send a
// 'pending-message-removed' for each one.
this._channel.ack_all_pending_messages_async(null);
@ -651,7 +647,7 @@ var ChatNotification = new Lang.Class({
Name: 'ChatNotification',
Extends: MessageTray.Notification,
_init: function(source) {
_init(source) {
this.parent(source, source.title, null,
{ secondaryGIcon: source.getSecondaryIcon() });
this.setUrgency(MessageTray.Urgency.HIGH);
@ -661,7 +657,7 @@ var ChatNotification = new Lang.Class({
this._timestampTimeoutId = 0;
},
destroy: function(reason) {
destroy(reason) {
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
@ -681,7 +677,7 @@ var ChatNotification = new Lang.Class({
* will be added, regardless of the difference since the
* last timestamp
*/
appendMessage: function(message, noTimestamp) {
appendMessage(message, noTimestamp) {
let messageBody = GLib.markup_escape_text(message.text, -1);
let styles = [message.direction];
@ -706,7 +702,7 @@ var ChatNotification = new Lang.Class({
noTimestamp: noTimestamp });
},
_filterMessages: function() {
_filterMessages() {
if (this.messages.length < 1)
return;
@ -722,7 +718,7 @@ var ChatNotification = new Lang.Class({
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ?
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(function(item) { return item.realMessage });
let filteredHistory = this.messages.filter(item => item.realMessage);
if (filteredHistory.length > maxLength) {
let lastMessageToKeep = filteredHistory[maxLength];
let expired = this.messages.splice(this.messages.indexOf(lastMessageToKeep));
@ -741,7 +737,7 @@ var ChatNotification = new Lang.Class({
* timestamp: The timestamp of the message.
* noTimestamp: suppress timestamp signal?
*/
_append: function(props) {
_append(props) {
let currentTime = (Date.now() / 1000);
props = Params.parse(props, { body: null,
group: null,
@ -771,7 +767,7 @@ var ChatNotification = new Lang.Class({
// from the timestamp of the message.
this._timestampTimeoutId = Mainloop.timeout_add_seconds(
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
Lang.bind(this, this.appendTimestamp));
this.appendTimestamp.bind(this));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
}
}
@ -779,7 +775,7 @@ var ChatNotification = new Lang.Class({
this._filterMessages();
},
appendTimestamp: function() {
appendTimestamp() {
this._timestampTimeoutId = 0;
this.messages[0].showTimestamp = true;
@ -790,7 +786,7 @@ var ChatNotification = new Lang.Class({
return GLib.SOURCE_REMOVE;
},
appendAliasChange: function(oldAlias, newAlias) {
appendAliasChange(oldAlias, newAlias) {
oldAlias = GLib.markup_escape_text(oldAlias, -1);
newAlias = GLib.markup_escape_text(newAlias, -1);
@ -810,7 +806,7 @@ var ChatLineBox = new Lang.Class({
Name: 'ChatLineBox',
Extends: St.BoxLayout,
vfunc_get_preferred_height: function(forWidth) {
vfunc_get_preferred_height(forWidth) {
let [, natHeight] = this.parent(forWidth);
return [natHeight, natHeight];
}
@ -820,23 +816,23 @@ var ChatNotificationBanner = new Lang.Class({
Name: 'ChatNotificationBanner',
Extends: MessageTray.NotificationBanner,
_init: function(notification) {
_init(notification) {
this.parent(notification);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
x_expand: true,
can_focus: true });
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
this._responseEntry.clutter_text.connect('text-changed', Lang.bind(this, this._onEntryChanged));
this._responseEntry.clutter_text.connect('activate', this._onEntryActivated.bind(this));
this._responseEntry.clutter_text.connect('text-changed', this._onEntryChanged.bind(this));
this.setActionArea(this._responseEntry);
this._responseEntry.clutter_text.connect('key-focus-in', Lang.bind(this, function() {
this._responseEntry.clutter_text.connect('key-focus-in', () => {
this.focused = true;
}));
this._responseEntry.clutter_text.connect('key-focus-out', Lang.bind(this, function() {
});
this._responseEntry.clutter_text.connect('key-focus-out', () => {
this.focused = false;
this.emit('unfocused');
}));
});
this._scrollArea = new St.ScrollView({ style_class: 'chat-scrollview vfade',
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
@ -855,11 +851,11 @@ var ChatNotificationBanner = new Lang.Class({
// force a scroll to the bottom if things change while we were at the
// bottom
this._oldMaxScrollValue = this._scrollArea.vscroll.adjustment.value;
this._scrollArea.vscroll.adjustment.connect('changed', Lang.bind(this, function(adjustment) {
this._scrollArea.vscroll.adjustment.connect('changed', adjustment => {
if (adjustment.value == this._oldMaxScrollValue)
this.scrollTo(St.Side.BOTTOM);
this._oldMaxScrollValue = Math.max(adjustment.lower, adjustment.upper - adjustment.page_size);
}));
});
this._inputHistory = new History.HistoryManager({ entry: this._responseEntry.clutter_text });
@ -868,32 +864,32 @@ var ChatNotificationBanner = new Lang.Class({
this._messageActors = new Map();
this._messageAddedId = this.notification.connect('message-added',
Lang.bind(this, function(n, message) {
(n, message) => {
this._addMessage(message);
}));
});
this._messageRemovedId = this.notification.connect('message-removed',
Lang.bind(this, function(n, message) {
(n, message) => {
let actor = this._messageActors.get(message);
if (this._messageActors.delete(message))
actor.destroy();
}));
});
this._timestampChangedId = this.notification.connect('timestamp-changed',
Lang.bind(this, function(n, message) {
(n, message) => {
this._updateTimestamp(message);
}));
});
for (let i = this.notification.messages.length - 1; i >= 0; i--)
this._addMessage(this.notification.messages[i]);
},
_onDestroy: function() {
_onDestroy() {
this.parent();
this.notification.disconnect(this._messageAddedId);
this.notification.disconnect(this._messageRemovedId);
this.notification.disconnect(this._timestampChangedId);
},
scrollTo: function(side) {
scrollTo(side) {
let adjustment = this._scrollArea.vscroll.adjustment;
if (side == St.Side.TOP)
adjustment.value = adjustment.lower;
@ -901,11 +897,11 @@ var ChatNotificationBanner = new Lang.Class({
adjustment.value = adjustment.upper;
},
hide: function() {
hide() {
this.emit('done-displaying');
},
_addMessage: function(message) {
_addMessage(message) {
let highlighter = new MessageList.URLHighlighter(message.body, true, true);
let body = highlighter.actor;
@ -927,7 +923,7 @@ var ChatNotificationBanner = new Lang.Class({
this._updateTimestamp(message);
},
_updateTimestamp: function(message) {
_updateTimestamp(message) {
let actor = this._messageActors.get(message);
if (!actor)
return;
@ -948,7 +944,7 @@ var ChatNotificationBanner = new Lang.Class({
}
},
_onEntryActivated: function() {
_onEntryActivated() {
let text = this._responseEntry.get_text();
if (text == '')
return;
@ -961,7 +957,7 @@ var ChatNotificationBanner = new Lang.Class({
this.notification.source.respond(text);
},
_composingStopTimeout: function() {
_composingStopTimeout() {
this._composingTimeoutId = 0;
this.notification.source.setChatState(Tp.ChannelChatState.PAUSED);
@ -969,7 +965,7 @@ var ChatNotificationBanner = new Lang.Class({
return GLib.SOURCE_REMOVE;
},
_onEntryChanged: function() {
_onEntryChanged() {
let text = this._responseEntry.get_text();
// If we're typing, we want to send COMPOSING.
@ -988,7 +984,7 @@ var ChatNotificationBanner = new Lang.Class({
this._composingTimeoutId = Mainloop.timeout_add_seconds(
COMPOSING_STOP_TIMEOUT,
Lang.bind(this, this._composingStopTimeout));
this._composingStopTimeout.bind(this));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');
} else {
this.notification.source.setChatState(Tp.ChannelChatState.ACTIVE);

View File

@ -24,14 +24,14 @@ var SortGroup = {
var CtrlAltTabManager = new Lang.Class({
Name: 'CtrlAltTabManager',
_init: function() {
_init() {
this._items = [];
this.addGroup(global.window_group, _("Windows"),
'focus-windows-symbolic', { sortGroup: SortGroup.TOP,
focusCallback: Lang.bind(this, this._focusWindows) });
focusCallback: this._focusWindows.bind(this) });
},
addGroup: function(root, name, icon, params) {
addGroup(root, name, icon, params) {
let item = Params.parse(params, { sortGroup: SortGroup.MIDDLE,
proxy: root,
focusCallback: null });
@ -41,12 +41,12 @@ var CtrlAltTabManager = new Lang.Class({
item.iconName = icon;
this._items.push(item);
root.connect('destroy', Lang.bind(this, function() { this.removeGroup(root); }));
root.connect('destroy', () => { this.removeGroup(root); });
if (root instanceof St.Widget)
global.focus_manager.add_group(root);
},
removeGroup: function(root) {
removeGroup(root) {
if (root instanceof St.Widget)
global.focus_manager.remove_group(root);
for (let i = 0; i < this._items.length; i++) {
@ -57,7 +57,7 @@ var CtrlAltTabManager = new Lang.Class({
}
},
focusGroup: function(item, timestamp) {
focusGroup(item, timestamp) {
if (item.focusCallback)
item.focusCallback(timestamp);
else
@ -68,7 +68,7 @@ var CtrlAltTabManager = new Lang.Class({
// and everything else in between, sorted by X coordinate, so that
// they will have the same left-to-right ordering in the
// Ctrl-Alt-Tab dialog as they do onscreen.
_sortItems: function(a, b) {
_sortItems(a, b) {
if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup;
@ -79,15 +79,17 @@ var CtrlAltTabManager = new Lang.Class({
return ax - bx;
},
popup: function(backward, binding, mask) {
popup(backward, binding, mask) {
// Start with the set of focus groups that are currently mapped
let items = this._items.filter(function (item) { return item.proxy.mapped; });
let items = this._items.filter(item => item.proxy.mapped);
// And add the windows metacity would show in its Ctrl-Alt-Tab list
if (Main.sessionMode.hasWindows && !Main.overview.visible) {
let screen = global.screen;
let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.DOCKS, screen.get_active_workspace ());
let display = global.display;
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let windows = display.get_tab_list(Meta.TabList.DOCKS,
activeWorkspace);
let windowTracker = Shell.WindowTracker.get_default();
let textureCache = St.TextureCache.get_default();
for (let i = 0; i < windows.length; i++) {
@ -105,10 +107,9 @@ var CtrlAltTabManager = new Lang.Class({
items.push({ name: windows[i].title,
proxy: windows[i].get_compositor_private(),
focusCallback: Lang.bind(windows[i],
function(timestamp) {
Main.activateWindow(this, timestamp);
}),
focusCallback: function(timestamp) {
Main.activateWindow(this, timestamp);
}.bind(windows[i]),
iconActor: icon,
iconName: iconName,
sortGroup: SortGroup.MIDDLE });
@ -118,21 +119,21 @@ var CtrlAltTabManager = new Lang.Class({
if (!items.length)
return;
items.sort(Lang.bind(this, this._sortItems));
items.sort(this._sortItems.bind(this));
if (!this._popup) {
this._popup = new CtrlAltTabPopup(items);
this._popup.show(backward, binding, mask);
this._popup.actor.connect('destroy',
Lang.bind(this, function() {
() => {
this._popup = null;
}));
});
}
},
_focusWindows: function(timestamp) {
global.screen.focus_default_window(timestamp);
_focusWindows(timestamp) {
global.display.focus_default_window(timestamp);
}
});
@ -140,13 +141,13 @@ var CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function(items) {
_init(items) {
this.parent(items);
this._switcherList = new CtrlAltTabSwitcher(this._items);
},
_keyPressHandler: function(keysym, action) {
_keyPressHandler(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
@ -161,7 +162,7 @@ var CtrlAltTabPopup = new Lang.Class({
return Clutter.EVENT_STOP;
},
_finish : function(time) {
_finish(time) {
this.parent(time);
Main.ctrlAltTabManager.focusGroup(this._items[this._selectedIndex], time);
},
@ -171,14 +172,14 @@ var CtrlAltTabSwitcher = new Lang.Class({
Name: 'CtrlAltTabSwitcher',
Extends: SwitcherPopup.SwitcherList,
_init : function(items) {
_init(items) {
this.parent(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
},
_addIcon : function(item) {
_addIcon(item) {
let box = new St.BoxLayout({ style_class: 'alt-tab-app',
vertical: true });

View File

@ -37,7 +37,7 @@ var DashItemContainer = new Lang.Class({
Name: 'DashItemContainer',
Extends: St.Widget,
_init: function() {
_init() {
this.parent({ style_class: 'dash-item-container' });
this._labelText = "";
@ -56,7 +56,7 @@ var DashItemContainer = new Lang.Class({
});
},
vfunc_allocate: function(box, flags) {
vfunc_allocate(box, flags) {
this.set_allocation(box, flags);
if (this.child == null)
@ -80,7 +80,7 @@ var DashItemContainer = new Lang.Class({
this.child.allocate(childBox, flags);
},
vfunc_get_preferred_height: function(forWidth) {
vfunc_get_preferred_height(forWidth) {
let themeNode = this.get_theme_node();
if (this.child == null)
@ -92,7 +92,7 @@ var DashItemContainer = new Lang.Class({
natHeight * this.child.scale_y);
},
vfunc_get_preferred_width: function(forHeight) {
vfunc_get_preferred_width(forHeight) {
let themeNode = this.get_theme_node();
if (this.child == null)
@ -104,7 +104,7 @@ var DashItemContainer = new Lang.Class({
natWidth * this.child.scale_y);
},
showLabel: function() {
showLabel() {
if (!this._labelText)
return;
@ -138,23 +138,23 @@ var DashItemContainer = new Lang.Class({
});
},
setLabelText: function(text) {
setLabelText(text) {
this._labelText = text;
this.child.accessible_name = text;
},
hideLabel: function () {
hideLabel() {
Tweener.addTween(this.label,
{ opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
onComplete: () => {
this.label.hide();
})
}
});
},
setChild: function(actor) {
setChild(actor) {
if (this.child == actor)
return;
@ -168,7 +168,7 @@ var DashItemContainer = new Lang.Class({
this.child.set_opacity(this._childOpacity);
},
show: function(animate) {
show(animate) {
if (this.child == null)
return;
@ -181,7 +181,7 @@ var DashItemContainer = new Lang.Class({
});
},
animateOutAndDestroy: function() {
animateOutAndDestroy() {
this.label.hide();
if (this.child == null) {
@ -195,9 +195,9 @@ var DashItemContainer = new Lang.Class({
childOpacity: 0,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
onComplete: () => {
this.destroy();
})
}
});
},
@ -235,7 +235,7 @@ var ShowAppsIcon = new Lang.Class({
Name: 'ShowAppsIcon',
Extends: DashItemContainer,
_init: function() {
_init() {
this.parent();
this.toggleButton = new St.Button({ style_class: 'show-apps',
@ -246,7 +246,7 @@ var ShowAppsIcon = new Lang.Class({
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
{ setSizeManually: true,
showLabel: false,
createIcon: Lang.bind(this, this._createIcon) });
createIcon: this._createIcon.bind(this) });
this.toggleButton.add_actor(this.icon.actor);
this.toggleButton._delegate = this;
@ -254,7 +254,7 @@ var ShowAppsIcon = new Lang.Class({
this.setDragApp(null);
},
_createIcon: function(size) {
_createIcon(size) {
this._iconActor = new St.Icon({ icon_name: 'view-app-grid-symbolic',
icon_size: size,
style_class: 'show-apps-icon',
@ -262,7 +262,7 @@ var ShowAppsIcon = new Lang.Class({
return this._iconActor;
},
_canRemoveApp: function(app) {
_canRemoveApp(app) {
if (app == null)
return false;
@ -274,7 +274,7 @@ var ShowAppsIcon = new Lang.Class({
return isFavorite;
},
setDragApp: function(app) {
setDragApp(app) {
let canRemove = this._canRemoveApp(app);
this.toggleButton.set_hover(canRemove);
@ -287,25 +287,24 @@ var ShowAppsIcon = new Lang.Class({
this.setLabelText(_("Show Applications"));
},
handleDragOver: function(source, actor, x, y, time) {
handleDragOver(source, actor, x, y, time) {
if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP;
},
acceptDrop: function(source, actor, x, y, time) {
acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source);
if (!this._canRemoveApp(app))
return false;
let id = app.get_id();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function () {
AppFavorites.getAppFavorites().removeFavorite(id);
return false;
}));
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
AppFavorites.getAppFavorites().removeFavorite(id);
return false;
});
return true;
}
@ -315,7 +314,7 @@ var DragPlaceholderItem = new Lang.Class({
Name: 'DragPlaceholderItem',
Extends: DashItemContainer,
_init: function() {
_init() {
this.parent();
this.setChild(new St.Bin({ style_class: 'placeholder' }));
}
@ -325,7 +324,7 @@ var EmptyDropTargetItem = new Lang.Class({
Name: 'EmptyDropTargetItem',
Extends: DashItemContainer,
_init: function() {
_init() {
this.parent();
this.setChild(new St.Bin({ style_class: 'empty-dash-drop-target' }));
}
@ -335,14 +334,14 @@ var DashActor = new Lang.Class({
Name: 'DashActor',
Extends: St.Widget,
_init: function() {
_init() {
let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
this.parent({ name: 'dash',
layout_manager: layout,
clip_to_allocation: true });
},
vfunc_allocate: function(box, flags) {
vfunc_allocate(box, flags) {
let contentBox = this.get_theme_node().get_content_box(box);
let availWidth = contentBox.x2 - contentBox.x1;
@ -363,7 +362,7 @@ var DashActor = new Lang.Class({
showAppsButton.allocate(childBox, flags);
},
vfunc_get_preferred_height: function(forWidth) {
vfunc_get_preferred_height(forWidth) {
// We want to request the natural height of all our children
// as our natural height, so we chain up to StWidget (which
// then calls BoxLayout), but we only request the showApps
@ -386,7 +385,7 @@ const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
var Dash = new Lang.Class({
Name: 'Dash',
_init : function() {
_init() {
this._maxHeight = -1;
this.iconSize = 64;
this._shownInitially = false;
@ -403,6 +402,7 @@ var Dash = new Lang.Class({
clip_to_allocation: true });
this._box._delegate = this;
this._container.add_actor(this._box);
this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this._showAppsIcon = new ShowAppsIcon();
this._showAppsIcon.childScale = 1;
@ -415,40 +415,39 @@ var Dash = new Lang.Class({
this._container.add_actor(this._showAppsIcon);
this.actor = new St.Bin({ child: this._container });
this.actor.connect('notify::height', Lang.bind(this,
function() {
if (this._maxHeight != this.actor.height)
this._queueRedisplay();
this._maxHeight = this.actor.height;
}));
this.actor.connect('notify::height', () => {
if (this._maxHeight != this.actor.height)
this._queueRedisplay();
this._maxHeight = this.actor.height;
});
this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay));
this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
this._appSystem.connect('installed-changed', () => {
AppFavorites.getAppFavorites().reload();
this._queueRedisplay();
}));
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
});
AppFavorites.getAppFavorites().connect('changed', this._queueRedisplay.bind(this));
this._appSystem.connect('app-state-changed', this._queueRedisplay.bind(this));
Main.overview.connect('item-drag-begin',
Lang.bind(this, this._onDragBegin));
this._onDragBegin.bind(this));
Main.overview.connect('item-drag-end',
Lang.bind(this, this._onDragEnd));
this._onDragEnd.bind(this));
Main.overview.connect('item-drag-cancelled',
Lang.bind(this, this._onDragCancelled));
this._onDragCancelled.bind(this));
// Translators: this is the name of the dock/favorites area on
// the left of the overview
Main.ctrlAltTabManager.addGroup(this.actor, _("Dash"), 'user-bookmarks-symbolic');
},
_onDragBegin: function() {
_onDragBegin() {
this._dragCancelled = false;
this._dragMonitor = {
dragMotion: Lang.bind(this, this._onDragMotion)
dragMotion: this._onDragMotion.bind(this)
};
DND.addDragMonitor(this._dragMonitor);
@ -459,26 +458,26 @@ var Dash = new Lang.Class({
}
},
_onDragCancelled: function() {
_onDragCancelled() {
this._dragCancelled = true;
this._endDrag();
},
_onDragEnd: function() {
_onDragEnd() {
if (this._dragCancelled)
return;
this._endDrag();
},
_endDrag: function() {
_endDrag() {
this._clearDragPlaceholder();
this._clearEmptyDropTarget();
this._showAppsIcon.setDragApp(null);
DND.removeDragMonitor(this._dragMonitor);
},
_onDragMotion: function(dragEvent) {
_onDragMotion(dragEvent) {
let app = getAppFromSource(dragEvent.source);
if (app == null)
return DND.DragMotionResult.CONTINUE;
@ -497,56 +496,56 @@ var Dash = new Lang.Class({
return DND.DragMotionResult.CONTINUE;
},
_appIdListToHash: function(apps) {
_appIdListToHash(apps) {
let ids = {};
for (let i = 0; i < apps.length; i++)
ids[apps[i].get_id()] = apps[i];
return ids;
},
_queueRedisplay: function () {
_queueRedisplay() {
Main.queueDeferredWork(this._workId);
},
_hookUpLabel: function(item, appIcon) {
item.child.connect('notify::hover', Lang.bind(this, function() {
_hookUpLabel(item, appIcon) {
item.child.connect('notify::hover', () => {
this._syncLabel(item, appIcon);
}));
});
let id = Main.overview.connect('hiding', Lang.bind(this, function() {
let id = Main.overview.connect('hiding', () => {
this._labelShowing = false;
item.hideLabel();
}));
item.child.connect('destroy', function() {
});
item.child.connect('destroy', () => {
Main.overview.disconnect(id);
});
if (appIcon) {
appIcon.connect('sync-tooltip', Lang.bind(this, function() {
appIcon.connect('sync-tooltip', () => {
this._syncLabel(item, appIcon);
}));
});
}
},
_createAppItem: function(app) {
_createAppItem(app) {
let appIcon = new AppDisplay.AppIcon(app,
{ setSizeManually: true,
showLabel: false });
if (appIcon._draggable) {
appIcon._draggable.connect('drag-begin',
Lang.bind(this, function() {
() => {
appIcon.actor.opacity = 50;
}));
});
appIcon._draggable.connect('drag-end',
Lang.bind(this, function() {
() => {
appIcon.actor.opacity = 255;
}));
});
}
appIcon.connect('menu-state-changed',
Lang.bind(this, function(appIcon, opened) {
(appIcon, opened) => {
this._itemMenuStateChanged(item, opened);
}));
});
let item = new DashItemContainer();
item.setChild(appIcon.actor);
@ -562,7 +561,7 @@ var Dash = new Lang.Class({
return item;
},
_itemMenuStateChanged: function(item, opened) {
_itemMenuStateChanged(item, opened) {
// When the menu closes, it calls sync_hover, which means
// that the notify::hover handler does everything we need to.
if (opened) {
@ -575,19 +574,19 @@ var Dash = new Lang.Class({
}
},
_syncLabel: function (item, appIcon) {
_syncLabel(item, appIcon) {
let shouldShow = appIcon ? appIcon.shouldShowTooltip() : item.child.get_hover();
if (shouldShow) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
Lang.bind(this, function() {
() => {
this._labelShowing = true;
item.showLabel();
this._showLabelTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId);
@ -601,22 +600,22 @@ var Dash = new Lang.Class({
item.hideLabel();
if (this._labelShowing) {
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() {
() => {
this._labelShowing = false;
this._resetHoverTimeoutId = 0;
return GLib.SOURCE_REMOVE;
}));
});
GLib.Source.set_name_by_id(this._resetHoverTimeoutId, '[gnome-shell] this._labelShowing');
}
}
},
_adjustIconSize: function() {
_adjustIconSize() {
// For the icon size, we only consider children which are "proper"
// icons (i.e. ignoring drag placeholders) and which are not
// animating out (which means they will be destroyed at the end of
// the animation)
let iconChildren = this._box.get_children().filter(function(actor) {
let iconChildren = this._box.get_children().filter(actor => {
return actor.child &&
actor.child._delegate &&
actor.child._delegate.icon &&
@ -655,9 +654,7 @@ var Dash = new Lang.Class({
let availSize = availHeight / iconChildren.length;
let iconSizes = baseIconSizes.map(function(s) {
return s * scaleFactor;
});
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
let newIconSize = baseIconSizes[0];
for (let i = 0; i < iconSizes.length; i++) {
@ -703,20 +700,18 @@ var Dash = new Lang.Class({
}
},
_redisplay: function () {
_redisplay() {
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
let running = this._appSystem.get_running();
let children = this._box.get_children().filter(function(actor) {
let children = this._box.get_children().filter(actor => {
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
});
// Apps currently in the dash
let oldApps = children.map(function(actor) {
return actor.child._delegate.app;
});
let oldApps = children.map(actor => actor.child._delegate.app);
// Apps supposed to be in the dash
let newApps = [];
@ -782,7 +777,7 @@ var Dash = new Lang.Class({
let nextApp = newApps.length > newIndex + 1 ? newApps[newIndex + 1]
: null;
let insertHere = nextApp && nextApp == oldApp;
let alreadyRemoved = removedActors.reduce(function(result, actor) {
let alreadyRemoved = removedActors.reduce((result, actor) => {
let removedApp = actor.child._delegate.app;
return result || removedApp == newApp;
}, false);
@ -834,27 +829,26 @@ var Dash = new Lang.Class({
this._box.queue_relayout();
},
_clearDragPlaceholder: function() {
_clearDragPlaceholder() {
if (this._dragPlaceholder) {
this._animatingPlaceholdersCount++;
this._dragPlaceholder.animateOutAndDestroy();
this._dragPlaceholder.connect('destroy',
Lang.bind(this, function() {
this._animatingPlaceholdersCount--;
}));
this._dragPlaceholder.connect('destroy', () => {
this._animatingPlaceholdersCount--;
});
this._dragPlaceholder = null;
}
this._dragPlaceholderPos = -1;
},
_clearEmptyDropTarget: function() {
_clearEmptyDropTarget() {
if (this._emptyDropTarget) {
this._emptyDropTarget.animateOutAndDestroy();
this._emptyDropTarget = null;
}
},
handleDragOver : function(source, actor, x, y, time) {
handleDragOver(source, actor, x, y, time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps
@ -932,7 +926,7 @@ var Dash = new Lang.Class({
},
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
acceptDrop(source, actor, x, y, time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps
@ -968,15 +962,14 @@ var Dash = new Lang.Class({
if (!this._dragPlaceholder)
return true;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function () {
let appFavorites = AppFavorites.getAppFavorites();
if (srcIsFavorite)
appFavorites.moveFavoriteToPos(id, favPos);
else
appFavorites.addFavoriteAtPos(id, favPos);
return false;
}));
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
let appFavorites = AppFavorites.getAppFavorites();
if (srcIsFavorite)
appFavorites.moveFavoriteToPos(id, favPos);
else
appFavorites.addFavoriteAtPos(id, favPos);
return false;
});
return true;
}

View File

@ -34,7 +34,7 @@ function _isToday(date) {
var TodayButton = new Lang.Class({
Name: 'TodayButton',
_init: function(calendar) {
_init(calendar) {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
@ -43,10 +43,9 @@ var TodayButton = new Lang.Class({
can_focus: true,
reactive: false
});
this.actor.connect('clicked', Lang.bind(this,
function() {
this._calendar.setDate(new Date(), false);
}));
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
});
let hbox = new St.BoxLayout({ vertical: true });
this.actor.add_actor(hbox);
@ -59,15 +58,14 @@ var TodayButton = new Lang.Class({
hbox.add_actor(this._dateLabel);
this._calendar = calendar;
this._calendar.connect('selected-date-changed', Lang.bind(this,
function(calendar, date) {
// Make the button reactive only if the selected date is not the
// current date.
this.actor.reactive = !_isToday(date)
}));
this._calendar.connect('selected-date-changed', (calendar, date) => {
// Make the button reactive only if the selected date is not the
// current date.
this.actor.reactive = !_isToday(date)
});
},
setDate: function(date) {
setDate(date) {
this._dayLabel.set_text(date.toLocaleFormat('%A'));
/* Translators: This is the date format to use when the calendar popup is
@ -88,7 +86,7 @@ var TodayButton = new Lang.Class({
var WorldClocksSection = new Lang.Class({
Name: 'WorldClocksSection',
_init: function() {
_init() {
this._clock = new GnomeDesktop.WallClock();
this._clockNotifyId = 0;
@ -97,13 +95,12 @@ var WorldClocksSection = new Lang.Class({
this.actor = new St.Button({ style_class: 'world-clocks-button',
x_fill: true,
can_focus: true });
this.actor.connect('clicked', Lang.bind(this,
function() {
this._clockAppMon.activateApp();
this.actor.connect('clicked', () => {
this._clockAppMon.activateApp();
Main.overview.hide();
Main.panel.closeCalendar();
}));
Main.overview.hide();
Main.panel.closeCalendar();
});
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this._grid = new St.Widget({ style_class: 'world-clocks-grid',
@ -115,17 +112,17 @@ var WorldClocksSection = new Lang.Class({
this._clockAppMon = new Util.AppSettingsMonitor('org.gnome.clocks.desktop',
'org.gnome.clocks');
this._clockAppMon.connect('available-changed',
Lang.bind(this, this._sync));
this._sync.bind(this));
this._clockAppMon.watchSetting('world-clocks',
Lang.bind(this, this._clocksChanged));
this._clocksChanged.bind(this));
this._sync();
},
_sync: function() {
_sync() {
this.actor.visible = this._clockAppMon.available;
},
_clocksChanged: function(settings) {
_clocksChanged(settings) {
this._grid.destroy_all_children();
this._locations = [];
@ -139,7 +136,7 @@ var WorldClocksSection = new Lang.Class({
this._locations.push({ location: l });
}
this._locations.sort(function(a, b) {
this._locations.sort((a, b) => {
return a.location.get_timezone().get_offset() -
b.location.get_timezone().get_offset();
});
@ -156,8 +153,10 @@ var WorldClocksSection = new Lang.Class({
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
: l.get_city_name();
let label = new St.Label({ style_class: 'world-clocks-city',
text: l.get_city_name(),
text: name,
x_align: Clutter.ActorAlign.START,
x_expand: true });
@ -179,7 +178,7 @@ var WorldClocksSection = new Lang.Class({
if (this._grid.get_n_children() > 1) {
if (!this._clockNotifyId)
this._clockNotifyId =
this._clock.connect('notify::clock', Lang.bind(this, this._updateLabels));
this._clock.connect('notify::clock', this._updateLabels.bind(this));
this._updateLabels();
} else {
if (this._clockNotifyId)
@ -188,7 +187,7 @@ var WorldClocksSection = new Lang.Class({
}
},
_updateLabels: function() {
_updateLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
@ -201,7 +200,7 @@ var WorldClocksSection = new Lang.Class({
var WeatherSection = new Lang.Class({
Name: 'WeatherSection',
_init: function() {
_init() {
this._weatherClient = new Weather.WeatherClient();
this.actor = new St.Button({ style_class: 'weather-button',
@ -233,11 +232,11 @@ var WeatherSection = new Lang.Class({
this._conditionsLabel.clutter_text.line_wrap = true;
box.add_child(this._conditionsLabel);
this._weatherClient.connect('changed', Lang.bind(this, this._sync));
this._weatherClient.connect('changed', this._sync.bind(this));
this._sync();
},
_getSummary: function(info, capitalize=false) {
_getSummary(info, capitalize=false) {
let options = capitalize ? GWeather.FormatOptions.SENTENCE_CAPITALIZATION
: GWeather.FormatOptions.NO_CAPITALIZATION;
@ -251,7 +250,7 @@ var WeatherSection = new Lang.Class({
return GWeather.Sky.to_string_full(sky, options);
},
_sameSummary: function(info1, info2) {
_sameSummary(info1, info2) {
let [ok1, phenom1, qualifier1] = info1.get_value_conditions();
let [ok2, phenom2, qualifier2] = info2.get_value_conditions();
if (ok1 || ok2)
@ -262,7 +261,7 @@ var WeatherSection = new Lang.Class({
return sky1 == sky2;
},
_getSummaryText: function() {
_getSummaryText() {
let info = this._weatherClient.info;
let forecasts = info.get_forecast_list();
if (forecasts.length == 0) // No forecasts, just current conditions
@ -310,7 +309,7 @@ var WeatherSection = new Lang.Class({
return String.prototype.format.apply(fmt, summaries);
},
_getLabelText: function() {
_getLabelText() {
if (!this._weatherClient.hasLocation)
return _("Select a location…");
@ -329,7 +328,7 @@ var WeatherSection = new Lang.Class({
return _("Weather information is currently unavailable");
},
_sync: function() {
_sync() {
this.actor.visible = this._weatherClient.available;
if (!this.actor.visible)
@ -342,7 +341,7 @@ var WeatherSection = new Lang.Class({
var MessagesIndicator = new Lang.Class({
Name: 'MessagesIndicator',
_init: function() {
_init() {
this.actor = new St.Icon({ icon_name: 'message-indicator-symbolic',
icon_size: 16,
visible: false, y_expand: true,
@ -350,31 +349,28 @@ var MessagesIndicator = new Lang.Class({
this._sources = [];
Main.messageTray.connect('source-added', Lang.bind(this, this._onSourceAdded));
Main.messageTray.connect('source-removed', Lang.bind(this, this._onSourceRemoved));
Main.messageTray.connect('queue-changed', Lang.bind(this, this._updateCount));
Main.messageTray.connect('source-added', this._onSourceAdded.bind(this));
Main.messageTray.connect('source-removed', this._onSourceRemoved.bind(this));
Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
let sources = Main.messageTray.getSources();
sources.forEach(Lang.bind(this, function(source) { this._onSourceAdded(null, source); }));
sources.forEach(source => { this._onSourceAdded(null, source); });
},
_onSourceAdded: function(tray, source) {
source.connect('count-updated', Lang.bind(this, this._updateCount));
_onSourceAdded(tray, source) {
source.connect('count-updated', this._updateCount.bind(this));
this._sources.push(source);
this._updateCount();
},
_onSourceRemoved: function(tray, source) {
_onSourceRemoved(tray, source) {
this._sources.splice(this._sources.indexOf(source), 1);
this._updateCount();
},
_updateCount: function() {
_updateCount() {
let count = 0;
this._sources.forEach(Lang.bind(this,
function(source) {
count += source.unseenCount;
}));
this._sources.forEach(source => { count += source.unseenCount; });
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);
@ -385,19 +381,19 @@ var IndicatorPad = new Lang.Class({
Name: 'IndicatorPad',
Extends: St.Widget,
_init: function(actor) {
_init(actor) {
this._source = actor;
this._source.connect('notify::visible', () => { this.queue_relayout(); });
this.parent();
},
vfunc_get_preferred_width: function(container, forHeight) {
vfunc_get_preferred_width(container, forHeight) {
if (this._source.visible)
return this._source.get_preferred_width(forHeight);
return [0, 0];
},
vfunc_get_preferred_height: function(container, forWidth) {
vfunc_get_preferred_height(container, forWidth) {
if (this._source.visible)
return this._source.get_preferred_height(forWidth);
return [0, 0];
@ -408,7 +404,7 @@ var FreezableBinLayout = new Lang.Class({
Name: 'FreezableBinLayout',
Extends: Clutter.BinLayout,
_init: function() {
_init() {
this.parent();
this._frozen = false;
@ -425,19 +421,19 @@ var FreezableBinLayout = new Lang.Class({
this.layout_changed();
},
vfunc_get_preferred_width: function(container, forHeight) {
vfunc_get_preferred_width(container, forHeight) {
if (!this._frozen || this._savedWidth.some(isNaN))
return this.parent(container, forHeight);
return this._savedWidth;
},
vfunc_get_preferred_height: function(container, forWidth) {
vfunc_get_preferred_height(container, forWidth) {
if (!this._frozen || this._savedHeight.some(isNaN))
return this.parent(container, forWidth);
return this._savedHeight;
},
vfunc_allocate: function(container, allocation, flags) {
vfunc_allocate(container, allocation, flags) {
this.parent(container, allocation, flags);
let [width, height] = allocation.get_size();
@ -450,12 +446,12 @@ var CalendarColumnLayout = new Lang.Class({
Name: 'CalendarColumnLayout',
Extends: Clutter.BoxLayout,
_init: function(actor) {
_init(actor) {
this.parent({ orientation: Clutter.Orientation.VERTICAL });
this._calActor = actor;
},
vfunc_get_preferred_width: function(container, forHeight) {
vfunc_get_preferred_width(container, forHeight) {
if (!this._calActor || this._calActor.get_parent() != container)
return this.parent(container, forHeight);
return this._calActor.get_preferred_width(forHeight);
@ -466,7 +462,7 @@ var DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
Extends: PanelMenu.Button,
_init: function() {
_init() {
let item;
let hbox;
let vbox;
@ -500,12 +496,12 @@ var DateMenuButton = new Lang.Class({
this._calendar = new Calendar.Calendar();
this._calendar.connect('selected-date-changed',
Lang.bind(this, function(calendar, date) {
(calendar, date) => {
layout.frozen = !_isToday(date);
this._messageList.setDate(date);
}));
});
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
this.menu.connect('open-state-changed', (menu, isOpen) => {
// Whenever the menu is opened, select today
if (isOpen) {
let now = new Date();
@ -513,7 +509,7 @@ var DateMenuButton = new Lang.Class({
this._date.setDate(now);
this._messageList.setDate(now);
}
}));
});
// Fill up the first column
this._messageList = new Calendar.CalendarMessageList();
@ -551,17 +547,17 @@ var DateMenuButton = new Lang.Class({
this._clock = new GnomeDesktop.WallClock();
this._clock.bind_property('clock', this._clockDisplay, 'text', GObject.BindingFlags.SYNC_CREATE);
this._clock.connect('notify::timezone', Lang.bind(this, this._updateTimeZone));
this._clock.connect('notify::timezone', this._updateTimeZone.bind(this));
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
this._sessionUpdated();
},
_getEventSource: function() {
_getEventSource() {
return new Calendar.DBusEventSource();
},
_setEventSource: function(eventSource) {
_setEventSource(eventSource) {
if (this._eventSource)
this._eventSource.destroy();
@ -571,7 +567,7 @@ var DateMenuButton = new Lang.Class({
this._eventSource = eventSource;
},
_updateTimeZone: function() {
_updateTimeZone() {
// SpiderMonkey caches the time zone so we must explicitly clear it
// before we can update the calendar, see
// https://bugzilla.gnome.org/show_bug.cgi?id=678507
@ -580,7 +576,7 @@ var DateMenuButton = new Lang.Class({
this._calendar.updateTimeZone();
},
_sessionUpdated: function() {
_sessionUpdated() {
let eventSource;
let showEvents = Main.sessionMode.showCalendarEvents;
if (showEvents) {

View File

@ -11,9 +11,9 @@ var Dialog = new Lang.Class({
Name: 'Dialog',
Extends: St.Widget,
_init: function (parentActor, styleClass) {
_init(parentActor, styleClass) {
this.parent({ layout_manager: new Clutter.BinLayout() });
this.connect('destroy', Lang.bind(this, this._onDestroy));
this.connect('destroy', this._onDestroy.bind(this));
this._initialKeyFocus = null;
this._initialKeyFocusDestroyId = 0;
@ -26,11 +26,11 @@ var Dialog = new Lang.Class({
this._dialog.add_style_class_name(styleClass);
this._parentActor = parentActor;
this._eventId = this._parentActor.connect('event', Lang.bind(this, this._modalEventHandler));
this._eventId = this._parentActor.connect('event', this._modalEventHandler.bind(this));
this._parentActor.add_child(this);
},
_createDialog: function () {
_createDialog() {
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
@ -40,6 +40,7 @@ var Dialog = new Lang.Class({
// mode accordingly so wrapped labels are handled correctly during
// size requests.
this._dialog.request_mode = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
this._dialog.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
this.contentLayout = new St.BoxLayout({ vertical: true,
style_class: "modal-dialog-content-box" });
@ -56,13 +57,13 @@ var Dialog = new Lang.Class({
y_align: St.Align.START });
},
_onDestroy: function () {
_onDestroy() {
if (this._eventId != 0)
this._parentActor.disconnect(this._eventId);
this._eventId = 0;
},
_modalEventHandler: function (actor, event) {
_modalEventHandler(actor, event) {
if (event.type() == Clutter.EventType.KEY_PRESS) {
this._pressedKey = event.get_key_symbol();
} else if (event.type() == Clutter.EventType.KEY_RELEASE) {
@ -88,7 +89,7 @@ var Dialog = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_setInitialKeyFocus: function(actor) {
_setInitialKeyFocus(actor) {
if (this._initialKeyFocus)
this._initialKeyFocus.disconnect(this._initialKeyFocusDestroyId);
@ -104,11 +105,11 @@ var Dialog = new Lang.Class({
return this._initialKeyFocus || this;
},
addContent: function (actor) {
addContent(actor) {
this.contentLayout.add (actor, { expand: true });
},
addButton: function (buttonInfo) {
addButton(buttonInfo) {
let { label, action, key } = buttonInfo;
let isDefault = buttonInfo['default'];
let keys;
@ -145,7 +146,7 @@ var Dialog = new Lang.Class({
return button;
},
clearButtons: function () {
clearButtons() {
this.buttonLayout.destroy_all_children();
this._buttonKeys = {};
},
@ -173,7 +174,7 @@ var MessageDialogContent = new Lang.Class({
null)
},
_init: function(params) {
_init(params) {
this._icon = new St.Icon({ y_align: Clutter.ActorAlign.START });
this._title = new St.Label({ style_class: 'headline' });
this._subtitle = new St.Label();
@ -243,7 +244,7 @@ var MessageDialogContent = new Lang.Class({
this.notify(prop);
},
insertBeforeBody: function(actor) {
insertBeforeBody(actor) {
this.messageBox.insert_child_below(actor, this._body);
}
});

View File

@ -49,10 +49,9 @@ function _getEventHandlerActor() {
Main.uiGroup.add_actor(eventHandlerActor);
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer.
eventHandlerActor.connect('event',
function(actor, event) {
return currentDraggable._onEvent(actor, event);
});
eventHandlerActor.connect('event', (actor, event) => {
return currentDraggable._onEvent(actor, event);
});
}
return eventHandlerActor;
}
@ -72,7 +71,7 @@ function removeDragMonitor(monitor) {
var _Draggable = new Lang.Class({
Name: 'Draggable',
_init : function(actor, params) {
_init(actor, params) {
params = Params.parse(params, { manualMode: false,
restoreOnSuccess: false,
dragActorMaxSize: undefined,
@ -81,18 +80,18 @@ var _Draggable = new Lang.Class({
this.actor = actor;
if (!params.manualMode) {
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this._onButtonPress.bind(this));
this.actor.connect('touch-event',
Lang.bind(this, this._onTouchEvent));
this._onTouchEvent.bind(this));
}
this.actor.connect('destroy', Lang.bind(this, function() {
this.actor.connect('destroy', () => {
this._actorDestroyed = true;
if (this._dragInProgress && this._dragCancellable)
this._cancelDrag(global.get_current_time());
this.disconnectAll();
}));
});
this._onEventId = null;
this._touchSequence = null;
@ -108,7 +107,7 @@ var _Draggable = new Lang.Class({
this._eventsGrabbed = false;
},
_onButtonPress : function (actor, event) {
_onButtonPress(actor, event) {
if (event.get_button() != 1)
return Clutter.EVENT_PROPAGATE;
@ -125,7 +124,7 @@ var _Draggable = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_onTouchEvent: function (actor, event) {
_onTouchEvent(actor, event) {
if (event.type() != Clutter.EventType.TOUCH_BEGIN ||
!global.display.is_pointer_emulating_sequence(event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
@ -145,7 +144,7 @@ var _Draggable = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_grabDevice: function(actor) {
_grabDevice(actor) {
let manager = Clutter.DeviceManager.get_default();
let pointer = manager.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
@ -157,7 +156,7 @@ var _Draggable = new Lang.Class({
this._grabbedDevice = pointer;
},
_ungrabDevice: function() {
_ungrabDevice() {
if (this._touchSequence)
this._grabbedDevice.sequence_ungrab (this._touchSequence);
else
@ -167,13 +166,13 @@ var _Draggable = new Lang.Class({
this._grabbedDevice = null;
},
_grabActor: function() {
_grabActor() {
this._grabDevice(this.actor);
this._onEventId = this.actor.connect('event',
Lang.bind(this, this._onEvent));
this._onEvent.bind(this));
},
_ungrabActor: function() {
_ungrabActor() {
if (!this._onEventId)
return;
@ -182,7 +181,7 @@ var _Draggable = new Lang.Class({
this._onEventId = null;
},
_grabEvents: function() {
_grabEvents() {
if (!this._eventsGrabbed) {
this._eventsGrabbed = Main.pushModal(_getEventHandlerActor());
if (this._eventsGrabbed)
@ -190,7 +189,7 @@ var _Draggable = new Lang.Class({
}
},
_ungrabEvents: function() {
_ungrabEvents() {
if (this._eventsGrabbed) {
this._ungrabDevice();
Main.popModal(_getEventHandlerActor());
@ -198,7 +197,7 @@ var _Draggable = new Lang.Class({
}
},
_onEvent: function(actor, event) {
_onEvent(actor, event) {
// We intercept BUTTON_RELEASE event to know that the button was released in case we
// didn't start the drag, to drop the draggable in case the drag was in progress, and
// to complete the drag and ensure that whatever happens to be under the pointer does
@ -249,7 +248,7 @@ var _Draggable = new Lang.Class({
* actors for other purposes (for example if you're using
* PopupMenu.ignoreRelease())
*/
fakeRelease: function() {
fakeRelease() {
this._buttonDown = false;
this._ungrabActor();
},
@ -264,7 +263,7 @@ var _Draggable = new Lang.Class({
* This function is useful to call if you've specified manualMode
* for the draggable.
*/
startDrag: function (stageX, stageY, time, sequence) {
startDrag(stageX, stageY, time, sequence) {
currentDraggable = this;
this._dragInProgress = true;
@ -281,7 +280,7 @@ var _Draggable = new Lang.Class({
this._touchSequence = sequence;
this._grabEvents();
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
this._dragX = this._dragStartX = stageX;
this._dragY = this._dragStartY = stageY;
@ -371,7 +370,7 @@ var _Draggable = new Lang.Class({
scale_y: scale * origScale,
time: SCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate: function() {
onUpdate() {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
@ -383,7 +382,7 @@ var _Draggable = new Lang.Class({
}
},
_maybeStartDrag: function(event) {
_maybeStartDrag(event) {
let [stageX, stageY] = event.get_coords();
// See if the user has moved the mouse enough to trigger a drag
@ -397,7 +396,7 @@ var _Draggable = new Lang.Class({
return true;
},
_updateDragHover : function () {
_updateDragHover() {
this._updateHoverId = 0;
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY);
@ -413,7 +412,7 @@ var _Draggable = new Lang.Class({
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
global.display.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
@ -431,26 +430,26 @@ var _Draggable = new Lang.Class({
targY,
0);
if (result != DragMotionResult.CONTINUE) {
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
global.display.set_cursor(DRAG_CURSOR_MAP[result]);
return GLib.SOURCE_REMOVE;
}
}
target = target.get_parent();
}
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
global.display.set_cursor(Meta.Cursor.DND_IN_DRAG);
return GLib.SOURCE_REMOVE;
},
_queueUpdateDragHover: function() {
_queueUpdateDragHover() {
if (this._updateHoverId)
return;
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._updateDragHover));
this._updateDragHover.bind(this));
GLib.Source.set_name_by_id(this._updateHoverId, '[gnome-shell] this._updateDragHover');
},
_updateDragPosition : function (event) {
_updateDragPosition(event) {
let [stageX, stageY] = event.get_coords();
this._dragX = stageX;
this._dragY = stageY;
@ -461,7 +460,7 @@ var _Draggable = new Lang.Class({
return true;
},
_dragActorDropped: function(event) {
_dragActorDropped(event) {
let [dropX, dropY] = event.get_coords();
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
dropX, dropY);
@ -510,7 +509,7 @@ var _Draggable = new Lang.Class({
}
this._dragInProgress = false;
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
@ -524,7 +523,7 @@ var _Draggable = new Lang.Class({
return true;
},
_getRestoreLocation: function() {
_getRestoreLocation() {
let x, y, scale;
if (this._dragActorSource && this._dragActorSource.visible) {
@ -556,13 +555,13 @@ var _Draggable = new Lang.Class({
return [x, y, scale];
},
_cancelDrag: function(eventTime) {
_cancelDrag(eventTime) {
this.emit('drag-cancelled', eventTime);
this._dragInProgress = false;
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
if (this._actorDestroyed) {
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
if (!this._buttonDown)
this._dragComplete();
this.emit('drag-end', eventTime, false);
@ -581,7 +580,7 @@ var _Draggable = new Lang.Class({
});
},
_restoreDragActor: function(eventTime) {
_restoreDragActor(eventTime) {
this._dragInProgress = false;
let [restoreX, restoreY, restoreScale] = this._getRestoreLocation();
@ -594,14 +593,14 @@ var _Draggable = new Lang.Class({
{ time: REVERT_ANIMATION_TIME });
},
_animateDragEnd: function (eventTime, params) {
_animateDragEnd(eventTime, params) {
this._animationInProgress = true;
// finish animation if the actor gets destroyed
// during it
this._dragActorDestroyId =
this._dragActor.connect('destroy',
Lang.bind(this, this._finishAnimation));
this._finishAnimation.bind(this));
params['opacity'] = this._dragOrigOpacity;
params['transition'] = 'easeOutQuad';
@ -613,7 +612,7 @@ var _Draggable = new Lang.Class({
Tweener.addTween(this._dragActor, params)
},
_finishAnimation : function () {
_finishAnimation() {
if (!this._animationInProgress)
return
@ -621,10 +620,10 @@ var _Draggable = new Lang.Class({
if (!this._buttonDown)
this._dragComplete();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
global.display.set_cursor(Meta.Cursor.DEFAULT);
},
_onAnimationComplete : function (dragActor, eventTime) {
_onAnimationComplete(dragActor, eventTime) {
dragActor.disconnect(this._dragActorDestroyId);
this._dragActorDestroyId = 0;
@ -641,7 +640,7 @@ var _Draggable = new Lang.Class({
this._finishAnimation();
},
_dragComplete: function() {
_dragComplete() {
if (!this._actorDestroyed)
Shell.util_set_hidden_from_pick(this._dragActor, false);

View File

@ -16,25 +16,23 @@ var EdgeDragAction = new Lang.Class({
Extends: Clutter.GestureAction,
Signals: { 'activated': {} },
_init : function(side, allowedModes) {
_init(side, allowedModes) {
this.parent();
this._side = side;
this._allowedModes = allowedModes;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
global.display.connect('grab-op-begin', () => { this.cancel(); });
},
_getMonitorRect : function (x, y) {
_getMonitorRect(x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.screen.get_monitor_index_for_rect(rect);
let monitorIndex = global.display.get_monitor_index_for_rect(rect);
return global.screen.get_monitor_geometry(monitorIndex);
return global.display.get_monitor_geometry(monitorIndex);
},
vfunc_gesture_prepare : function(action, actor) {
vfunc_gesture_prepare(action, actor) {
if (this.get_n_current_points() == 0)
return false;
@ -50,7 +48,7 @@ var EdgeDragAction = new Lang.Class({
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
},
vfunc_gesture_progress : function (action, actor) {
vfunc_gesture_progress(action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
@ -70,7 +68,7 @@ var EdgeDragAction = new Lang.Class({
return true;
},
vfunc_gesture_end : function (action, actor) {
vfunc_gesture_end(action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);

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