Compare commits

..

462 Commits

Author SHA1 Message Date
02f2f694e4 Bump version to 3.10.1
Update NEWS.
2013-10-15 20:27:52 +02:00
d175a588f7 network: being able to use keyboard to connect to a Wireless
https://bugzilla.gnome.org/show_bug.cgi?id=710144
2013-10-15 20:27:05 +02:00
4bb41f2f66 Revert "network: being able to use keyboard to connect to a Wireless"
This reverts commit d581d29198.
2013-10-15 20:14:02 +02:00
088c46c7be Revert "Bump version to 3.10.1"
This reverts commit 4228c40b3d.
2013-10-15 20:14:00 +02:00
4228c40b3d Bump version to 3.10.1
Update NEWS.
2013-10-15 20:06:25 +02:00
d581d29198 network: being able to use keyboard to connect to a Wireless
https://bugzilla.gnome.org/show_bug.cgi?id=710144
2013-10-15 19:10:38 +02:00
5a7e854f9e appDisplay: Remember selected view across sessions
The application picker will always open with the view that was last
selected during the session, but the selection is reset on each
restart. This results in some annoyance for users that use the
ALL view exclusively, as they have to toggle views once each
session - the same would apply to exclusive FREQUENT view users
were the defaults to be changed, so the best solution is to simply
make the selected view persistent by storing it in GSettings.

https://bugzilla.gnome.org/show_bug.cgi?id=710042
2013-10-15 19:06:53 +02:00
6e13823ccc shell-js: fix incorrect G_BEGIN_DECLS in header 2013-10-15 09:21:59 +11:00
5c5f2fdf8f a11y: setting ATK_ROLE_ARROW to object unicodeArrow
https://bugzilla.gnome.org/show_bug.cgi?id=710120
2013-10-14 22:29:09 +02:00
96aa33f4ef messageTray: Don't remove and re-add the focus group on button changes
https://bugzilla.gnome.org/show_bug.cgi?id=710115
2013-10-14 15:24:53 -04:00
25fd23e703 messageTray: Split out the notification's destroy handler
This is complex enough to split out.

https://bugzilla.gnome.org/show_bug.cgi?id=710115
2013-10-14 15:24:53 -04:00
99cf4e5787 messageTray: Only connect to a notification's open/destroy once
If we pushNotification the same notification multiple times, we
won't append it to the array again, but we will attach multiple
handlers needlessly.

https://bugzilla.gnome.org/show_bug.cgi?id=710115
2013-10-14 15:24:53 -04:00
66a4cb5875 messageTray: Move the notification policy classes here
The NotificationDaemon really should be for the hookup of remote
notifications, rather than policies.

https://bugzilla.gnome.org/show_bug.cgi?id=710115
2013-10-14 15:24:53 -04:00
da14e2c349 messageTray: Clean up code that determines if something is clearable
https://bugzilla.gnome.org/show_bug.cgi?id=710115
2013-10-14 15:24:53 -04:00
4cda61a16a gdm: support pre-authenticated logins from oVirt
oVirt is software for managing medium-to-large scale deployments of
virtual machine guests across multiple hosts. It supports a feature
where users can authenticate with a central server and get
transparently connected to a guest system and then automatically get logged
into that guest to an associated user session.

Guests using old versions of GDM support this single-sign-on capability
by means of a greeter plugin, using the old greeter's extension
API.

This commit adds similar support to the gnome-shell based login screen.

How it works:

* The OVirtCredentialsManager singleton listens for

  'org.ovirt.vdsm.Credentials.UserAuthenticated'

  D-Bus signal on the system bus from the

  'org.ovirt.vdsm.Credentials'

  bus name. The service that provides that bus name is called
  the oVirt guest agent. It is also responsible for interacting
  with the the central server to get user credentials.

* This UserAuthenticated signal passes, as a parameter, the a token
  which needs to be passed through to the PAM service that is specifically
  set up to integrate with the oVirt authentication architecture.
  The singleton object keeps the token internally so it can be queried
  later on.

* The OVirtCredentialsManager emits a signal 'user-authenticated' on
  it's object once the dbus signal is triggered

* When the 'user-authenticated' signal is emitted, the login screen
  tells GDM to start user verification using the PAM service. The
  authentication stack of the service includes a PAM module
  provided by oVirt that securely retrieves user credentials
  from the oVirt guest agent. The PAM module then forwards those
  credentials on to other modules in the stack so, e.g.,
  the user's gnome keyring can be automatically unlocked.

* In case of the screen shield being visible, it also will react on that
  'user-authenticated' signal and lift the shield.
  In that case the login screen will check on construction time if
  the signal has already been triggered, and a token is available.
  If a token is available it will immediately trigger the functionality
  as described above.

Signed-off-by: Vinzenz Feenstra <evilissimo@redhat.com>

https://bugzilla.gnome.org/show_bug.cgi?id=702162
2013-10-14 13:54:30 -04:00
002afda503 SearchDisplay: handle certain result IDs specially
Allow the prefix 'special:' applied to result IDs to mark results
that should be always shown, even when they would overflow the
maximum results cap. This will be used by epiphany for the special
"Search the Web" result.

https://bugzilla.gnome.org/show_bug.cgi?id=707055
2013-10-14 18:47:20 +02:00
cb7a2e8c6a shell-global: Use G_VARIANT_TYPE macro for checking 2013-10-14 10:52:45 -04:00
d21ae1dad1 shell-global: Fix an invalid memory botch-up
The value we return is a floating ref, which gjs shouldn't
try to free.

https://bugzilla.gnome.org/show_bug.cgi?id=710104
2013-10-14 09:49:51 -04:00
4548859509 shell-global: Fix a few memory leaks
https://bugzilla.gnome.org/show_bug.cgi?id=710104
2013-10-14 09:49:51 -04:00
09c6e6427a Updated Serbian translation 2013-10-14 10:29:57 +02:00
8c34398a15 Updated Slovenian translation 2013-10-13 23:43:34 +02:00
a65b705080 [l10n] Updated Catalan (Valencian) translation 2013-10-13 22:43:34 +02:00
7e28c71074 [l10n] Update Catalan translation 2013-10-13 22:43:31 +02:00
726f4a6715 Updated Lithuanian translation 2013-10-13 20:06:00 +03:00
a444b43548 Updated Portuguese translation 2013-10-13 12:22:54 +01:00
473bb139d1 Updated Latvian translation 2013-10-13 13:35:18 +03:00
d084770cea NetworkMenu: fix regression for VPN connections
Fix regression from e898e29910,
the code was moved from a method to a global function, but one
call site was not updated.

https://bugzilla.gnome.org/show_bug.cgi?id=710019
2013-10-13 02:11:14 +02:00
619389ed20 NotificationDaemon: fix icons for notifications without an app
NotificationDaemon doesn't pass a gicon to the Notification constructor,
because it calls .update() immediately after, so messageTray.js
calls into Source.createIcon(), which returns null and crashes.
Instead, shortcut the Notification constructor by skipping
.update() completely.

https://bugzilla.gnome.org/show_bug.cgi?id=709998
2013-10-13 01:23:18 +02:00
ad043e009e workspaceThumbnail: Drop the _background hack
The _background hack was added because the old way the zooming animation
worked, it set the allocation of the workspaces view and thumbnails box
to the final position and used animations to smoothly animate.

During the 3.6 cycle when we added the new search view, Cosimo changed the
way the zoom animation works so that rather than set the final allocation
and animate, we actually do adjust the allocation of the workspaces view
and thumbnails box.

So, as the hack is no longer necessary, we can drop it.

https://bugzilla.gnome.org/show_bug.cgi?id=694881
2013-10-12 14:38:13 -04:00
89b9d079b1 overviewControls: Don't use the child's preferred size to slide from
In order for the workspace thumbnails box to have the correct size,
we need to constrain the width of the thumbnails box to the height we're
given, instead of assuming an unlimited height.

https://bugzilla.gnome.org/show_bug.cgi?id=694881
2013-10-12 14:38:13 -04:00
58a8845047 overviewControls: Don't try to align something sliding to the right
0 is already the correct value.

https://bugzilla.gnome.org/show_bug.cgi?id=694881
2013-10-12 14:38:13 -04:00
3e6c8e68b4 overviewControls: Clarify some code with a comment
translationX is sort of a bad name, since it confuses with the
actor's translation, which is used for sliding without allocation.

https://bugzilla.gnome.org/show_bug.cgi?id=694881
2013-10-12 14:38:13 -04:00
40cd92f701 overviewControls: Correct the use of x2 in SlidingControl
The x2 here needs to be more than just the width; it needs to
be added onto the x1.

https://bugzilla.gnome.org/show_bug.cgi?id=694881
2013-10-12 14:38:13 -04:00
e216addf7c Updated Dutch translation 2013-10-12 19:59:34 +02:00
9291594330 app-system: remove outdated comment
This parameter was removed before 3.2 but the comment stuck around.
2013-10-12 10:09:36 -05:00
f6010864ea layout: Flush region update in showOverview
We cannot wait for the queued update region to fire when
xdnd is being used because a wrong input shape can result
into a xdnd leave event when the user moves the pointer fast.

https://bugzilla.gnome.org/show_bug.cgi?id=708887
2013-10-11 20:16:44 +02:00
13e6a6def5 Revert "overview: Ignore dragEnd while the animation is still in progress"
This reverts commit 80a3bb85aa.

https://bugzilla.gnome.org/show_bug.cgi?id=708887
2013-10-11 20:16:44 +02:00
575b373cd5 power: Use the icon from the primary device for status
https://bugzilla.gnome.org/show_bug.cgi?id=709925
2013-10-11 13:37:10 -04:00
0892065649 notificationDaemon: Raise the app when clicking on a notification, not the MRU window
https://bugzilla.gnome.org/show_bug.cgi?id=709866
2013-10-11 13:37:10 -04:00
766ef367fb notificationDaemon: Fix the fallback for image-data
The indentation here is wrong, the else actually belongs to the outer
if statement, not the inner if statement.
2013-10-11 13:37:10 -04:00
0c7d9958f5 notificationDaemon: Remove dead code 2013-10-11 13:37:09 -04:00
425b8f6073 Updated Czech translation 2013-10-11 18:28:52 +02:00
63593e45a6 Make dropdown arrows consistent size
Since the agregate menu does 120% of font-size, make this
for all dropdown arrows in gnome-shell and rename the css
class to make clear that it is used in overall gnome-shell

https://bugzilla.gnome.org/show_bug.cgi?id=709564
2013-10-11 17:32:55 +02:00
a6ee9806de Uploaded Ukranian 2013-10-11 15:02:28 +03:00
a6579f4ceb Updated Brazilian Portuguese translation 2013-10-11 07:24:18 -03:00
639622a4fe [l10n] Updated Italian translation. 2013-10-11 09:41:24 +02:00
e28ec2f5ab Updated Indonesian translation 2013-10-11 10:15:14 +07:00
873753c735 Updated Hebrew translation 2013-10-11 01:14:45 +03:00
ff14951be4 Updated Hebrew translation 2013-10-11 01:11:25 +03:00
b47b445558 Updated Polish translation 2013-10-10 23:43:39 +02:00
6e9a2fea89 messageTray: Add 'Notifications' switch to tray menu
According to the designs, the notifications switch was supposed
to move from the user menu to the new message tray menu. However
so far the new system status implementation only removed the old
switch, so add it back in its new place now.

https://bugzilla.gnome.org/show_bug.cgi?id=707073
2013-10-10 23:13:47 +02:00
64d2679b3c Updated Czech translation 2013-10-10 21:09:42 +02:00
3c3d4dfccb Updated Hungarian translation 2013-10-10 13:43:23 +02:00
0ccffed517 Updated Spanish translation 2013-10-10 10:49:53 +02:00
20c18c1fc0 Suppress animation for titles in overview
Because of the animation and collision with relayout, the title of windows in overview may not appear, mainly
the first time we enter in overview

With an animation delay of 0.1s, you'll not see the difference

https://bugzilla.gnome.org/show_bug.cgi?id=709392
2013-10-10 08:51:13 +02:00
a21c0097c2 Tajik translation updated 2013-10-10 11:48:03 +05:00
404d9ef2af [l10n] Updated Italian translation. 2013-10-10 08:37:21 +02:00
503fa1cbce Updated Indonesian translation 2013-10-10 12:59:23 +07:00
63f7991d0f Updated Brazilian Portuguese translation 2013-10-09 23:26:40 -03:00
ae301c1f39 Updated Galician translations 2013-10-09 23:09:57 +02:00
8e911fb719 Updated Galician translations 2013-10-09 23:04:21 +02:00
a0d84e44c5 L10N: Updated Persian translations 2013-10-10 00:28:17 +03:30
81fb7ebb31 Fix some broken GTK-Doc comment blocks 2013-10-09 20:14:57 +02:00
3751211590 shell-global: Fix introspection issues
Remove stray bullet points, and don't actually mark for introspection
since it's private anyway (it starts with a _)
2013-10-09 13:31:00 -04:00
6b4cba09be Updated Polish translation 2013-10-09 19:04:21 +02:00
6a7d184b7b NetworkMenu: make the settings launcher point to the right devices
Tell gnome-control-center to focus on the associated device when
launching it from one of the submenus.

https://bugzilla.gnome.org/show_bug.cgi?id=709246
2013-10-09 18:39:44 +02:00
bde5cfc8bb NetworkMenu/NMDeviceModem: use the operator name when we have it
Instead of the connection name, as the operator name is usually
shorter and more useful.

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-09 18:39:44 +02:00
777c7a952b NetworkMenu/NMDeviceModem: fix status texts for airplane mode
Show "Hardware Disabled" when disabled by HW switch, and
generically "Disabled" when airplane mode is active, as
indicated by v4 mockups.
Note that bluetooth is not affected by NM handling of airplane
mode (and generally the firmware makes the USB bluetooth
adapter disappear when rfkilled), so this is in NMDeviceModem
instead of NMConnectionDevice.

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-09 18:39:44 +02:00
c79bdd9029 NetworkMenu/NMConnectionDevice: fix status text
Be consistent with v4 mockups

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-09 18:39:44 +02:00
6a154efe65 Network: show Not Connected instead of Off when wifi radio is on
When wifi is powered but not connected, show Not Connected instead
of off. This avoids a Off status next to a Turn Off menu item.

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-09 18:39:44 +02:00
627f3ef36b keyring: Cancel active prompts on disable()
Since commit 1242a16265, we will use a fake prompt which
cancels alls requests without dialog when the keyring component
is disabled. However this does only apply to new requests, dialogs
that are already active when the session mode changes are kept
open. This is not quite as expected, so cancel the prompt in that
case.

https://bugzilla.gnome.org/show_bug.cgi?id=708910
2013-10-09 17:58:37 +02:00
3d28836f2c keyring: Remove unused global
https://bugzilla.gnome.org/show_bug.cgi?id=708910
2013-10-09 17:58:37 +02:00
c28bd04958 Finnish translation update 2013-10-09 14:23:48 +03:00
a6fb3acb42 NetworkMenu: hide the "Turn On" item when the rfkill is hardware blocked
If wifi is disabled in hardware, there is nothing we can do at
the sw level, so hide the menu item.

https://bugzilla.gnome.org/show_bug.cgi?id=709635
2013-10-08 22:20:27 +02:00
8a8b3bf96e NetworkMenu: fix wireless-enabled property notifications
The property is on the NMClient, not NMDevice. Also, make sure
we disconnect the signal when the item is destroyed.
Also, connect to wireless-hardware-enabled, which we'll use soon.

https://bugzilla.gnome.org/show_bug.cgi?id=709635
2013-10-08 22:20:27 +02:00
f7624e5f05 network: make the icon visible again when going from ethernet to nothing
https://bugzilla.gnome.org/show_bug.cgi?id=709638
2013-10-08 14:26:38 -04:00
55edfd2e4a notificationDaemon: Focus the new window before destroying the notification
Destroying the notification will make the key focus be reset to NULL, which
means that gnome-shell will try to focus the MRU window, thinking the user is
done interacting and wants to go back to whatever they were doing.

Unfortunately, since we focus two windows at the same time, they will have
the same timestamp, meaning that the window that actually gets focused will
be a race as to whoever responds to their WM_TAKE_FOCUS event last.

If we explicitly set the focus beforehand, then gnome-shell will believe it
got key focus taken away from it, and won't try to focus the MRU when the
key focus drops to NULL.

https://bugzilla.gnome.org/show_bug.cgi?id=703265
2013-10-08 13:05:34 -04:00
91878dd52c Updated Indonesian translation 2013-10-08 17:07:23 +07:00
c132358ec9 Updated Latvian translation 2013-10-07 21:54:39 +03:00
e426f8ac47 BoxPointer: account for border width when requesting size
We must reduce the forWidth in the call to get_preferred_height()
with the border width, otherwise we might request a smaller height
that we actually need and overflow.

https://bugzilla.gnome.org/show_bug.cgi?id=696564
2013-10-07 20:18:48 +02:00
740dca8afc build: Bump gjs requirement
https://bugzilla.gnome.org/show_bug.cgi?id=709543
2013-10-07 09:37:59 +02:00
6ae06d319c [l10n] Updated Catalan (Valencian) translation 2013-10-06 21:58:43 +02:00
30bc2b2f9c [l10n] Update Catalan translation 2013-10-06 21:06:39 +02:00
7dc8e9d657 Updated Russian translation 2013-10-06 12:31:47 +04:00
1ab2fa5bf0 [l10n]Updated Turkish translation 2013-10-06 09:19:37 +03:00
779a1077bf Updated Serbian translation 2013-10-05 20:59:51 +02:00
815bf7a53a L10N: Updated Persian translations 2013-10-05 18:06:59 +03:30
91a382dfb5 Fix Lithuanian calendar translation 2013-10-05 16:51:19 +03:00
2d8d4cd57d Updated Serbian translation 2013-10-05 06:49:07 +02:00
0c5fe2b3bf Updated Serbian translation 2013-10-05 06:08:07 +02:00
56c487347f Updated Belarusian translation. 2013-10-03 23:02:05 +03:00
0a572fce1b Updated Norwegian bokmål translation 2013-10-03 20:38:08 +02:00
e898e29910 NetworkMenu/NMConnectionDevice: grab the connection before using it
If the active connection for the device is not the primary or
activating globally, it won't have the _connection and _primaryDevice
expando properties, so grab them from the settings object.

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-03 16:03:41 +02:00
843f076225 NetworkMenu/NMDeviceWireless: use the device state instead of active connection state
Since we connect to signals for that, we need to sync on that, or
we can miss a notification.

https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-03 16:01:27 +02:00
fdb732c8c2 Bluetooth: fix ngettext call
https://bugzilla.gnome.org/show_bug.cgi?id=709043
2013-10-03 16:01:27 +02:00
33896a4e8f network: fix NMConnectionSection destruction
The patch fixes the following warning, and along with it, the proper
destruction of the NMConnectionSection is performed so that items get
correctly removed from the menu.

(gnome-shell:24528): Gjs-WARNING **: JS ERROR: TypeError:
this.statusItem is undefined
NMConnectionSection<.destroy@/home/aleksander/gnome/install/share/gnome-shell/js/ui/status/network.js:173
wrapper@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:213
_parent@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:175
NMConnectionDevice<.destroy@/home/aleksander/gnome/install/share/gnome-shell/js/ui/status/network.js:292
wrapper@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:213
_parent@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:175
NMDeviceModem<.destroy@/home/aleksander/gnome/install/share/gnome-shell/js/ui/status/network.js:448
wrapper@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:213
NMApplet<._removeDeviceWrapper@/home/aleksander/gnome/install/share/gnome-shell/js/ui/status/network.js:1421
wrapper@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:213
NMApplet<._deviceRemoved@/home/aleksander/gnome/install/share/gnome-shell/js/ui/status/network.js:1416
wrapper@/home/aleksander/gnome/install/share/gjs-1.0/lang.js:213

https://bugzilla.gnome.org/show_bug.cgi?id=709248
2013-10-03 00:50:02 +02:00
51e016a0d6 theme: modify the avatar and user name
Change the avatar and user name border radius, padding
and text size to be consistent with mockups.

https://bugzilla.gnome.org/show_bug.cgi?id=702309
2013-10-02 22:26:30 +02:00
8737b06559 loginDialog: MessageType is now in GdmUtil
https://bugzilla.gnome.org/show_bug.cgi?id=709286
2013-10-02 13:58:09 -04:00
15ab285174 layout: Use monitor index when adding bg managers
Don't assume that this._bgManagers.push() (i.e adding to the end) is always
correct.

On startup we call _createPrimaryBackground which passes in the primary index
which may not be 0.
2013-10-02 15:58:22 +02:00
3a4782cc64 app-system: Fix some enum warnings
https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-10-02 09:49:03 -04:00
0256a6d47b app: Use g_variant_lookup instead of dict iteration 2013-10-02 09:49:02 -04:00
8b0e846e0e background: Disconnect settings signal handler on destroy
We connect to the changed signal in _init() but never actually disconnect from
it. The callback has a reference to "this" which results into the background
object not getting garbage collected.

Fix that leaks by disconnecting in _destroy()

https://bugzilla.gnome.org/show_bug.cgi?id=709263
2013-10-02 15:43:30 +02:00
41acb5d3cc Updated Czech translation 2013-10-02 09:56:45 +02:00
a2f9b8ea9b workspacesView: Remove dead code 2013-10-01 18:41:26 -04:00
6237a1c505 workspace: Remove unused leftover constant
from the window zooming days
2013-10-01 18:41:26 -04:00
7c08db0b0f [l10n] Updated Italian translation. 2013-10-01 19:22:11 +02:00
df1270ac49 Updated Danish translation 2013-10-01 19:10:05 +02:00
46edc053d4 overview: Add cover pane directly to overviewGroup
The cover pane is used to block events during transitions, but as
workspaces don't share the same container as other overview elements,
they are currently excempt from the event blocking.
Move the cover pane to the top-level overview container instead.

https://bugzilla.gnome.org/show_bug.cgi?id=709034
2013-10-01 17:16:51 +02:00
908046c31a [l10n] Updated Estonian translation 2013-10-01 17:14:01 +03:00
8380c79875 network: Update the network indicator when the VPN state changes 2013-10-01 10:25:46 -04:00
8a4879a96a Updated Traditional Chinese translation(Hong Kong and Taiwan) 2013-09-30 19:40:48 +08:00
cdf1a77f08 Updated Spanish translation 2013-09-30 12:00:58 +02:00
3f9857ccbd Assamese translation updated 2013-09-30 13:32:07 +05:30
1d65a31420 Updated Lithuanian translation 2013-09-29 20:33:17 +03:00
dafdf0838a Updated Slovak translation 2013-09-29 17:41:47 +01:00
f9cf135f68 update Punjabi Translaiton 2013-09-29 05:26:34 -05:00
a1878e54c9 Updated Norwegian bokmål translation 2013-09-29 11:29:08 +02:00
95e5d899a9 Updated Basque language 2013-09-29 10:53:34 +02:00
ee8321df67 Updated Slovenian translation 2013-09-28 21:49:04 +02:00
4918213e68 Tajik translation updated 2013-09-28 19:39:12 +05:00
ed7f349fc6 Updated Galician translations 2013-09-28 16:25:15 +02:00
2888f22a24 Updated Norwegian bokmål translation 2013-09-28 14:53:19 +02:00
fcb217f681 Updated Brazilian Portuguese translation 2013-09-28 05:16:53 -03:00
9ffa9fe1a8 Updated Galician translations 2013-09-27 21:38:08 +02:00
905020c507 Updated Slovak translation 2013-09-27 17:40:35 +01:00
02f5500641 theme: Make indicators checked&active like checked 2013-09-27 17:06:26 +02:00
465af55d6e theme: Add hover/active states to indicators
Until now we had the same svg for hover, active and checked
states in the pagination indicators. Just differentiate between
them using differents svg.

svg files provided by Jakub Steiner

https://bugzilla.gnome.org/show_bug.cgi?id=708852
2013-09-27 15:50:28 +02:00
80a3bb85aa overview: Ignore dragEnd while the animation is still in progress
Moving the mouse fast enough during xdnd will trigger a xdnd-leave event
because the input shape is not updated until after the animation is done.

So simply ignore the leave events while the animation is in progress.

https://bugzilla.gnome.org/show_bug.cgi?id=708887
2013-09-27 12:54:22 +02:00
ea26bd3003 Updated Latvian translation 2013-09-26 23:30:59 +03:00
508a511d2a Revert "overviewControls: Don't allow appearing controls to "pop in""
This reverts commit e31693bbee.

This doesn't properly adjust the allocation, leading to an unbalanced
overview where things aren't centered properly. Just revert for now,
and we'll rethink this next cycle.
2013-09-26 16:20:06 -04:00
2d80cb71db searchDisplay: Scroll results when the user focuses a provider icon
Otherwise, it seems odd to highlight results the user can't see
simply by pressing down a lot.

https://bugzilla.gnome.org/show_bug.cgi?id=708868
2013-09-26 15:17:29 -04:00
e31693bbee overviewControls: Don't allow appearing controls to "pop in"
When coming back from search or apps, the workspace thumbnails and dash
don't slide in but "pop in". This is because of bad timing: when slideIn
is called, we immediately start the translation animation, and it
completes before by the time we fade the new page in.

Fix this by calling slideIn and slideOut at two different times: we now
slide out when the old page with our controls is fading out, and slide in
when the new page with our controls is fading in.

https://bugzilla.gnome.org/show_bug.cgi?id=708340
2013-09-26 13:39:20 -04:00
fb561f10a7 network: Make sure to set the signal icon at dialog item construction time
We forgot to set it here; it would be updated if there was changes in the
signal, but not when it was created.

https://bugzilla.gnome.org/show_bug.cgi?id=708442
2013-09-26 11:06:42 -04:00
0c57d53e03 Update Esperanto translation 2013-09-26 09:09:37 -04:00
3b1b9f589b SystemMenu: wait for a completed paint before switching VT
Activating the GDM login screen switches VT and causes X to freeze
event processing (because it lost the drm master), so must make
sure to have painted the lock screen at least once before proceeding,
or the user can go back and see the unlocked desktop.

https://bugzilla.gnome.org/show_bug.cgi?id=708051
2013-09-26 10:46:42 +02:00
ac8d39acf4 Updated Lithuanian translation 2013-09-25 23:22:27 +03:00
664e795217 [l10n]Updated Turkish translation 2013-09-25 21:16:28 +03:00
82bf323f63 Updated German translation 2013-09-25 15:25:31 +02:00
547ac85113 Updated Basque language 2013-09-25 11:17:01 +02:00
46e0e4430d Bump version to 3.10.0.1
Update NEWS.
2013-09-24 16:04:57 -04:00
609a31ea46 loginManager: fix versionCompare function
It's important to compare the version components as integers,
not strings, so "10" evaulates as greater than "5"

This fixes the login screen in gnome 3.10.

https://bugzilla.gnome.org/show_bug.cgi?id=708691
2013-09-24 14:22:09 -04:00
3e99eb10d1 Updated Norwegian bokmål translation 2013-09-24 19:38:41 +02:00
b9d935af0c ActivitiesButton: close the dummy menu when activating the button
We need to close the menu to make sure that any grabs held by
the PopupMenuManager are released, and events are properly delivered.

https://bugzilla.gnome.org/show_bug.cgi?id=707852
2013-09-24 16:28:31 +02:00
31d3e82aa8 Updated Czech translation 2013-09-24 16:10:40 +02:00
dfdc17197b Punjabi Translation updated by Aman 2013-09-24 07:54:25 -05:00
62b965b4b7 Updated Spanish translation 2013-09-24 14:39:14 +02:00
ba221abea5 Updated Belarusian translation. 2013-09-24 15:03:09 +03:00
aa026c7134 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2013-09-24 19:13:45 +08:00
496cfff97a Assamese translation updated 2013-09-24 14:25:28 +05:30
ccaa7f5f3e Updated Russian translation 2013-09-24 12:18:45 +04:00
f492d21c70 Update Kazakh translation 2013-09-24 06:37:02 +06:00
1983541f8c Bump version to 3.10.0
Update NEWS.
2013-09-23 23:33:14 +02:00
e4cb3672b9 Updated Galician translations 2013-09-23 22:24:36 +02:00
a06a78a9c1 aggregate-menu: Increase width
Add 20px more width to make longer strings (translations) fit better.

https://bugzilla.gnome.org/show_bug.cgi?id=708472
2013-09-23 22:23:46 +02:00
2ba91ad837 Updated Slovenian translation 2013-09-23 21:18:03 +02:00
66eb3ea723 Updated Polish translation 2013-09-23 20:38:24 +02:00
d30e992b20 Updated Polish translation 2013-09-23 20:35:58 +02:00
c6a342563f Updated Danish translation 2013-09-23 19:43:15 +02:00
fd584eda05 l10n: Update Japanese translation 2013-09-24 00:01:51 +09:00
4301506590 Updated Hebrew translation
Signed-off-by: Yosef Or Boczko <yoseforb@gmail.com>
2013-09-23 17:59:51 +03:00
88f7c3a970 Updated Indonesian translation 2013-09-23 21:25:49 +07:00
f21a9f0cc2 [l10n] Updated Italian translation. 2013-09-23 16:21:33 +02:00
2233c2e618 Updated Brazilian Portuguese translation 2013-09-23 10:56:43 -03:00
6264419bd4 Update French translation 2013-09-23 15:48:18 +02:00
b62effb8fa add missing translation markers around string in schema 2013-09-23 15:35:06 +02:00
c8a07dd612 messageTray: Fix condition for adding the tray to CtrlAltTab
With the current condition, we wrongly add the message tray to
CtrlAltTab if we start up locked or as greeter.

https://bugzilla.gnome.org/show_bug.cgi?id=708380
2013-09-23 13:32:17 +02:00
02c99e4b25 authPrompt: Clear _queryingService on verification failure
A conversation is finished after failing, and we are expecting a new
one to be started shortly after. However if we encounter an existing
reference to a previously set _queryingService, we will clear the
password entry, which might already contain a partially typed password
at that point. The behavior does make sense in the case of conflicting
conversations, but in the failure case it is both unexpected and
annoying, so clear _queryingService early to prevent this.

https://bugzilla.gnome.org/show_bug.cgi?id=708186
2013-09-23 13:32:17 +02:00
1242a16265 keyring: Don't unregister the prompt when disabled
gnome-keyring provides a fallback in case our builtin prompt fails
to register, so keyring dialogs may still pop up even when they
are supposed to be disabled.
Instead, keep the prompt registered but cancel requests immediately
while disabled.

https://bugzilla.gnome.org/show_bug.cgi?id=708187
2013-09-23 13:32:17 +02:00
a89fd17b8e shell: Make KeyringPrompt.cancel() callable from signal handlers
gcr/gnome-keyring don't handle the case where prompt_password_async()/
prompt_confirm_async() return their result from within the function
very well (or rather: break badly). Calling gcr_prompt_close() instead
is safe, but to avoid these kind of errors in the future, modify
shell_keyring_prompt_cancel() to work as expected in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=708187
2013-09-23 13:32:17 +02:00
3d5e7bd6f1 Updated Indonesian translation 2013-09-23 09:40:56 +07:00
cefcb89487 Updated Portuguese translation 2013-09-22 23:50:24 +01:00
005272bde9 bluetooth: Actually add the menu item to the bluetooth menu
https://bugzilla.gnome.org/show_bug.cgi?id=708541
2013-09-22 22:22:49 +02:00
491e60e4f2 Updated Galician translations 2013-09-22 19:49:52 +02:00
e5f72fd302 Updated Hebrew translation 2013-09-22 13:58:19 +03:00
5f21b100b8 Updated Ukrainian 2013-09-22 11:28:53 +03:00
1a4c7629c5 Translate 'suspend' as 'pauzestand' for consistency 2013-09-21 23:27:43 +02:00
d21734ee47 Updated Dutch translation 2013-09-21 23:04:37 +02:00
e140e2c367 Updated Latvian translatio 2013-09-21 21:53:36 +03:00
7ced1f5b54 focusCaretTracker: Lower AT-SPI's timeout values
Have AT-SPI calls time out after 250ms, to mitigate the effect of a
deadlock when querying another application that is trying to query
gnome-shell.

https://bugzilla.gnome.org/show_bug.cgi?id=708387
2013-09-21 04:51:42 -05:00
54b028ee3e Updated Ukrainian 2013-09-21 11:42:12 +03:00
703336e1ea Updated Esperanto translation 2013-09-21 09:54:37 +02:00
9e936252ae Updated Polish translation 2013-09-20 17:44:36 +02:00
fc71a0f081 Updated Polish translation 2013-09-20 17:29:48 +02:00
86c72fa15d Updated Traditional Chinese translation(Hong Kong and Taiwan) 2013-09-20 13:43:49 +08:00
6ba5af1e9e Updated Romanian Translation 2013-09-19 21:54:35 +02:00
33a4f59cfb popupMenu: Center the labels in submenu items
https://bugzilla.gnome.org/show_bug.cgi?id=708330
2013-09-19 12:40:43 -04:00
39134f0d9b networkAgent: Don't allow ellipsization of Password label
We don't want password entries to grow when entering more characters
that fit the available width; as labels' ClutterText ellipsizes by
default, the password labels allow entries to grow by shrinking.
Setting the appropriate ellipsize mode fixes this.

https://bugzilla.gnome.org/show_bug.cgi?id=708324
2013-09-19 07:53:57 +02:00
30e7440851 keyring: Don't allow ellipsization of Password label
We don't want the password entry to grow when entering more characters
that fit the available width; as labels' ClutterText ellipsizes by
default, the password label allows the entry to grow by shrinking.
Setting the appropriate ellipsize mode fixes this.

https://bugzilla.gnome.org/show_bug.cgi?id=708324
2013-09-19 07:53:57 +02:00
be1a7bac7c networkAgent: Port to ClutterTableLayout
We don't make use of any functionality StTable provides over
ClutterTableLayout, so port all users to the Clutter layout
in order to remove our own copy of the code.

https://bugzilla.gnome.org/show_bug.cgi?id=703833
2013-09-19 07:53:57 +02:00
fb52a93a28 keyring: Port to ClutterTableLayout
We don't make use of any functionality StTable provides over
ClutterTableLayout, so port all users to the Clutter layout
in order to remove our own copy of the code.

https://bugzilla.gnome.org/show_bug.cgi?id=703833
2013-09-19 07:53:56 +02:00
efdf1ff755 main: Close runDialog as necessary on session mode changes
We already do this for looking glass, but it makes even less sense
for the normal run dialog - if a mode sets runDialog to false, the
intention is to not allow executing aribitrary commands.

https://bugzilla.gnome.org/show_bug.cgi?id=708218
2013-09-19 07:53:56 +02:00
2c00dad211 network: Make sure to resync when the activating connection changes
Otherwise, we may be left with a stale activating connection if a
connection is activating, but doesn't fully activate for whatever
reason.

https://bugzilla.gnome.org/show_bug.cgi?id=708322
2013-09-18 17:15:01 -04:00
c23786c73e St: Fix fade effect
Commit 4095a58eb9 introduced a
regression, since we have to take into account four cases,
top, bottom, right, and left, and that can't be merged into
two like that commit did.
So fix it to make fade effect works again.

https://bugzilla.gnome.org/show_bug.cgi?id=708256
2013-09-18 20:01:49 +02:00
7f1b07b76f Revert "Background: Drop "saturation" related source"
This reverts commit 2f35ad6e65.
2013-09-18 13:54:54 +02:00
2f35ad6e65 Background: Drop "saturation" related source
"saturation" was removed from MetaBackground in mutter with
https://git.gnome.org/browse/mutter/commit/?id=0e589061
2013-09-18 13:49:35 +02:00
159c7d34c7 l10n: Update Japanese translation 2013-09-18 20:41:47 +09:00
fe8e990ed7 Punjabi Translation updated by Aman 2013-09-17 22:08:46 -05:00
1fb9b18cb6 Updated Belarusian translation. 2013-09-17 22:46:22 +03:00
5c2586127b Update gvc
A translator accidentally undid this.
2013-09-17 11:54:44 -04:00
661b266b45 Updated Esperanto translation
Reviewed by Ken Price
2013-09-17 10:11:50 -04:00
98af044196 Updated Romanian Translation 2013-09-17 09:55:18 +02:00
8006c336f5 Bump version to 3.9.92
Update NEWS.
2013-09-16 23:59:39 +02:00
bdf07d2ce8 Updated Greek translation 2013-09-16 22:38:25 +03:00
efcf858e60 Updated Hebrew translation 2013-09-16 21:55:49 +03:00
93d9c16672 appDisplay: Rework indicators animation
Previously the animation was not entirely according to the mockup.
Now we are closer to the mockup.

The padding for the indicators are decremented, since we need that
to make the animation not too quick. As a drawback, maybe visually
is not as good as before, or the area to click dots is too much little.
Just make that change for now and test it widely, and we can change
that after.

https://bugzilla.gnome.org/show_bug.cgi?id=707565
2013-09-16 18:49:24 +02:00
7aaf261f5a [l10n] Updated Italian translation. 2013-09-16 14:29:11 +02:00
5eb4450012 Updated Hungarian translation 2013-09-16 13:13:38 +02:00
49c8cdd8f6 a11y: check states EXPANDABLE/EXPANDED on PopupSubMenuMenuItem
https://bugzilla.gnome.org/show_bug.cgi?id=708038
2013-09-16 12:36:16 +02:00
c860b96a86 Updated Basque language 2013-09-15 15:39:35 +02:00
69403bda80 Updated slovak translation 2013-09-15 10:22:30 +02:00
f5456b66ff Updated slovak translation 2013-09-15 10:19:30 +02:00
28b4c413cb Updated slovak translation 2013-09-15 10:12:56 +02:00
5b97250bb1 Updated slovak translation 2013-09-15 10:09:03 +02:00
5d26c29eaa Updated slovak translation 2013-09-15 10:07:23 +02:00
613944eccd Update Kazakh translation 2013-09-15 14:00:57 +06:00
8d0e8fc021 Updated Polish translation 2013-09-15 01:22:01 +02:00
41ee70d414 Update Russian translation 2013-09-14 20:56:06 +02:00
3691e8ddd7 Remove "Menu" from the name of the Settings menu
Its presence makes Orca present "Settings Menu menu". Removing it does
not introduce any new strings.

https://bugzilla.gnome.org/show_bug.cgi?id=708080
2013-09-14 14:07:17 -04:00
be54e94045 Update French translation 2013-09-14 19:08:19 +02:00
366ca72342 Updated Danish translation 2013-09-14 15:55:57 +02:00
fc4e392ac1 Updated Danish translation 2013-09-13 22:03:50 +02:00
507be35d3a Updated Korean translation 2013-09-14 04:27:43 +09:00
5c0d62cd0e Updated German translation 2013-09-13 19:31:45 +02:00
7b7c4568b2 appDisplay: Change pages with page down/up keys
Add key bindings to app picker to allow change pages using
the page up/down keys.

https://bugzilla.gnome.org/show_bug.cgi?id=707979
2013-09-13 19:16:11 +02:00
f38091d96b appDisplay: Move boundary page assertions
Since the function that manages the changes between pages is
goToPage, just move the assertions of page >= 0 and page < nPages
to that function

https://bugzilla.gnome.org/show_bug.cgi?id=707979
2013-09-13 18:58:46 +02:00
7c78e1fbf5 appDisplay: Fix indicator animation position
The original position was calculated with the stage and the
transformed position of the indicator when mapped. The values
were wrong on some situations, so lets calculate the position
based on the dots width.

https://bugzilla.gnome.org/show_bug.cgi?id=707580
2013-09-13 18:15:33 +02:00
72f0a48fac theme: Erase appDisplay padding
Since now AllView doesn't have a scrollbar this
padding is not necesary, and will allow to place
the indicators correctly using only the indicators
padding in a upcoming patch.

https://bugzilla.gnome.org/show_bug.cgi?id=707580
2013-09-13 18:13:41 +02:00
193f872ebe Magnifier: don't initialize if we don't need it
Let's avoid initializing AT-SPI and start monitoring events if we
are not actually using the magnifier.

https://bugzilla.gnome.org/show_bug.cgi?id=708020
2013-09-13 16:09:33 +02:00
c3f96cf0e8 data: Fix make dist and conditionally install gnome-shell-wayland 2013-09-13 15:11:04 +02:00
df09109d81 overviewControls: Use a custom layout to catch all geometry changes
We currently update workspaces geometry when we are notified about
allocation changes of the overview group; however as the geometry
is based on stage coordinates, we miss notifications when the
allocation relative to the parent is unchanged, which happens when
the primary monitor's position changes but not its resolution.
Use a custom layout manager to give us a signal that is emitted
reliably.

https://bugzilla.gnome.org/show_bug.cgi?id=708009
2013-09-13 13:50:31 +02:00
662cb9e2a3 Updated Spanish translation 2013-09-13 12:49:59 +02:00
daa54a3798 Assamese Translation Updated 2013-09-13 15:10:33 +05:30
f035a1a0e0 Updated Galician translations 2013-09-13 10:28:22 +02:00
2688bf3333 Tajik translation updated 2013-09-13 13:14:07 +05:00
4095a58eb9 st-scroll-view-fade: Reduce number of GLSL uniforms and instructions
The vvalue and hvalue uniforms are only used to decide whether we
should do fade the edges or not based on the fade_edges uniform.
The result does not change accross fragments so there is no reason
to recompute it for every fragment (pixel) so just split the edge
fade into two uniforms and compute the "should we fade the edges"
boolean once for every direction (when setting the uniforms) instead
of for every single fragment twice.

This reduces the number of uniforms as well as the the number of instructions
which are limited on older hardware. It should also be more efficent.

https://bugzilla.gnome.org/show_bug.cgi?id=708007
2013-09-13 09:45:19 +02:00
c1b1ebe97e Updated Czech translation 2013-09-13 08:57:44 +02:00
a47b97d443 Updated Brazilian Portuguese translation 2013-09-12 23:02:30 -03:00
df5d5583eb lookingGlass: Fix position on multi-head
We currently assume that the primary monitor is located at (0, 0),
fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=707996
2013-09-13 00:03:24 +02:00
79e764d5ec Update .gitignore 2013-09-12 23:28:37 +02:00
2fcb04e5b2 Updated Lithuanian translation 2013-09-12 22:41:11 +03:00
da1e264687 dnd: Use sync_pointer rather than complex enter/leave tracking
https://bugzilla.gnome.org/show_bug.cgi?id=707940
2013-09-12 14:33:33 -04:00
03975287d2 Updated Slovenian translation 2013-09-12 20:30:32 +02:00
50a61b38f7 Updated Polish translation 2013-09-12 19:39:01 +02:00
1fe072471e Updated POTFILES.in 2013-09-12 19:36:37 +02:00
93e840295e Update .gitignore 2013-09-12 11:16:20 -04:00
6ab7d640f0 Updated British English translation 2013-09-12 14:38:32 +01:00
255cb8edb1 AppFolderPopup: fix the position of close buttons
We need to adjust the offset of close buttons, in case the box
pointer has the arrow at the top. To do so, extend close buttons
to hook into a boxpointer (since that's the common use for them)
and automatically adjust their position.

https://bugzilla.gnome.org/show_bug.cgi?id=707842
2013-09-12 14:33:35 +02:00
367fb32493 Updated Hungarian translation 2013-09-12 13:58:25 +02:00
ef6d1fd6ce Updated Hungarian translation 2013-09-12 13:42:27 +02:00
3e8ab0645b ScreenShield: fix a typo due to the MetaCursorTracker switch
And replace another show_cursor() usage with the new API.

Reviewed-by: Carlos Soriano in IRC.
2013-09-12 13:17:23 +02:00
135727c9f7 Add support for running wayland under gnome-session
Include a .desktop file that autostarts us as a wayland compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
c58448817b ShellGlobal: use MetaCursorTracker to query the pointer position
Gdk uses Xwayland, so it only sees the events we forward to X11
clients. Instead, we can use the abstraction API provided by
mutter and get the right value automatically.
Also, we need to use MetaCursorTracker to handle the cursor
visibility too.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
8ae0f1a9dc StEntry: add a hook to set the cursor from libgnome-shell
We need to call into MetaScreen to set the cursor, but we can't
do that from libst, so add a hook that libgnome-shell can fill,
and remove more ClutterX11 usage.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
ba9c1d98f6 ShellGlobal: use a different window for IBus when running on wayland
When running as a wayland compositor, the clutter stage doesn't
have an usable window for IPC, so just create another one.

Also, disable freezing the keyboard when running on wayland, as
we can't do it really.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
4db6e70f97 Disable XDND when running as a wayland compositor
We can't do xdnd on wayland easily, so let's disable this for 3.10

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
9d1f789937 ShellGlobal: repurpose the stage_gdk_window as the IBus window
And use it directly in the IBus event handling (by pushing it down
to StIMText)

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:25 +02:00
11c2933e23 ShellGlobal: remove cursor manipulation functions
Use the new API in MetaScreen instead, which is automatically
routed to MetaCursorTracker as appropriate.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-12 10:34:22 +02:00
fbd4951ea7 [l10n] Updated Estonian translation 2013-09-12 07:54:11 +03:00
744749f2f3 dnd: Remove the queue updated ID for completed drags as well
I thought that cancelDrag was called for completed drags as well,
but it's not. Move the updateHoverId source removal to dragComplete.

This fixes "this._dragActor is undefined" warnings after completed
drags.

https://bugzilla.gnome.org/show_bug.cgi?id=707935
2013-09-11 15:11:23 -04:00
db1c65970b Remove various E4X junk remove4x can't handle 2013-09-11 15:02:33 -04:00
2d8ed4c77f Bind "this" for various methods
For extremely silly reasons with how the class framework works, the wrapper
method requires "this" to be bound in order for it to work, or else we'll
emit errors in strict mode.

https://bugzilla.gnome.org/show_bug.cgi?id=707892
2013-09-11 15:02:32 -04:00
9ba970b83d lookingGlass: Fix newline replacing
text.replace() returns the new string as strings in JS are immutable.
2013-09-11 15:02:32 -04:00
954d262d67 st: Fix spacing on right icon in entry
https://bugzilla.gnome.org/show_bug.cgi?id=705779
2013-09-11 18:41:55 +02:00
1b6090fe13 Make the search entry behave better in RTL locales
It is expected that the primary and secondary icons in entries
change places in RTL locales. When doing so, the edit-clear
icon must be replaced by an rtl variant too.

http://bugzilla.gnome.org/show_bug.cgi?id=705779
2013-09-11 18:41:55 +02:00
f8234b07f8 workspacesView: Don't double-destroy workspaces
The WorkspaceView actors contain the Workspace actors, so destroying the
WorkspaceView actors should be enough.

https://bugzilla.gnome.org/show_bug.cgi?id=707889
2013-09-11 10:15:26 -04:00
25318f696d workspace: Clean up a leftover later_add on destroy
https://bugzilla.gnome.org/show_bug.cgi?id=707889
2013-09-11 10:15:26 -04:00
1ab3d12bc7 Finnish translation update 2013-09-11 09:46:44 +03:00
d66e0a0b45 Fix simple GTK+ deprecations 2013-09-10 20:43:17 -04:00
d46ceead04 Fix simple, unused variable warnings 2013-09-10 20:43:17 -04:00
1cc9480e56 Updated Latvian translation 2013-09-10 21:31:25 +03:00
c022b541f1 Updated Belarusian translation. 2013-09-10 20:02:46 +03:00
96588466d4 Don't pass on X events to Clutter
The Mutter plugin manager has now been changed so that it itself will
pass on the events through Clutter so there is no need to do this in
Gnome Shell anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=707467
2013-09-10 17:27:18 +02:00
dbde12f8bf Assamese Translation Updated 2013-09-10 20:47:49 +05:30
660f0fec16 popupMenu: Fix algorithm for separator visibility to work with sections
Before, separators naively checked whether their siblings were visible
using actor visibility. However, if section actors are visible but have
no visible children, this will fail. Special-case separators when doing
visiblity checks.

https://bugzilla.gnome.org/show_bug.cgi?id=707801
2013-09-10 10:23:43 -04:00
fd9401cc62 Revert "popupMenu: Make the section invisible if it has no visible children"
This reverts commit 5a0ac6c2ac.

https://bugzilla.gnome.org/show_bug.cgi?id=707801
2013-09-10 10:23:43 -04:00
1edb9f7525 altTab: Only create one settings instance per window switcher popup
Every settings instance we create is a round-trip to the dconf
daemon, so we need to be careful of not creating them too haphazardly.

https://bugzilla.gnome.org/show_bug.cgi?id=707806
2013-09-10 10:23:43 -04:00
15cfb9d1d9 AppMenu: remove tweens before animating the actor visibility
When we show(), we need to make sure that the hiding animation
doesn't reach the end, otherwise we would hide the actor but
still have _visible = true.
We were relying on tweener overwriting to do this, but it
doesn't quite work, so better be explicit and do it ourselves.

https://bugzilla.gnome.org/show_bug.cgi?id=707814
2013-09-10 10:46:00 +02:00
da6744da2d Updated Indonesian translation 2013-09-10 13:10:42 +07:00
bd5aa66a5f Update Arabic translation 2013-09-09 23:15:20 +02:00
7c30fe7738 Punjabi Translation updated by Aman 2013-09-09 14:09:40 -05:00
8ce599df38 theme: Change overview icon shadow inset opacity
In the commit 9a8bf3b was changed the background opacity of overview
icons. That cause that the shadow of the checked state of icons
was too hard, so it seems to be cut off.
Change the opacity of the shadow to solve this.
2013-09-09 13:37:36 +02:00
75fe13f1df Updated Serbian translation 2013-09-08 16:26:18 +02:00
8ad6ded3ec Tajik translation updated 2013-09-08 15:45:21 +05:00
38d22c47f5 Tajik translation updated 2013-09-08 15:42:31 +05:00
956b6b89b6 Tajik translation updated 2013-09-08 15:38:46 +05:00
f27c2e6813 Updated Norwegian bokmål translation 2013-09-08 11:23:16 +02:00
d35c9f880a Updated German translation 2013-09-08 08:14:10 +02:00
d62aacf301 Updated Russian translation 2013-09-07 23:11:29 +04:00
716ea64212 l10n: Update Japanese translation 2013-09-07 22:36:18 +09:00
c9d6b13f6a Remove unused functions
Bug https://bugzilla.gnome.org/show_bug.cgi?id=707666
2013-09-07 15:05:59 +02:00
b437e68026 app: Removed unused function
https://bugzilla.gnome.org/show_bug.cgi?id=707663
2013-09-07 00:09:31 +02:00
1dfc38d078 app: Stop using window visibility when comparing apps
shell_app_compare() (which is only used as sort function for
shell_app_system_get_running() nowadays) currently takes the
visibility of an app's windows into account, e.g. applications
with visible windows (non-minimized windows on current workspace)
sort earlier than applications without.
This translate traditional window-switcher behavior to applications,
but we stopped sorting by workspace in the app-switcher a while ago,
and with the new auto-minimization behavior of fullscreen windows
it is more confusing than helpful - in fact, since mutter commit
7e61ef09369a we no longer do this for the window list, so it
makes sense to apply the same to application sorting.

https://bugzilla.gnome.org/show_bug.cgi?id=707663
2013-09-07 00:09:31 +02:00
387184b052 appDisplay: Increase fade offset in FolderView
Just as we do in AllView, we set the offset of FolderViews' fade
effect so that no icon is faded when a full page is visible.
This works fine in AllView, however in the FolderView case where
the popup's offsets eat away from the available fade height, the
effect ends up being barely noticeable at all.
While it is not ideal to apply the fade to the edge of a "full page",
it looks less ugly than the current state, so pick the lesser evil ...

https://bugzilla.gnome.org/show_bug.cgi?id=707662
2013-09-06 23:54:46 +02:00
beec47d7ad theme: Decrease padding on folder view popup
If a folder view is scrolled, its scrollbar ends up too close to the
content (even partially overlapping it) with the current padding.
Making it much smaller fixes the issue without affecting the content
position - the removed padding will just move to IconGrid's dynamic
padding.

https://bugzilla.gnome.org/show_bug.cgi?id=707662
2013-09-06 23:54:46 +02:00
6b554337ff appDisplay: Make sure we don't clip folder view
If we round up the value, we make sure we don't clip in any
case neither the folder view or the close button.
2013-09-06 23:45:50 +02:00
08f95264d6 embedded-window: Set as app-paintable to workaround opaque region issues
In specific cases, GTK+ does not have enough information to set a correct
opaque region, in which the recommended fix is to set your window as
app-paintable. In the tray icon case, the socket window was considered
opaque but GTK+ as it had a solid window background, but it cannot have an
opaque region set, as the plug isn't composited against the socket, but
instead punches through the socket window.

https://bugzilla.gnome.org/show_bug.cgi?id=707614
2013-09-06 16:28:41 -04:00
2802920e93 Updated Italian translation 2013-09-06 22:15:53 +02:00
b04c47c15f focusCaretTracker: Minor cleanup 2013-09-06 19:14:53 +02:00
56d96383e2 st: Fix typo 2013-09-06 17:23:19 +02:00
f2cbf846e7 build: Fix linker errors on Debian/Ubuntu 2013-09-06 16:21:55 +02:00
0088e94293 Updated Czech translation 2013-09-06 11:55:01 +02:00
a03a077e3d Updated Czech translation 2013-09-06 11:50:44 +02:00
85d2b9e32a appDisplay: Also scroll on focused indicators
Since now if you focus the indicators, you can't scroll and
change pages in the app picker. That was reported as odd from
some users/developers.
So allow to scroll when the focus is in the indicators.

https://bugzilla.gnome.org/show_bug.cgi?id=707609
2013-09-06 10:40:07 +02:00
aa6471b3cc messageTray: Reset clickedSummaryItem on ungrab
If we don't, we will pop up the summary again the next time
_updateState() is called.

https://bugzilla.gnome.org/show_bug.cgi?id=707600
2013-09-06 10:16:37 +02:00
b462a85c43 appDisplay: Fix obvious copy+paste error 2013-09-06 02:58:15 +02:00
9d8f30f955 Magnifier: Implement focus and caret tracking
A11y users who use the magnifier may have trouble
focusing when they're typing or trying to keynav.
Implement a new system so that they can have the
magnifier track the caret and focus instead instead
of just the mouse.

Bug https://bugzilla.gnome.org/show_bug.cgi?id=647074
2013-09-05 13:18:54 -04:00
420db828e9 appDisplay: Also fade ScrollView in folders 2013-09-05 18:30:18 +02:00
fd8def705d appDisplay: Remove _updateAdjustment
Provided that PaginatedIconGrid's height request is correct, we
can rely on StBoxLayout to update the adjustment correctly.
2013-09-05 18:18:05 +02:00
39c4fa1bf0 iconGrid: Initialize properties in _init
While this is good style anyway, after the latest appDisplay changes
the first call to get_preferred_height() happens before we properly
compute those properties, resulting in a size request of NaN that
triggers a Clutter warning.
2013-09-05 18:18:05 +02:00
32b964e9b7 power: Fix translations in the power section
This technically isn't a string freeze break, since xgettext already
picked up the string and translators have been translating it.

https://bugzilla.gnome.org/show_bug.cgi?id=707557
2013-09-05 12:03:26 -04:00
2980515c85 appDisplay: Fix return value for _onScroll
ClutterActor::scroll-event has a boolean return value to indicate
whether the event has been handled, or event emission should continue.
Now that we are using an StScrollView, we depend on this to avoid
propagating the event to the view's own handler.

https://bugzilla.gnome.org/show_bug.cgi?id=707409
2013-09-04 23:52:19 +02:00
36bee16781 appDisplay: Use a ScrollView for pages
While we obviously don't want any scrollbars, its fade effect
will give us some extra polish when switching pages.

https://bugzilla.gnome.org/show_bug.cgi?id=707409
2013-09-04 23:52:19 +02:00
4f5d3e00db st: Add StScrollViewFade:fade-edges
Add a new property which controls whether edge areas are excluded
from the effect (the default and current behavior), or not.

https://bugzilla.gnome.org/show_bug.cgi?id=707409
2013-09-04 23:52:18 +02:00
6fb044f351 st: Make st_scroll_view_update_fade_effect() public
Using fixed fade offsets is not always appropriate, this will allow
to set them from code instead.

https://bugzilla.gnome.org/show_bug.cgi?id=707409
2013-09-04 23:52:18 +02:00
b403845d03 st: Make StScrollViewFade a ClutterShaderEffect
The cogl_shader_XXX and cogl_program_YYY APIs have been deprecated
this cycle, so port to ClutterShaderEffect instead.

https://bugzilla.gnome.org/show_bug.cgi?id=707508
2013-09-04 23:13:30 +02:00
9d0e00acce Updated slovak translation 2013-09-04 20:12:26 +02:00
d5afe8f4f2 Update gvc 2013-09-04 13:00:31 -04:00
3eb5ca3653 Updated Ukrainian 2013-09-04 18:47:00 +03:00
db07aa42ea panel: fix crash when bluetooth is disabled
https://bugzilla.gnome.org/show_bug.cgi?id=707430
2013-09-04 11:34:17 +02:00
081f51b9eb Finnish translation update 2013-09-04 11:04:49 +03:00
38d9c16aba gnome-shell.css: typo replace tabs with spaces 2013-09-04 09:48:07 +02:00
392a426ddf iconGrid: typo in iconGrid this._vItemSize to this._getVItemSize() 2013-09-04 09:43:10 +02:00
d77b2751a6 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2013-09-04 15:06:39 +08:00
3b28308291 Updated Polish translation 2013-09-04 02:08:10 +02:00
574ecb5ad4 Updated Italian translation 2013-09-04 00:42:12 +02:00
7a57a780d8 Updated Lithuanian translation 2013-09-04 00:34:30 +03:00
cf9842433e search: "pushed in" :active state
https://bugzilla.gnome.org/show_bug.cgi?id=704714
2013-09-03 17:19:53 +02:00
c6d089d701 build: Don't add version to private libgnome-shell-menu library 2013-09-03 16:17:06 +02:00
ec37e2d2b5 Updated Spanish translation 2013-09-03 16:10:59 +02:00
e68b648a33 appDisplay: Don't show page indicators if there's only one page
It doesn't make sense to show the indicators in that case, so
don't show them. This has been the design in the first place,
but the code that did that was lost at some point during review ...

https://bugzilla.gnome.org/show_bug.cgi?id=707363
2013-09-03 13:54:21 +02:00
56179d8a54 build: Fix building introspection for ShellRecorder
This is a regression from commit 21a85832b3, which resulted in
shell-recorder.[ch] not being included in gir generation.

https://bugzilla.gnome.org/show_bug.cgi?id=707308
2013-09-03 13:53:32 +02:00
47d232f694 Updated Galician translations 2013-09-03 12:57:20 +02:00
fc26fb2149 Updated Brazilian Portuguese translation 2013-09-02 21:06:47 -03:00
92d828b04e Bump version to 3.9.91
Update NEWS.
2013-09-03 01:45:04 +02:00
6f9dc913d4 Updated Slovenian translation 2013-09-02 23:01:58 +02:00
9ea0f7255f PageIndicators: extend the clickable area
Replace the inactive spacing with clickable padding inside the
buttons, for easier selection with a mouse.

https://bugzilla.gnome.org/show_bug.cgi?id=707314
2013-09-02 22:53:04 +02:00
938628a05f appDisplay: Default to All view when not enough usage data is available
The frequent view is not useful when it doesn't contain any applications
yet. While the previously added label makes this state appear less like
an error (OMG, my apps are gone!), it doesn't address the issue of
usefulness - default to the more helpful All view in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=694710
2013-09-02 21:26:11 +02:00
a765dfc52e appDisplay: Show label when frequent app view is empty.
Currently we show a empty view, that seems broken, so we add a label
showing that there's not enough frequent applications to show.

https://bugzilla.gnome.org/show_bug.cgi?id=694710
2013-09-02 21:25:03 +02:00
d58f0646cf iconGrid: Also adapt icon size to available space
Similar to adapting the spacing dynamically to the available
space we already do, scale down icon sizes if the grid is too
small to fit the requested minimum number of rows/columns.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
792b963bda iconGrid: Change IconGrid.addItem() to take an object instead of an actor
IconGrid has never really been a general purpose container, but has
always been used in conjunction with BaseIcon. IconGrid will soon
gain the ability to adjust the item size dynamically to adapt to the
available space, which will require that we can make some more
assumptions about the items added to the grid (namely: we need
access to BaseIcon's setIconSize() method).
So change addItem() to take an object instead, which should have
an actor and a (BaseIcon) icon property.

Based on a patch by Carlos Soriano.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
9a8bf3b881 theme: Change icons style to follow new design
Change the background, glow and labels of the Dash and AppDisplay
to follow the new design

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
1e02081cd2 appDisplay: Add pan action to FolderView
Since we have now a ScrollView in the FolderView,
add support for the pan action

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
3f24a87034 appDisplay: Make space on grid to fit collection when opening
Move icons out of the way to make place for the FolderView
popup before opening it.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
dd9f8021ff iconGrid: Add openExtraSpace()/closeExtraSpace() methods
Add methods to open/close extra space for n rows. The app picker
will use those to make AppFolder popups appear inline with the
main grid rather than on top of it.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:36:39 +02:00
74978e84f8 appDisplay: Start always at page 0 in AllView
Reset the AllView scroll adjustment between overview openings,
following design reasons

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:02:36 +02:00
6ef775390f appDisplay: Start always at scroll 0 on FolderView
Reset the scroll adjustment between popups opennings,
following the same design we want to the AllView

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 20:02:36 +02:00
1313c1b157 appDisplay: Align and contain collection grid with parent view
The popup of the FolderView is now contained inside
the parent view, solving the overflow of apps with a ScrollView.
Also, solved a lot of bugs in popup/FolderView calculation
of position and size.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:54:23 +02:00
6d6c400b25 iconGrid: Add padWithSpacing property
Add a property to also add the calculated spacing
around the grid.
This will allow FolderView to be aligned with the
main grid without cutting off any of the surrounding
boxPointer decorations or the close button

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:51:28 +02:00
46bd1b9b18 appDisplay: Add and rework pan action response
Add pan action to AllView and rework it to take
into account the velocity the user gives to the action

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:51:28 +02:00
dcea8bed6d appDisplay: Add page indicators
Add indicators to the pagination in AllView, which displays
how many pages of apps we have and allows the user to
navigate through them.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:51:00 +02:00
e8b35f4623 theme: Change app picker bottom padding
Increase the bottom padding between the views and the control buttons
of the AppDisplay to be more eye pleasant

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:47:05 +02:00
ae263bb4db iconGrid: Add minRows/minColumns properties
When we adapt the grid to different display sizes,
we don't want the number of displayed items to get
too small. In the future we will scale down icons to
make sure that the grid fits add least minRows
x minColumns items, but for now we only take the
properties into account when calculating the dynamic spacing.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:43:49 +02:00
754ca7c8f2 appDisplay: Paginate AllView
Organize applications in AllView by pages using the new PaginatedIconGrid
added previously. Pagination is generally a better pattern for collections
than scrolling, as it better suits spacial memory.
Hook into AppDisplay's allocation function to communicate the available
size to the different views before child allocations - this is only
required by the paginated view (as pages must be computed before
calling get_preferred_height/get_preferred_width), but doing it for
all views will guarantee that their dynamic spacing calculation is
based on the same values.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 19:06:35 +02:00
804c02701a appDisplay: Animate _updateIconOpacities
Animate the transition between full opacity and partly opacity
to follow overall animations design of gnome-shell

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
fbb4077812 appDisplay: Rename AlphabeticalView to BaseAppView
Since the items are not ordered in an alphabetical
way, just rename the class to be consistent.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
961e1b89a2 appDisplay: Move FolderView near FolderIcon for better context
Since FolderView is closely related with FolderIcon, we
have more context while working if FolderView is near
FolderIcon

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
cc449228f3 iconGrid: Rename childrenInRow to columnsForWidth
Since the parameter of the function is the width, reflect that in
the function name. Also, since we are counting columns, not only
children for each row, reflect that in the function name also.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
3984c47867 iconGrid: Add PaginatedIconGrid
The new PaginatedIconGrid class acts as a container for pages.
So the new class provides  the container behaviour and some
useful functions like positions of pages, number of pages, etc.
But, it doesn't add indicators of the pages and doesn't manage
the scroll of the pages, neither any management of the pages
like in which page currently it is, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
cfb80266c2 iconGrid: Move spacing calculation to its own function
Move spacing calculation to a function, which makes
it reusable and overwritable by subclasses

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
cc5198205d iconGrid: Split out _calculateChildBox
Split out the calculation of the child box in allocation function
to be reusable by subclasses and let the code be more modular

https://bugzilla.gnome.org/show_bug.cgi?id=706081
2013-09-02 18:57:36 +02:00
a27b44a3c2 NetworkAgent: use g_close() instead of GUnixInputStream
We created the input stream just to close the FD, but GLib has
a handy close() wrapper, so we can use that instead.

https://bugzilla.gnome.org/show_bug.cgi?id=707269
2013-09-02 18:45:07 +02:00
937d064860 Updated Spanish translation 2013-09-02 18:11:03 +02:00
9c814d1584 ShellDBus: add ShowApplications method
Add a method to control the visibility of the applications view.
This can used by gnome-settings-daemon for special keys in
certain keyboards.

https://bugzilla.gnome.org/show_bug.cgi?id=698743
2013-09-02 11:02:18 +02:00
415563dc6e Add a FocusApp method to org.gnome.Shell
This method, which accepts a .desktop filename, is used to highlight
a specific application in the overview, for example because it has
just been created or installed.

https://bugzilla.gnome.org/show_bug.cgi?id=654086
2013-09-02 10:51:00 +02:00
bed653737b Updated Belarusian translation. 2013-09-01 19:10:57 +03:00
b53be942d4 workspace: Make sure to sort the last row in the overview
We added special code to sort each row in the overview so that
windows were less likely to cross lines, but the awkward control
flow meant that everything but the last row got sorted.

https://bugzilla.gnome.org/show_bug.cgi?id=707197
2013-08-31 22:33:16 -04:00
1d26161d23 network: Adapt to the new NetworkManager API names
"physical connection" has been replaced with "primary connection"
2013-08-31 22:33:16 -04:00
39afb58472 windowManager: Don't open overview after closing the last window on a workspace
Activating the overview is fairly easy (hot corner, <super>), so doing it
automatically after closing the last window on a workspace does not save
a lot of effort; it does result in a surprising context switch when the
user does not expect the behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=662581
2013-08-31 23:53:39 +02:00
22cd18571b Updated Polish translation 2013-08-31 22:38:48 +02:00
5753eb6682 dash: Fix typo
Whoops, how did this make it through review?
2013-08-31 19:53:37 +02:00
e26a6ea71b dash: reload favorites when the installed app change
Force a reload of the favorite system, to pick apps that were
uninstalled.

https://bugzilla.gnome.org/show_bug.cgi?id=706878
2013-08-31 18:55:24 +02:00
6fbe765636 network: allow disconnecting while activation is in progress
While connecting, the item should read "Turn Off", not "Connect".
To do so, change the meaning of isActive() to be really "not isOff()"

https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
22b2ccd83d network: fix signal name
There is no state-changed signal on NMActiveConnection

https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
fc5aadd6dd network: use the VPN state to compute the icon for VPN items
We watch changes in the VPN state, not the active connection state,
so if we use the active connection state, we might miss an update
(because the VPN property is notified before the other one)

https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
5a9f0c24b4 network: don't return null from NMConnectionDevice._getStatus()
StLabel complains set you set the text to NULL

https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
0c12c072fa NMConnectionItem: fix typo
https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
f7284caefd network: don't crash because a device doesn't have a description yet
Descriptions are only added after all devices are read (thanks
to the disambiguation in libnm-gtk), but we use them immediately
when we call _sync() in various points (such as checkConnection())

https://bugzilla.gnome.org/show_bug.cgi?id=706262
2013-08-31 18:52:01 +02:00
4e7f317679 Update Kazakh translation 2013-08-31 19:49:03 +06:00
3534d6fddc Fix Catalan spelling mistakes 2013-08-30 21:38:19 +02:00
0b79e9cc9e loginDialog: Remove "Session" subtitle heading
It doesn't really add any value at all.

https://bugzilla.gnome.org/show_bug.cgi?id=707072
2013-08-30 10:45:46 -04:00
3ce97ccaa8 Updated Brazilian Portuguese translation 2013-08-30 11:08:02 -03:00
407a340b2b EndSessionDialog: don't show other logged in users at log out
We're not killing their session, so it's pointless to show them.

https://bugzilla.gnome.org/show_bug.cgi?id=707124
2013-08-30 15:59:13 +02:00
532346ecfb Updated Indonesian translation 2013-08-30 14:40:37 +07:00
cd25f5b6cb Updated Galician translations 2013-08-30 00:54:30 +02:00
5a0ac6c2ac popupMenu: Make the section invisible if it has no visible children
https://bugzilla.gnome.org/show_bug.cgi?id=706852
2013-08-29 15:17:12 -04:00
f0da08bbb1 system: Hide the AltSwitcher when we have nothing to show
https://bugzilla.gnome.org/show_bug.cgi?id=706852
2013-08-29 15:17:12 -04:00
fb3f6e2238 Update gvc 2013-08-29 14:49:24 -04:00
8b977252f3 loginDialog: show session menu button when in auth failed
Right now we only show the session menu button when verifying,
but we should also show it when verification is failed or we
can end up in situation where the session menu disappears during
an authentication retry.

https://bugzilla.gnome.org/show_bug.cgi?id=707064
2013-08-29 14:02:21 -04:00
9582f9b6e5 Updated Slovenian translation 2013-08-29 18:24:43 +02:00
3f15a41006 network: Use one notification globally for connection status
Rather than one per device.

https://bugzilla.gnome.org/show_bug.cgi?id=706098
2013-08-29 12:10:32 -04:00
e1c4cfd7eb network: Update for new APIs
New network manager APIs mean we don't have to do any scanning
through the active networks and synchronize state ourselves.

https://bugzilla.gnome.org/show_bug.cgi?id=706098
2013-08-29 12:10:32 -04:00
a326f40bbf Tajik translation updated 2013-08-29 11:19:42 +05:00
09c2fff8fc Updated Lithuanian translation 2013-08-28 23:32:03 +03:00
a4c1eb12b4 a11y: calendar: full date string should be navigable
Also moved the set of label_actor of the menu some lines before,
to improve readability.

https://bugzilla.gnome.org/show_bug.cgi?id=706903
2013-08-28 19:13:33 +02:00
4e80758970 a11y: calendar: Month name should be navigable
https://bugzilla.gnome.org/show_bug.cgi?id=706903
2013-08-28 16:23:09 +02:00
40ae408b3b a11y: calendar: add accessible name for next/prev month buttons
https://bugzilla.gnome.org/show_bug.cgi?id=706903
2013-08-28 16:23:05 +02:00
84d8d4f622 a11y: using generic accessible at slider
Needed in order to fill the AtkValue implementation using
signal callbacks (ala ShellGenericContainer).

https://bugzilla.gnome.org/show_bug.cgi?id=648623
2013-08-28 16:05:54 +02:00
5c04840312 a11y: add a generic accessible
Using the same idea that shell-generic-container. It implements
AtkValue with a dummy implementation based on signals. Javascript
code would connect to that and returns the proper value.

https://bugzilla.gnome.org/show_bug.cgi?id=648623
2013-08-28 16:05:54 +02:00
bd28d5c48a a11y: add the possibility to set the accessible object of a widget
In the common case, the accessible object is created by the
own widget. In some cases it is needed to specify a custom
accessible, as some of the logic will be implemented on the
javascript code (extend functionality using Components vs Hierarchy).

https://bugzilla.gnome.org/show_bug.cgi?id=648623
2013-08-28 16:05:54 +02:00
f176d890c0 Increase padding between system status icons
Makes the icons easier to read, and increases the size of the
click target a bit.

https://bugzilla.gnome.org/show_bug.cgi?id=706796
2013-08-28 14:36:50 +01:00
3b158a96b7 build: Ensure that we provide CFLAGS and LIBS for Wayland builds
We need to use PKG_CHECK_MODULES, not PKG_CHECK_EXISTS. We make it
non-fatal by passing a final argument to the m4 macro.
2013-08-28 11:12:23 +01:00
dcd0b2bf66 Tajik translation updated 2013-08-28 10:38:46 +05:00
edd1c89ea1 configure: Make wayland entirely optional 2013-08-27 23:59:16 -04:00
32d858dce3 configure: Remove a badly defined and unused variable 2013-08-27 23:59:16 -04:00
1e4bb53a34 Updated slovak translation 2013-08-27 22:44:51 +02:00
f5f94097bf Updated Norwegian bokmål translation 2013-08-27 20:19:55 +02:00
77a3218db3 Updated Spanish Translation 2013-08-27 19:48:08 +02:00
c3ed40905a Updated Spanish translation 2013-08-27 19:44:54 +02:00
268ac0bde8 theme: add bottom badding for login dialog hint
Since we're getting rid of the top padding, we need to add what we
take away to the bottom padding to keep the size the same.

https://bugzilla.gnome.org/show_bug.cgi?id=706670
2013-08-27 10:31:26 -04:00
88e3f6af47 authPrompt: give message label an initial style
This commit consolidates the styles of the various
message types into one 'login-dialog-message' style
and then adds additional styles on top to cover the
differences.

This allows us to give the message label an initial
style so that is padded properly before any messages
are displayed.

https://bugzilla.gnome.org/show_bug.cgi?id=706670
2013-08-27 10:20:16 -04:00
21a85832b3 Implementing building two separate binaries for x11 and wayland
Build gnome-shell for x11, and gnome-shell-wayland for wayland
(as well as the associated libgnome-shell and libgnome-shell-wayland).
The first one links to libmutter, the second to libmutter-wayland.

libgnome-shell and libgnome-shell-wayland are now compiled from
libgnome-shell-base (with all sources that are independent of mutter),
libgnome-shell-menu (with the copy-pasted gtk sources), plus the
sources that use mutter API

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-27 09:46:01 +02:00
254efdd122 Remove the jhbuild wrapper script
It's mostly equivalent to "jhbuild run gnome-shell", which is
the preferred way. Also, running from the source tree can't be
supported at this point, and the wrapper is getting in the way
of having two binaries, one for wayland and one for X11.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-27 09:46:01 +02:00
62ac6e74d9 Updated Galician translations 2013-08-27 02:55:06 +02:00
2c2268b39d gnome-shell-plugin: Fix unused variable warning 2013-08-26 20:06:34 -04:00
41aa14eaf0 gdm: Remove constraints from authPrompt / loginDialog as well
https://bugzilla.gnome.org/show_bug.cgi?id=706843
2013-08-26 19:05:15 -04:00
1f50f4658d unlockDialog: Remove clutter constraints from the code
These cause annoying allocation cycle warnings, and it's simpler to
just express our desired layout in terms of nested containers.
Adapt the theme to match as well.

https://bugzilla.gnome.org/show_bug.cgi?id=706843
2013-08-26 19:05:15 -04:00
d31481fd8b Updated Irish translation 2013-08-26 16:35:25 -06:00
80ab28bc3a loginDialog: Fade in the gdm auth prompt on login 2013-08-26 18:17:35 -04:00
48b7ebe1c0 loginDialog: Remove useless style class manipulation
StWidget already does this for us.
2013-08-26 18:17:35 -04:00
c59cf18337 loginDialog: Provide a finish method
The screenShield expects to be able to call finish on the dialog.
2013-08-26 18:04:20 -04:00
b7b1260540 screenShield: Don't fade in the lock dialog
We slide the shield over it, so the animation is rarely seen, and
since no other actor is under the lock screen, the not-cleared stage
can show through, causing weird issues when trying to blend.

https://bugzilla.gnome.org/show_bug.cgi?id=706841
2013-08-26 17:52:57 -04:00
897c5634b0 Fix autogen with latest gnome-common
Side-by-side use of IT_PROG_INTLTOOL and AM_GNU_GETTEXT is unsupported and breaks build.
2013-08-26 14:50:28 -06:00
78e3a05e14 Updated Lithuanian translation 2013-08-26 22:54:19 +03:00
1bb6367b79 schema: Remove some now unused gsettings keys 2013-08-26 13:42:11 -04:00
f5512ef21b Updated Brazilian Portuguese translation 2013-08-26 12:02:09 -03:00
a0fa9937ba Add a variant of the Restart dialog for offline updates
Detect when an offline update is pending, and show a more
suitable message in the Restart dialog.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:46:45 -04:00
ef2345ea85 system: Add a way to suspend from the system menu
When we implemented the new designs, we lost the ability to suspend
from the system menu. Re-enable this ability by re-adding the hidden
"Alt" shortcut item.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:02:44 -04:00
dd8fd09470 endSessionDialog: Split into two sections
https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:02:44 -04:00
a779e2aeca endSessionDialog: Don't stop the timer when we have inhibitors
https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:02:44 -04:00
aaaf25d578 endSessionDialog: Convert to the standard _sync pattern
... for starting and stopping the timer. This helps clean up the
state transitions in the code when caring about multiple things.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:02:44 -04:00
2e65c852c3 endSessionDialog: List other users and sessions in with the inhibitors
Instead of in a separate dialog. This does not meet the designs right
now, but it's a good first start.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-26 10:02:44 -04:00
1b206fe94c Dash: don't show a tooltip over an application with a popup menu
If the popup menu associated with the application icon is open,
make sure that the tooltip is hidden.

https://bugzilla.gnome.org/show_bug.cgi?id=705611
2013-08-26 13:52:49 +02:00
8b93c97a09 Update Kazakh translation 2013-08-25 22:08:57 +06:00
6247b55fc3 Updated German translation 2013-08-25 00:30:01 +02:00
12d9d49fa4 Updated Brazilian Portuguese translation 2013-08-23 21:26:10 -03:00
aef3f097e4 build: Switch to 3.10 moduleset 2013-08-23 23:40:03 +02:00
1a415d5fa7 userWidget: Actually respect the iconSize parameter
The iconSize parameter was only being respected if it was the
default icon fallback.

https://bugzilla.gnome.org/show_bug.cgi?id=706681
2013-08-23 13:25:11 -04:00
e4d46aee97 endSessionDialog: Remove the interactivity of the end session dialog
This was always sort of a hidden feature, and with the new designs
it's going to get unclear about what's clickable, and what's not.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-23 13:25:11 -04:00
d3a88e59b9 src: Eliminate compiler warnings 2013-08-23 12:34:42 -04:00
44e3811520 loginDialog: ask for username up front if disable-user-list==TRUE
Right now, we rely on PAM to ask for the username if disable-user-list
is TRUE.  This is suboptimal because it means we can't check if we
should show a session menu.

This commit changes disable-user-list==TRUE to ask for a username up
front, rather than have PAM do it.

https://bugzilla.gnome.org/show_bug.cgi?id=706607
2013-08-23 11:40:35 -04:00
e0574d2861 Replace GnomeIdleMonitor with MetaIdleMonitor
Now that GnomeIdleMonitor is a DBus API for mutter, we need to
use own in-process thing, to avoid dead locks.

https://bugzilla.gnome.org/show_bug.cgi?id=706005
2013-08-23 16:22:44 +02:00
d4f66da793 theme: small round button for system menu actions
- got freeze break from release team (2) and the docs team

https://bugzilla.gnome.org/show_bug.cgi?id=706638
2013-08-23 15:49:01 +02:00
c7e3289396 ScreenShield: hide the lightboxes when resuming from suspend
We show a lightbox when we suspend, to animate the fading to black
caused by turning off the monitors, but we need to hide it when
coming back, otherwise the user is just staring at a black screen
it until he moves the mouse or presses a key.

https://bugzilla.gnome.org/show_bug.cgi?id=706654
2013-08-23 14:21:02 +02:00
9cb7aeb32d Tajik translation updated 2013-08-23 12:48:11 +05:00
4537370a54 Updated POTFILES.in 2013-08-23 00:23:25 +02:00
9d2bc1142f endSessionDialog: Fix syntax error
That's what I get for not testing my changes before I push :(
2013-08-22 17:27:47 -04:00
c44caa5c96 endSessionDialog: Don't error out if gnome-session hands us a dead inhibitor
Sometimes gnome-session hands us a bad object path for JIT inhibitors
it creates for XSMP clients. While this is a bug in gnome-session, we
shouldn't show an empty-looking dialog here.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-22 17:16:38 -04:00
77dc587686 endSessionDialog: Fix a warning
If _timerId is undefined/null, as it is by default, we will take this
path, and fail when trying to remove a source ID for undefined.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-22 17:15:03 -04:00
ce768241da loginManager: Remove login manager versions of PowerOff/Reboot
These don't go through gnome-session, so they don't properly update
its state machine. We should use these in the future when we want to
use logind user sessions, but for now, they're just a trap.

https://bugzilla.gnome.org/show_bug.cgi?id=706612
2013-08-22 16:40:52 -04:00
5f9e50175f loginDialog: add support for auth without username / fix Not Listed?
commit 93f072d1fc attempted to
add support for auth without a username to the login screen, but
do to a messed up rebase only partially added it.

This commit fixes that.

https://bugzilla.gnome.org/show_bug.cgi?id=706607
2013-08-22 15:40:55 -04:00
34ec457a47 popupMenu: Fix indentation and style 2013-08-22 14:09:04 -04:00
dd1651f2d1 Setting proper name and role for system menu sliders
https://bugzilla.gnome.org/show_bug.cgi?id=706391
2013-08-22 17:18:33 +02:00
c3c529b001 Merge branch 'menu-arrow' 2013-08-22 16:37:40 +02:00
aa569304bc Fix key navigation on system menu sliders
Rely key press events management if the menu item contains
a slider.

https://bugzilla.gnome.org/show_bug.cgi?id=706386
2013-08-22 16:02:35 +02:00
3d57fd3227 slider: fix wrong variable name for own actor
https://bugzilla.gnome.org/show_bug.cgi?id=706386
2013-08-22 16:02:35 +02:00
c18a6a6577 theme: darken open submenu items
- avoid the clash of adjacent open and selected items

https://bugzilla.gnome.org/show_bug.cgi?id=706037
2013-08-22 15:42:49 +02:00
9720301d01 gdmUtil: make _startService support no username
commit fd11ad95f6 factored
out duplicated code, but unintentionally dropped support
for beginning verification without a username.

This commit brings it back.

https://bugzilla.gnome.org/show_bug.cgi?id=706542
2013-08-22 09:40:51 -04:00
5ea75499fe objectManager: fix indentation 2013-08-22 09:40:12 -04:00
b45bbb77ef theme: don't do harsh gradients for submenus
- use a more flat gradient for submenus. nothing is as curved
  and it doesn't help legibility.

https://bugzilla.gnome.org/show_bug.cgi?id=706037
2013-08-22 15:38:29 +02:00
d29b86baf0 objectManager: clear inhibitor on unregistered interfaces
A D-Bus service can export more supported interfaces than the
shell cares about.  In those cases, we avoid creating proxies,
but neglect to finish things up so the object manager class
knows it can mark itself loaded.

This commit makes sure we do the proper finishing, so the object
manager still loads in the face of unsupported interfaces.

https://bugzilla.gnome.org/show_bug.cgi?id=706542
2013-08-22 09:38:15 -04:00
1730aff2b9 Updated Norwegian bokmål translation 2013-08-22 15:21:22 +02:00
1b03484b04 Updated Polish translation 2013-08-22 02:16:10 +02:00
148 changed files with 33133 additions and 34802 deletions

5
.gitignore vendored
View File

@ -19,6 +19,8 @@ configure
data/50-gnome-shell-*.xml
data/gnome-shell.desktop
data/gnome-shell.desktop.in
data/gnome-shell-wayland.desktop
data/gnome-shell-wayland.desktop.in
data/gnome-shell-extension-prefs.desktop
data/gnome-shell-extension-prefs.desktop.in
data/gschemas.compiled
@ -71,13 +73,14 @@ src/calendar-server/evolution-calendar.desktop.in
src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell
src/gnome-shell-calendar-server
src/gnome-shell-extension-tool
src/gnome-shell-extension-prefs
src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer
src/gnome-shell-jhbuild
src/gnome-shell-perf-helper
src/gnome-shell-perf-tool
src/gnome-shell-real
src/gnome-shell-wayland
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
src/run-js-test
src/test-recorder

166
NEWS
View File

@ -1,3 +1,169 @@
3.10.1
======
* Make sure lock screen is drawn once before switching user [Giovanni; #708051]
* Fix signal strength indicators in network selector [Jasper; #708442]
* Scroll search results when focusing provider icons [Jasper; #708868]
* Add separate hover/active states to page indicators [Carlos; #708852]
* Tweak appearance of user name and avatar [Yash; #702309]
* Hide "Turn On" in network menu when disabled by hardware [Giovanni; #709635]
* Cancel open keyring prompts when the screen is locked [Florian; #708910]
* Differentiate "Not Connected" and "Off" in network menu [Giovanni; #709043]
* Make network settings items point to the right device [Giovanni; #709246]
* Remove animation of window preview titles [Sebastien; #709392]
* Add 'Notifications' switch to tray menu [Florian; #707073]
* Make dropdown arrows consistent [Carlos; #709564]
* power: Use icon from primary device for status [Jasper; #709925]
* Fix XDND drags to overview [Adel; #708887]
* Fix workspace switcher disappearing with too many workspaces [Jasper; #694881]
* Handle search results with 'special:' prefix specially [Giovanni; #707055]
* gdm: Support pre-authenticated logins from oVirt [Vinzenz; #702162]
* Use ARROW role for labels representing arrows [Alejandro; #710120]
* Make selected view in app picker persistent [Florian; #710042]
* Make network selector navigable by keyboard [Alejandro; #710144]
* Misc bug fixes [Florian, Adel, Jasper, Aleksander, Giovanni, Dan, Michael,
Tim; #709034, #709263, #698486, #709286, #709248, #709543, #696564, #703265,
#709638, #709866, #709998, #710019, #710104, #710115]
Contributors:
Giovanni Campagna, Michael Catanzaro, Vinzenz Feenstra, Adel Gadllah,
Yash Girdhar, Sebastien Lafargue, Tim Lunn, Aleksander Morgado,
Florian Müllner, Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre,
Dieter Verfaillie, Dan Winship
Translations:
Inaki Larranaga Murgoitio [eu], Christian Kirbach [de], Muhammet Kara [tr],
Aurimas Černius [lt], Ryan Lortie [eo], Rūdolfs Mazurs [lv],
Dušan Kazik [sk], Fran Diéguez [gl], Enrico Nicoletto [pt_BR],
Kjartan Maraas [nb], Victor Ibragimov [tg], Matej Urbančič [sl],
A S Alam [pa], Nilamdyuti Goswami [as], Daniel Mustieles [es],
Cheng-Chia Tseng [zh_HK, zh_TW], Mattias Põldaru [et], Kenneth Nielsen [da],
Milo Casagrande [it], Marek Černocký [cs], Ihar Hrachyshka [be],
Мирослав Николић [sr, sr@latin], Arash Mousavi [fa], Yuri Myasoedov [ru],
Gil Forcada [ca], Carles Ferrando [ca@valencia], Andika Triwidada [id],
Timo Jyrinki [fi], Piotr Drąg [pl], Rafael Ferreira [pt_BR],
Gabor Kelemen [hu], Yosef Or Boczko [he], Daniel Korostil [uk],
Wouter Bolsterlee [nl], António Lima [pt]
3.10.0.1
=========
* Fix login screen [Ray; #708691]
Contributors:
Ray Strode, Giovanni Campagna, Jasper St. Pierree
Translations:
Kjartan Maraas [nb], Marek Černocký [cs], A S Alam [pa], Daniel Mustieles [es],
Ihar Hrachyshka [be], Chao-Hsiung Liao [zh_HK], Nilamdyuti Goswami [as],
Yuri Myasoedov [ru], Baurzhan Muftakhidinov [kk]
3.10.0
======
* Fix fade effect in ScrollViews [Carlos; #708256]
* network: Resync when activating connection changes [Jasper; #708322]
* Close run dialog when the screen locks [Florian; #708218]
* Fix entry growing out of password dialogs [Florian; #708324, #703833]
* Vertically center labels in submenu items [Jasper; #708330]
* https://bugzilla.gnome.org/show_bug.cgi?id=708387 [Mike; #708387]
* Fix bluetooth icon not being added to status menu [Jasper; #708541]
* Fix GNOME 2 keyring dialogs appearing on lock screen [Florian; #708187]
* Fix passwords being cleared twice when authentication fails [Florian; #708186]
* Fix message tray appearing in a11y popup on login screen [Florian; #708380]
* Increase width of aggregate menu popup [Adel; #708472]
Contributors:
Adel Gadllah, Mike Gorse, Ryan Lortie, Florian Müllner, Frédéric Péters,
Carlos Soriano, Jasper St. Pierre, Rico Tzschichholz
Translations:
Daniel Șerbănescu [ro], Ryan Lortie [eo], Ihar Hrachyshka [be],
A S Alam [pa], Jiro Matsuzawa [ja], Chao-Hsiung Liao [zh_HK, zh_TW],
Piotr Drąg [pl], Kristjan SCHMIDT [eo], Daniel Korostil [uk],
Rūdolfs Mazurs [lv], Reinout van Schouwen [nl], Yosef Or Boczko [he],
Fran Diéguez [gl], António Lima [pt], Andika Triwidada [id],
Alexandre Franke [fr], Rafael Ferreira [pt_BR], Milo Casagrande [it],
Kenneth Nielsen [da], Matej Urbančič [sl]
3.9.92
======
* Don't show page indicators if there's only one page [Florian; #707363]
* Make :active style of app and non-app results consistent [Jakub; #704714]
* Fade app pages when scrolled [Florian; #707409]
* Don't block scrolling on page indicators [Carlos; #707609]
* Tweak visual appearance of folder views [Florian; #707662]
* Don't put minimized apps at the end of the app switcher [Florian; #707663]
* Merge the wayland branch [Giovanni, Neil; #707467]
* Make search entry behave better in RTL locales [Matthias, Florian; #705779]
* Allow to change app pages with pageUp/pageDown keys [Carlos; #707979]
* Set approriate a11y states on expandable menu items [Alejandro; #708038]
* Improve page indicator animation [Carlos; #707565]
* Misc bug fixes and cleanups [Florian, Olivier, Jasper, Giovanni, Magdalen,
Adel, Carlos, Rico, Joanmarie; #707308, #707430, #707508, #707557, #707600,
#707614, #707666, #707814, #707806, #707801, #707889, #707892, #707935,
#707842, #707940, #707996, #708007, #708009, #708020, #707580, #708080]
Contributors:
Magdalen Berns, Olivier Blin, Giovanni Campagna, Matthias Clasen,
Joanmarie Diggs, Adel Gadllah, Florian Müllner, Alejandro Piñeiro,
Neil Roberts, Carlos Soriano, Jasper St. Pierre, Jakub Steiner,
Rico Tzschichholz
Translations:
Rafael Ferreira [pt_BR], Fran Diéguez [gl], Daniel Mustieles [es],
Aurimas Černius [lt], Luca Ferretti [it], Piotr Drąg [pl],
Chao-Hsiung Liao [zh_HK, zh_TW], Timo Jyrinki [fi], Daniel Korostil [uk],
Dušan Kazik [sk], Adam Matoušek [cs], Marek Černocký [cs],
Jiro Matsuzawa [ja], Yuri Myasoedov [ru], Tobias Endrigkeit [de],
Kjartan Maraas [nb], Victor Ibragimov [tg], Мирослав Николић [sr, sr@latin],
A S Alam [pa], Khaled Hosny [ar], Andika Triwidada [id],
Nilamdyuti Goswami [as], Ihar Hrachyshka [be], Rūdolfs Mazurs [lv],
Mattias Põldaru [et], Gabor Kelemen [hu], Bruce Cowan [en_GB],
Matej Urbančič [sl], Enrico Nicoletto [pt_BR], Benjamin Steinwender [de],
Changwoo Ryu [ko], Kris Thomsen [da], Alexandre Franke [fr],
Evgeny Bobkin [ru], Baurzhan Muftakhidinov [kk], Peter Mráz [sk],
Inaki Larranaga Murgoitio [eu], Yosef Or Boczko [he]
3.9.91
======
* Improve submenu styling [Jakub; #706037]
* Fix changing slider values via keyboard [Alejandro; #706386]
* Fix accessibility of sliders [Alejandro; #706391]
* Tweak system actions style [Jakub; #706638]
* Add support for auth without username / fix Not Listed? [Ray; #706607]
* Dash: Don't show tooltips for apps with open popups [Giovanni; #705611]
* Implement new end-session/power-off dialog design [Jasper, Matthias; #706612]
* Implement building separate binaries for x11 and wayland [Giovanni; #705497]
* authPrompt: Fix controls moving when showing messages [Ray; #706670]
* Tweak padding between system status icons [Allan; #706796]
* Add a generic accessible usable by JS code [Alejandro; #648623]
* Improve keynav and accessibility of the calendar [Alejandro; #706903]
* Update to new NetworkManager APIs [Jasper; #706098]
* Hide system actions section in the lock screen [Jasper; #706852]
* Don't show other logged in users at log out [Giovanni; #707124]
* Remove "Session" subtitle heading in login dialog [Jasper; #707072]
* dash: Reload favorites when installed apps change [Giovanni; #706878]
* Don't open overview after closing last window on workspace [Florian; #662581]
* Add FocusApp DBus method [Giovanni; #654086]
* Add ShowApplications DBus method [Giovanni; #698743]
* Implement new app picker design [Carlos, Florian; #706081]
* Improve frequent apps being empty by default [Carlos, Florian; #694710]
* Extend clickable area of page indicators [Giovanni; #707314]
* Misc bug fixes [Ray, Giovanni, Jasper, Emmanuele; #706542, #706654, #706005,
#706681, #706841, #706843, #707064, #706262, #707197, #707269]
Contributors:
Emmanuele Bassi, Giovanni Campagna, Matthias Clasen, Allan Day, Adel Gadllah,
Florian Müllner, Alejandro Piñeiro, Carlos Soriano, Jasper St. Pierre,
Jakub Steiner, Ray Strode, Seán de Búrca
Translations:
Piotr Drąg [pl], Kjartan Maraas [nb], Victor Ibragimov [tg],
Enrico Nicoletto [pt_BR], Benjamin Steinwender [de],
Baurzhan Muftakhidinov [kk], Aurimas Černius [lt], Seán de Búrca [ga],
Fran Diéguez [gl], Daniel Mustieles [es], Dušan Kazik [sk],
Matej Urbančič [sl], Andika Triwidada [id], Jordi Mas [ca],
Ihar Hrachyshka [be]
3.9.90
======
* workspaceThumbnails: Exclude transient windows when shifting workspaces

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.9.90],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.10.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -24,9 +24,6 @@ LT_INIT([disable-static])
# i18n
IT_PROG_INTLTOOL([0.40])
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.17])
GETTEXT_PACKAGE=gnome-shell
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
@ -62,8 +59,8 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.13.4
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.35.4
MUTTER_MIN_VERSION=3.9.90
GJS_MIN_VERSION=1.38.1
MUTTER_MIN_VERSION=3.10.1
GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3
@ -78,26 +75,35 @@ NETWORKMANAGER_MIN_VERSION=0.9.8
PULSE_MIN_VERS=2.0
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0
libmutter >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
$recorder_modules
gdk-x11-3.0 libsoup-2.4
xtst
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
libcanberra libcanberra-gtk3
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION)
SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0
gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
$recorder_modules
gdk-x11-3.0 libsoup-2.4
xtst
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0 >= $STARTUP_NOTIFICATION_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
libcanberra libcanberra-gtk3
telepathy-glib >= $TELEPATHY_GLIB_MIN_VERSION
polkit-agent-1 >= $POLKIT_MIN_VERSION
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION"
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
PKG_CHECK_MODULES(MUTTER_WAYLAND, [libmutter-wayland >= $MUTTER_MIN_VERSION],
[MUTTER_WAYLAND_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter-wayland`
AC_SUBST(MUTTER_WAYLAND_TYPELIB_DIR)
have_mutter_wayland=yes],
[have_mutter_wayland=no])
AM_CONDITIONAL(HAVE_MUTTER_WAYLAND, test $have_mutter_wayland != no)
PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
@ -133,8 +139,9 @@ AC_SUBST([GNOME_KEYBINDINGS_KEYSDIR])
GOBJECT_INTROSPECTION_CHECK([$GOBJECT_INTROSPECTION_MIN_VERSION])
MUTTER_GIR_DIR=`$PKG_CONFIG --variable=girdir libmutter`
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
AC_SUBST(MUTTER_GIR_DIR)
MUTTER_TYPELIB_DIR=`$PKG_CONFIG --variable=typelibdir libmutter`
AC_SUBST(MUTTER_TYPELIB_DIR)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
@ -174,10 +181,6 @@ AM_CONDITIONAL(ENABLE_MAN, test "$enable_man" != no)
GNOME_COMPILE_WARNINGS([error])
AC_ARG_ENABLE(jhbuild-wrapper-script,
AS_HELP_STRING([--enable-jhbuild-wrapper-script],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])

View File

@ -3,6 +3,10 @@ dist_wanda_DATA = wanda.png
desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_MUTTER_WAYLAND
desktop_DATA += gnome-shell-wayland.desktop
endif HAVE_MUTTER_WAYLAND
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
@ -41,6 +45,10 @@ dist_theme_DATA = \
theme/message-tray-background.png \
theme/more-results.svg \
theme/noise-texture.png \
theme/page-indicator-active.svg \
theme/page-indicator-inactive.svg \
theme/page-indicator-checked.svg \
theme/page-indicator-hover.svg \
theme/panel-button-border.svg \
theme/panel-button-highlight-narrow.svg \
theme/panel-button-highlight-wide.svg \
@ -81,6 +89,7 @@ convert_DATA = gnome-shell-overrides.convert
EXTRA_DIST = \
gnome-shell.desktop.in.in \
gnome-shell-wayland.desktop.in.in \
gnome-shell-extension-prefs.desktop.in.in \
$(introspection_DATA) \
$(menu_DATA) \
@ -90,6 +99,7 @@ EXTRA_DIST = \
CLEANFILES = \
gnome-shell.desktop.in \
gnome-shell-wayland.desktop.in \
gnome-shell-extension-prefs.in \
$(desktop_DATA) \
$(keys_DATA) \

View File

@ -0,0 +1,15 @@
[Desktop Entry]
Type=Application
_Name=GNOME Shell (wayland compositor)
_Comment=Window management and application launching
Exec=@bindir@/mutter-launch -- gnome-shell-wayland --wayland
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@
Categories=GNOME;GTK;Core;
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-Phase=DisplayServer
X-GNOME-Autostart-Notify=true
X-GNOME-AutoRestart=false

View File

@ -37,6 +37,13 @@
application view, rather than being displayed inline in the main view.
</_description>
</key>
<key name="app-picker-view" type="u">
<default>0</default>
<summary>App Picker View</summary>
<description>
Index of the currently selected view in the application picker.
</description>
</key>
<key name="command-history" type="as">
<default>[]</default>
<_summary>History for command (Alt-F2) dialog</_summary>
@ -45,16 +52,6 @@
<default>[]</default>
<_summary>History for the looking glass dialog</_summary>
</key>
<key name="saved-im-presence" type="i">
<default>1</default>
<_summary>Internally used to store the last IM presence explicitly set by the user. The
value here is from the TpConnectionPresenceType enumeration.</_summary>
</key>
<key name="saved-session-presence" type="i">
<default>0</default>
<_summary>Internally used to store the last session presence status for the user. The
value here is from the GsmPresenceStatus enumeration.</_summary>
</key>
<key name="always-show-log-out" type="b">
<default>false</default>
<_summary>Always show the 'Log out' menuitem in the user menu.</_summary>
@ -226,10 +223,10 @@ value here is from the GsmPresenceStatus enumeration.</_summary>
<key name="focus-change-on-pointer-rest" type="b">
<default>true</default>
<summary>Delay focus changes in mouse mode until the pointer stops moving</summary>
<description>
<_summary>Delay focus changes in mouse mode until the pointer stops moving</_summary>
<_description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</_description>
</key>
</schema>
</schemalist>

View File

@ -157,17 +157,17 @@ StScrollBar StButton#vhandle:active {
min-width: 200px;
}
.popup-submenu-menu-item-triangle {
.unicode-arrow {
font-size: 120%;
}
.popup-submenu-menu-item:open {
background-color: #4c4c4c;
background-color: #333333;
}
.popup-sub-menu {
background-gradient-start: rgba(80,80,80,0.3);
background-gradient-end: rgba(80,80,80,0.7);
background-gradient-end: rgba(80,80,80,0.4);
background-gradient-direction: vertical;
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.9);
}
@ -633,15 +633,16 @@ StScrollBar StButton#vhandle:active {
.panel-status-indicators-box,
.panel-status-menu-box {
spacing: 8px;
spacing: 2px;
}
.system-status-icon {
icon-size: 1.09em;
padding: 0 5px;
}
.aggregate-menu {
width: 340px;
width: 360px;
}
.aggregate-menu .popup-menu-icon {
@ -655,18 +656,27 @@ StScrollBar StButton#vhandle:active {
.system-menu-action {
color: #e6e6e6;
border-radius: 4px;
padding: 6px;
border-radius: 32px; /* wish we could do 50% */
padding: 13px;
border: 1px solid #5f5f5f; /* using rgba() is flaky unfortunately */
}
.system-menu-action:hover,
.system-menu-action:focus {
color: white;
background-color: rgba(255,255,255,0.1);
background-color: #4c4c4c;
border: none;
padding: 14px;
}
.system-menu-action:active {
color: black;
background-color: #6f6f6f;
}
.system-menu-action > StIcon {
icon-size: 32px;
icon-size: 16px;
}
.screencast-indicator {
@ -683,7 +693,9 @@ StScrollBar StButton#vhandle:active {
padding-bottom: 32px;
}
.workspace-thumbnails-background {
.workspace-thumbnails {
spacing: 11px;
visible-width: 32px; /* Amount visible before hovering */
border: 1px solid rgba(128, 128, 128, 0.4);
border-right: 0px;
border-radius: 9px 0px 0px 9px;
@ -691,18 +703,13 @@ StScrollBar StButton#vhandle:active {
padding: 11px 7px 11px 11px;
}
.workspace-thumbnails-background:rtl {
.workspace-thumbnails:rtl {
border-right: 1px;
border-left: 0px;
border-radius: 0px 9px 9px 0px;
padding: 11px 11px 11px 7px;
}
.workspace-thumbnails {
spacing: 11px;
visible-width: 32px; /* Amount visible before hovering */
}
.workspace-thumbnail-indicator {
border: 4px solid rgba(255,255,255,0.7);
border-radius: 4px;
@ -898,9 +905,9 @@ StScrollBar StButton#vhandle:active {
/* Application Launchers, Grid and List results */
.icon-grid {
spacing: 36px;
-shell-grid-horizontal-item-size: 118px;
-shell-grid-vertical-item-size: 118px;
spacing: 30px;
-shell-grid-horizontal-item-size: 136px;
-shell-grid-vertical-item-size: 136px;
}
.icon-grid .overview-icon {
@ -908,7 +915,6 @@ StScrollBar StButton#vhandle:active {
}
.app-display {
padding: 8px;
spacing: 20px;
}
@ -924,12 +930,39 @@ StScrollBar StButton#vhandle:active {
padding: 3px 31px;
}
.search-display > StBoxLayout,
.all-apps > StBoxLayout,
.all-apps,
.frequent-apps > StBoxLayout {
/* horizontal padding to make sure scrollbars or dash don't overlap content */
padding: 0px 88px;
padding: 0px 88px 10px 88px;
}
.page-indicator {
padding: 15px 20px;
}
.page-indicator .page-indicator-icon {
width: 18px;
height: 18px;
background-image: url(page-indicator-inactive.svg);
}
.page-indicator:hover .page-indicator-icon {
background-image: url(page-indicator-hover.svg);
}
.page-indicator:active .page-indicator-icon {
background-image: url(page-indicator-active.svg);
}
.page-indicator:checked .page-indicator-icon,
.page-indicator:checked:active .page-indicator-icon {
background-image: url(page-indicator-checked.svg);
}
.no-frequent-applications-label {
font-size: 18pt;
color: #999999;
}
.app-folder-icon {
@ -961,13 +994,21 @@ StScrollBar StButton#vhandle:active {
background-image: url("more-results.svg");
}
.app-well-app > .overview-icon.overview-icon-with-label,
.grid-search-result .overview-icon.overview-icon-with-label {
/* since the label controls its own spacing, it is visually more
consistent to use different padding values for top and bottom */
padding: 10px 8px 5px 8px;
spacing: 4px;
}
.app-well-app > .overview-icon,
.show-apps > .overview-icon,
.search-provider-icon,
.list-search-result,
.grid-search-result .overview-icon {
border-radius: 4px;
padding: 3px;
padding: 6px;
border: 1px rgba(0,0,0,0);
transition-duration: 100ms;
text-align: center;
@ -979,13 +1020,13 @@ StScrollBar StButton#vhandle:active {
.app-folder-popup {
-arrow-border-radius: 8px;
-arrow-background-color: black;
-arrow-background-color: rgba(0,0,0,0.3);
-arrow-base: 24px;
-arrow-rise: 11px;
}
.app-folder-popup-bin {
padding: 15px;
padding: 5px;
}
.app-well-app.running > .overview-icon {
@ -995,7 +1036,7 @@ StScrollBar StButton#vhandle:active {
}
.app-well-app.app-folder > .overview-icon {
background-color: rgba(0,0,0,0.5);
background-color: rgba(0,0,0,0.3);
}
.app-well-app:hover > .overview-icon,
@ -1010,7 +1051,7 @@ StScrollBar StButton#vhandle:active {
}
.app-display .app-well-app > .overview-icon {
border-radius: 10px;
border-radius: 4px;
}
.list-search-result:hover .list-search-result-description {
@ -1032,12 +1073,14 @@ StScrollBar StButton#vhandle:active {
.app-well-app:checked > .overview-icon,
.app-well-app:active > .overview-icon,
.show-apps:checked > .overview-icon,
.show-apps:active > .overview-icon {
.show-apps:active > .overview-icon,
.search-provider-icon:active,
.list-search-result:active {
background-gradient-start: rgba(255, 255, 255, .05);
background-gradient-end: rgba(255, 255, 255, .15);
background-gradient-direction: vertical;
border-radius: 4px;
box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 1);
box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.7);
transition-duration: 100ms;
}
@ -1202,6 +1245,10 @@ StScrollBar StButton#vhandle:active {
padding-top: 8px;
}
.calendar-month-label:focus {
background-color: #999999;
}
.calendar-change-month-back {
width: 18px;
height: 12px;
@ -1247,6 +1294,10 @@ StScrollBar StButton#vhandle:active {
color: #eeeeec;
}
.datemenu-date-label:focus {
background-color: #999999;
}
.calendar-day-base {
font-size: 9pt;
text-align: center;
@ -1617,7 +1668,7 @@ StScrollBar StButton#vhandle:active {
}
.chat-notification-scrollview{
max-height: 22em;
max-height: 22em;
}
.subscription-message {
@ -1875,6 +1926,10 @@ StScrollBar StButton#vhandle:active {
spacing: 42px;
}
.end-session-dialog-list {
padding-top: 20px;
}
.end-session-dialog-subject {
padding-left: 17px;
padding-bottom: 20px;
@ -1908,50 +1963,30 @@ StScrollBar StButton#vhandle:active {
height: 32px;
}
.end-session-dialog-app-list {
font-size: 10pt;
.end-session-dialog-inhibitor-layout {
spacing: 16px;
max-height: 200px;
padding-top: 42px;
padding-left: 49px;
padding-right: 32px;
padding-right: 50px;
padding-left: 50px;
}
.end-session-dialog-app-list:rtl {
padding-right: 49px;
padding-left: 32px;
.end-session-dialog-list-header {
font-weight: bold;
}
.end-session-dialog-app-list-item {
color: #ccc;
.end-session-dialog-app-list-item,
.end-session-dialog-session-list-item {
spacing: 1em;
}
.end-session-dialog-app-list-item:hover {
color: white;
}
.end-session-dialog-app-list-item:ltr {
padding-right: 1em;
}
.end-session-dialog-app-list-item:rtl {
padding-left: 1em;
}
.end-session-dialog-app-list-item-icon:ltr {
padding-right: 17px;
}
.end-session-dialog-app-list-item-icon:rtl {
padding-left: 17px;
}
.end-session-dialog-app-list-item-name {
font-size: 10pt;
.end-session-dialog-app-list-item-name,
.end-session-dialog-session-list-item-name {
font-weight: bold;
}
.end-session-dialog-app-list-item-description {
font-size: 8pt;
color: #444444;
color: #cccccc;
font-size: 10pt;
}
/* ShellMountOperation Dialogs */
@ -2238,9 +2273,7 @@ StScrollBar StButton#vhandle:active {
.framed-user-icon {
border: 2px solid #8b8b8b;
border-radius: 5px;
width: 48pt;
height: 48pt;
border-radius: 3px;
background-size: contain;
}
@ -2267,14 +2300,6 @@ StScrollBar StButton#vhandle:active {
/* Reset border and background */
border: none;
background-color: transparent;
padding-bottom: 80px;
padding-top: 80px;
border-radius: 16px;
min-height: 150px;
max-height: 700px;
min-width: 350px;
}
.login-dialog-button-box {
@ -2288,10 +2313,11 @@ StScrollBar StButton#vhandle:active {
.login-dialog-user-list {
spacing: 12px;
padding: .2em;
width: 23em;
}
.login-dialog-user-list-item {
border-radius: 10px;
border-radius: 5px;
padding: .2em;
}
@ -2304,19 +2330,20 @@ StScrollBar StButton#vhandle:active {
}
.login-dialog-user-list-item .login-dialog-user-list-item-name {
font-size: 20pt;
padding-left: 9px;
font-size: 20px;
padding-left: 18px;
font-weight: bold;
}
.login-dialog-user-list:expanded .login-dialog-user-list-item {
color: #666666;
color: #bfbfbf;
}
.login-dialog-user-list-item,
.login-dialog-user-list-item:hover .login-dialog-user-list-item-name,
.login-dialog-user-list:expanded .login-dialog-user-list-item:focus .login-dialog-user-list-item-name,
.login-dialog-user-list:expanded .login-dialog-user-list-item:logged-in {
color: white;
color: #bfbfbf;
text-shadow: black 0px 2px 2px;
}
@ -2348,7 +2375,7 @@ StScrollBar StButton#vhandle:active {
.login-dialog-user-list-item-icon {
border: 2px solid #8b8b8b;
border-radius: 8px;
border-radius: 3px;
width: 64px;
height: 64px;
}
@ -2449,8 +2476,7 @@ StScrollBar StButton#vhandle:active {
background-color: rgba(102, 102, 102, 0.15);
}
.login-dialog-message-warning,
.login-dialog-message-info {
.login-dialog-message {
padding-top: 4px;
padding-bottom: 16px;
min-height: 2em;
@ -2461,15 +2487,16 @@ StScrollBar StButton#vhandle:active {
}
.login-dialog-message-hint {
padding-bottom: 16px;
min-height: 2em;
padding-top: 0px;
padding-bottom: 20px;
}
.user-widget-label {
font-size: 16pt;
font-size: 20px;
font-weight: bold;
text-align: left;
padding-left: 15px;
padding-left: 18px;
color:white;
text-shadow: black 0px 4px 3px 0px;
}

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
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="18"
height="18"
id="svg4703"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="page-indicator-pushed.svg">
<defs
id="defs4705" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.392433"
inkscape:cx="1.0245308"
inkscape:cy="13.3715"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid6140" />
</sodipodi:namedview>
<metadata
id="metadata4708">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,2)">
<path
transform="matrix(0.54617904,0,0,0.62523128,-1131.9904,-392.39214)"
d="m 2099.9808,638.83099 a 10.985409,9.5964489 0 1 1 -21.9708,0 10.985409,9.5964489 0 1 1 21.9708,0 z"
sodipodi:ry="9.5964489"
sodipodi:rx="10.985409"
sodipodi:cy="638.83099"
sodipodi:cx="2088.9954"
id="path4711"
style="fill:#fdffff;fill-opacity:1;stroke:none"
sodipodi:type="arc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
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="18"
height="18"
id="svg4703"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="page-indicator-active.svg">
<defs
id="defs4705" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.197802"
inkscape:cx="2.1522887"
inkscape:cy="16.782904"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1920"
inkscape:window-height="1021"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata4708">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,2)">
<path
transform="matrix(0.72823872,0,0,0.8336417,-1512.2872,-525.55618)"
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
sodipodi:ry="9.5964489"
sodipodi:rx="10.985409"
sodipodi:cy="638.83099"
sodipodi:cx="2088.9954"
id="path4711"
style="fill:#fdffff;fill-opacity:0.94117647;stroke:none"
sodipodi:type="arc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
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="18"
height="18"
id="svg5266"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="page-indicator-inactive.svg">
<defs
id="defs5268" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="11.313709"
inkscape:cx="-2.307566"
inkscape:cy="17.859535"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5271">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,2)">
<path
sodipodi:type="arc"
style="fill:none;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276000000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path5274"
sodipodi:cx="2088.9954"
sodipodi:cy="638.83099"
sodipodi:rx="10.985409"
sodipodi:ry="9.5964489"
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
transform="matrix(0.63720887,0,0,0.72943648,-1322.1264,-458.98661)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
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="18"
height="18"
id="svg5266"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="page-indicator-inactive.svg">
<defs
id="defs5268" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="11.313709"
inkscape:cx="-2.307566"
inkscape:cy="17.859535"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="2560"
inkscape:window-height="1374"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5271">
<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 />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,2)">
<path
sodipodi:type="arc"
style="fill:none;fill-opacity:0;stroke:#ffffff;stroke-width:2.93356276000000005;stroke-miterlimit:4;stroke-opacity:0.39215686000000000;stroke-dasharray:none"
id="path5274"
sodipodi:cx="2088.9954"
sodipodi:cy="638.83099"
sodipodi:rx="10.985409"
sodipodi:ry="9.5964489"
d="m 2099.9808,638.83099 c 0,5.29998 -4.9184,9.59645 -10.9854,9.59645 -6.0671,0 -10.9854,-4.29647 -10.9854,-9.59645 0,-5.29997 4.9183,-9.59645 10.9854,-9.59645 6.067,0 10.9854,4.29648 10.9854,9.59645 z"
transform="matrix(0.63720887,0,0,0.72943648,-1322.1264,-458.98661)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -112,7 +112,7 @@ expand_content_files=
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell.la
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(BLUETOOTH_LIBS) $(top_builddir)/src/libgnome-shell-menu.la $(top_builddir)/src/libgnome-shell-base.la $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

@ -21,6 +21,7 @@ nobase_dist_js_DATA = \
gdm/batch.js \
gdm/fingerprint.js \
gdm/loginDialog.js \
gdm/oVirt.js \
gdm/realmd.js \
gdm/util.js \
extensionPrefs/main.js \
@ -55,6 +56,7 @@ nobase_dist_js_DATA = \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
ui/focusCaretTracker.js\
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \

View File

@ -36,8 +36,6 @@ const BeginRequestType = {
DONT_PROVIDE_USERNAME: 1
};
let _messageStyleMap;
const AuthPrompt = new Lang.Class({
Name: 'AuthPrompt',
@ -61,6 +59,7 @@ const AuthPrompt = new Lang.Class({
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.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('next', Lang.bind(this, function() {
@ -109,7 +108,8 @@ const AuthPrompt = new Lang.Class({
this._entry.grab_key_focus();
this._message = new St.Label({ opacity: 0 });
this._message = new St.Label({ opacity: 0,
styleClass: 'login-dialog-message' });
this._message.clutter_text.line_wrap = true;
this.actor.add(this._message, { x_fill: true, y_align: St.Align.START });
@ -120,7 +120,7 @@ const AuthPrompt = new Lang.Class({
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
this._defaultButtonWell = new St.Widget();
this._defaultButtonWell = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._defaultButtonWellActor = null;
this._initButtons();
@ -220,6 +220,11 @@ const AuthPrompt = new Lang.Class({
this.emit('prompted');
},
_onOVirtUserAuthenticated: function() {
if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
this.reset();
},
_onSmartcardStatusChanged: function() {
this.smartcardDetected = this._userVerifier.smartcardDetected;
@ -245,6 +250,7 @@ const AuthPrompt = new Lang.Class({
},
_onVerificationFailed: function() {
this._queryingService = null;
this.clear();
this.updateSensitivity(true);
@ -265,10 +271,6 @@ const AuthPrompt = new Lang.Class({
addActorToDefaultButtonWell: function(actor) {
this._defaultButtonWell.add_child(actor);
actor.add_constraint(new Clutter.AlignConstraint({ source: this._spinner.actor,
align_axis: Clutter.AlignAxis.BOTH,
factor: 0.5 }));
},
setActorInDefaultButtonWell: function(actor, animate) {
@ -375,27 +377,22 @@ const AuthPrompt = new Lang.Class({
});
},
_initMessageStyleMap: function() {
if (_messageStyleMap)
return;
_messageStyleMap = {};
_messageStyleMap[GdmUtil.MessageType.NONE] = '';
_messageStyleMap[GdmUtil.MessageType.ERROR] = 'login-dialog-message-warning';
_messageStyleMap[GdmUtil.MessageType.INFO] = 'login-dialog-message-info';
_messageStyleMap[GdmUtil.MessageType.HINT] = 'login-dialog-message-hint';
},
setMessage: function(message, type) {
this._initMessageStyleMap();
if (type == GdmUtil.MessageType.ERROR)
this._message.add_style_class_name('login-dialog-message-warning');
else
this._message.remove_style_class_name('login-dialog-message-warning');
if (type == GdmUtil.MessageType.HINT)
this._message.add_style_class_name('login-dialog-message-hint');
else
this._message.remove_style_class_name('login-dialog-message-hint');
if (message) {
Tweener.removeTweens(this._message);
this._message.text = message;
this._message.styleClass = _messageStyleMap[type];
this._message.opacity = 255;
} else {
this._message.styleClass = null;
this._message.opacity = 0;
}
},
@ -453,10 +450,11 @@ const AuthPrompt = new Lang.Class({
// The user is constant at the unlock screen, so it will immediately
// respond to the request with the username
beginRequestType = BeginRequestType.PROVIDE_USERNAME;
} else if (this.smartcardDetected &&
this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME)) {
} else if (this._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) ||
(this.smartcardDetected &&
this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) {
// We don't need to know the username if the user preempted the login screen
// with a smartcard.
// with a smartcard or with preauthenticated oVirt credentials
beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
} else {
// In all other cases, we should get the username up front.

View File

@ -102,11 +102,6 @@ const UserListItem = new Lang.Class({
syncStyleClasses: function() {
this._updateLoggedIn();
if (global.stage.get_key_focus() == this.actor)
this.actor.add_style_pseudo_class('focus');
else
this.actor.remove_style_pseudo_class('focus');
},
_updateLoggedIn: function() {
@ -314,10 +309,6 @@ const SessionMenuButton = new Lang.Class({
this._button.remove_style_pseudo_class('active');
}));
let subtitle = new PopupMenu.PopupMenuItem(_("Session"), { style_class: 'popup-subtitle-menu-item',
reactive: false });
this._menu.addMenuItem(subtitle);
this._manager = new PopupMenu.PopupMenuManager({ actor: this._button });
this._manager.addMenu(this._menu);
@ -393,6 +384,7 @@ const LoginDialog = new Lang.Class({
_init: function(parentActor) {
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
layout_manager: new Clutter.BinLayout(),
style_class: 'login-dialog',
visible: false });
@ -431,11 +423,12 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._updateLogoTexture));
this._userSelectionBox = new St.BoxLayout({ style_class: 'login-dialog-user-selection-box',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true,
vertical: true,
visible: false });
this._userSelectionBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
align_axis: Clutter.AlignAxis.BOTH,
factor: 0.5 }));
this.actor.add_child(this._userSelectionBox);
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
@ -453,14 +446,7 @@ const LoginDialog = new Lang.Class({
this._authPrompt.connect('prompted', Lang.bind(this, this._onPrompted));
this._authPrompt.connect('reset', Lang.bind(this, this._onReset));
this._authPrompt.hide();
this._authPrompt.actor.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
align_axis: Clutter.AlignAxis.BOTH,
factor: 0.5 }));
this.actor.add_child(this._authPrompt.actor);
this._userList.actor.add_constraint(new Clutter.BindConstraint({ source: this._authPrompt.actor,
coordinate: Clutter.BindCoordinate.WIDTH }));
// translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for
@ -475,11 +461,7 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._notListedButton.connect('clicked',
Lang.bind(this, function() {
this._authPrompt.cancelButton.show();
this._hideUserListAndLogIn();
}));
this._notListedButton.connect('clicked', Lang.bind(this, this._hideUserListAskForUsernameAndBeginVerification));
this._notListedButton.hide();
@ -488,14 +470,11 @@ const LoginDialog = new Lang.Class({
x_align: St.Align.START,
x_fill: true });
this._logoBin = new St.Bin({ style_class: 'login-dialog-logo-bin', y_expand: true });
this._logoBin.set_y_align(Clutter.ActorAlign.END);
this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
align_axis: Clutter.AlignAxis.X_AXIS,
factor: 0.5 }));
this._logoBin.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
align_axis: Clutter.AlignAxis.Y_AXIS,
factor: 1.0 }));
this._logoBin = new St.Widget({ style_class: 'login-dialog-logo-bin',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
this.actor.add_child(this._logoBin);
this._updateLogo();
@ -568,11 +547,10 @@ const LoginDialog = new Lang.Class({
if (this._logoFileUri != uri)
return;
let icon = null;
this._logoBin.destroy_all_children();
if (this._logoFileUri)
icon = this._textureCache.load_uri_async(this._logoFileUri,
-1, _LOGO_ICON_HEIGHT);
this._logoBin.set_child(icon);
this._logoBin.add_child(this._textureCache.load_uri_async(this._logoFileUri,
-1, _LOGO_ICON_HEIGHT));
},
_updateLogo: function() {
@ -595,11 +573,13 @@ const LoginDialog = new Lang.Class({
this._user = null;
if (this._disableUserList) {
this._authPrompt.cancelButton.hide();
this._hideUserListAndLogIn();
if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
if (!this._disableUserList)
this._showUserList();
else
this._hideUserListAskForUsernameAndBeginVerification();
} else {
this._showUserList();
this._hideUserListAndBeginVerification();
}
},
@ -608,10 +588,11 @@ const LoginDialog = new Lang.Class({
},
_shouldShowSessionMenuButton: function() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING)
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
return false;
if (this._user && this._user.is_logged_in())
if (this._user && this._user.is_loaded && this._user.is_logged_in())
return false;
return true;
@ -638,7 +619,7 @@ const LoginDialog = new Lang.Class({
// Translators: this message is shown below the username entry field
// to clue the user in on how to login to the local network realm
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), AuthPrompt.MessageType.HINT);
this._authPrompt.setMessage(_("(e.g., user or %s)").format(hint), GdmUtil.MessageType.HINT);
},
_askForUsernameAndBeginVerification: function() {
@ -655,6 +636,7 @@ const LoginDialog = new Lang.Class({
this._authPrompt.disconnect(nextSignalId);
this._authPrompt.updateSensitivity(false);
let answer = this._authPrompt.getAnswer();
this._user = this._userManager.get_user(answer);
this._authPrompt.clear();
this._authPrompt.startSpinning();
this._authPrompt.begin({ userName: answer });
@ -911,6 +893,12 @@ const LoginDialog = new Lang.Class({
{ sortGroup: CtrlAltTab.SortGroup.MIDDLE });
this._userList.actor.grab_key_focus();
this.actor.show();
this.actor.opacity = 0;
Tweener.addTween(this.actor,
{ opacity: 255,
time: 1,
transition: 'easeInQuad' });
return true;
},
@ -922,5 +910,9 @@ const LoginDialog = new Lang.Class({
addCharacter: function(unichar) {
this._authPrompt.addCharacter(unichar);
},
finish: function(onComplete) {
this._authPrompt.finish(onComplete);
},
});
Signals.addSignalMethods(LoginDialog.prototype);

62
js/gdm/oVirt.js Normal file
View File

@ -0,0 +1,62 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const OVirtCredentialsIface = <interface name='org.ovirt.vdsm.Credentials'>
<signal name="UserAuthenticated">
<arg type="s" name="token"/>
</signal>
</interface>;
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);
let _oVirtCredentialsManager = null;
function OVirtCredentials() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
g_interface_name: OVirtCredentialsInfo.name,
g_interface_info: OVirtCredentialsInfo,
g_name: 'org.ovirt.vdsm.Credentials',
g_object_path: '/org/ovirt/vdsm/Credentials',
g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null);
return self;
}
const OVirtCredentialsManager = new Lang.Class({
Name: 'OVirtCredentialsManager',
_init: function() {
this._token = null;
this._credentials = new OVirtCredentials();
this._credentials.connectSignal('UserAuthenticated',
Lang.bind(this, this._onUserAuthenticated));
},
_onUserAuthenticated: function(proxy, sender, [token]) {
this._token = token;
this.emit('user-authenticated', token);
},
hasToken: function() {
return this._token != null;
},
getToken: function() {
return this._token;
},
resetToken: function() {
this._token = null;
}
});
Signals.addSignalMethods(OVirtCredentialsManager.prototype);
function getOVirtCredentialsManager() {
if (!_oVirtCredentialsManager)
_oVirtCredentialsManager = new OVirtCredentialsManager();
return _oVirtCredentialsManager;
}

View File

@ -10,6 +10,7 @@ const St = imports.gi.St;
const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint;
const OVirt = imports.gdm.oVirt;
const Main = imports.ui.main;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
@ -19,6 +20,7 @@ const Tweener = imports.ui.tweener;
const PASSWORD_SERVICE_NAME = 'gdm-password';
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
const SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
const OVIRT_SERVICE_NAME = 'gdm-ovirtcred';
const FADE_ANIMATION_TIME = 0.16;
const CLONE_FADE_ANIMATION_TIME = 0.25;
@ -151,6 +153,14 @@ const ShellUserVerifier = new Lang.Class({
this.reauthenticating = false;
this._failCounter = 0;
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
if (this._oVirtCredentialsManager.hasToken())
this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken());
this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, this._oVirtUserAuthenticated));
},
begin: function(userName, hold) {
@ -277,6 +287,11 @@ const ShellUserVerifier = new Lang.Class({
}));
},
_oVirtUserAuthenticated: function(token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
},
_checkForSmartcard: function() {
let smartcardDetected;
@ -381,21 +396,38 @@ const ShellUserVerifier = new Lang.Class({
_startService: function(serviceName) {
this._hold.acquire();
this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
this._reportInitError('Failed to start verification for user', e);
return;
}
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
}));
this._hold.release();
}));
} else {
this._userVerifier.call_begin_verification(serviceName,
this._cancellable,
Lang.bind(this, function(obj, result) {
try {
obj.call_begin_verification_finish(result);
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
return;
} catch(e) {
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
}));
}
},
_beginVerification: function() {
@ -438,6 +470,12 @@ const ShellUserVerifier = new Lang.Class({
if (!this.serviceIsForeground(serviceName))
return;
if (serviceName == OVIRT_SERVICE_NAME) {
// The only question asked by this service is "Token?"
this.answerQuery(serviceName, this._oVirtCredentialsManager.getToken());
return;
}
this.emit('ask-question', serviceName, secretQuestion, '\u25cf');
},
@ -498,6 +536,16 @@ const ShellUserVerifier = new Lang.Class({
},
_onConversationStopped: function(client, serviceName) {
// If the login failed with the preauthenticated oVirt credentials
// then discard the credentials and revert to default authentication
// mechanism.
if (this.serviceIsForeground(OVIRT_SERVICE_NAME)) {
this._oVirtCredentialsManager.resetToken();
this._preemptingService = null;
this._verificationFailed(false);
return;
}
// if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed

View File

@ -8,21 +8,9 @@ const Shell = imports.gi.Shell;
const Signals = imports.signals;
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'>
<method name='PowerOff'>
<arg type='b' direction='in'/>
</method>
<method name='Reboot'>
<arg type='b' direction='in'/>
</method>
<method name='Suspend'>
<arg type='b' direction='in'/>
</method>
<method name='CanPowerOff'>
<arg type='s' direction='out'/>
</method>
<method name='CanReboot'>
<arg type='s' direction='out'/>
</method>
<method name='CanSuspend'>
<arg type='s' direction='out'/>
</method>
@ -84,8 +72,10 @@ function versionCompare(required, reference) {
reference = reference.split('.');
for (let i = 0; i < required.length; i++) {
if (required[i] != reference[i])
return required[i] < reference[i];
let requiredInt = parseInt(required[i]);
let referenceInt = parseInt(reference[i]);
if (requiredInt != referenceInt)
return requiredInt < referenceInt;
}
return true;
@ -159,24 +149,6 @@ const LoginManagerSystemd = new Lang.Class({
}));
},
canPowerOff: function(asyncCallback) {
this._proxy.CanPowerOffRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRebootRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0] != 'no');
});
},
canSuspend: function(asyncCallback) {
this._proxy.CanSuspendRemote(function(result, error) {
if (error)
@ -195,14 +167,6 @@ const LoginManagerSystemd = new Lang.Class({
});
},
powerOff: function() {
this._proxy.PowerOffRemote(true);
},
reboot: function() {
this._proxy.RebootRemote(true);
},
suspend: function() {
this._proxy.SuspendRemote(true);
},
@ -264,24 +228,6 @@ const LoginManagerConsoleKit = new Lang.Class({
}));
},
canPowerOff: function(asyncCallback) {
this._proxy.CanStopRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
},
canReboot: function(asyncCallback) {
this._proxy.CanRestartRemote(function(result, error) {
if (error)
asyncCallback(false);
else
asyncCallback(result[0]);
});
},
canSuspend: function(asyncCallback) {
asyncCallback(false);
},
@ -290,14 +236,6 @@ const LoginManagerConsoleKit = new Lang.Class({
asyncCallback([]);
},
powerOff: function() {
this._proxy.StopRemote();
},
reboot: function() {
this._proxy.RestartRemote();
},
suspend: function() {
this.emit('prepare-for-sleep', true);
this.emit('prepare-for-sleep', false);

View File

@ -20,7 +20,7 @@ const ObjectManagerIface = <interface name="org.freedesktop.DBus.ObjectManager">
<arg name="objectPath" type="o"/>
<arg name="interfaces" type="as" />
</signal>
</interface>
</interface>;
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);
@ -71,21 +71,24 @@ const ObjectManager = new Lang.Class({
},
_addInterface: function(objectPath, interfaceName, onFinished) {
let info = this._interfaceInfos[interfaceName];
let info = this._interfaceInfos[interfaceName];
if (!info)
return;
if (!info) {
if (onFinished)
onFinished();
return;
}
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.NONE });
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.NONE });
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, function(initable, result) {
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
Lang.bind(this, function(initable, result) {
let error = null;
try {
initable.init_finish(result);

View File

@ -1,7 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const St = imports.gi.St;
const Main = imports.ui.main;
@ -78,6 +80,22 @@ function spawnCommandLine(command_line) {
}
}
// spawnApp:
// @argv: an argv array
//
// Runs @argv as if it was an application, handling startup notification
function spawnApp(argv) {
try {
let app = Gio.AppInfo.create_from_commandline(argv.join(' '), null,
Gio.AppInfoCreateFlags.SUPPORTS_STARTUP_NOTIFICATION);
let context = global.create_app_launch_context();
app.launch([], context);
} catch(err) {
_handleSpawnError(argv[0], err);
}
}
// trySpawn:
// @argv: an argv array
//
@ -189,28 +207,57 @@ function insertSorted(array, val, cmp) {
return pos;
}
function makeCloseButton() {
let closeButton = new St.Button({ style_class: 'notification-close'});
const CloseButton = new Lang.Class({
Name: 'CloseButton',
Extends: St.Button,
// This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for
// Clutter 2.0. Since St.Bin doesn't define its own setters, the
// setters are a workaround to get Clutter's version.
closeButton.set_x_align(Clutter.ActorAlign.END);
closeButton.set_y_align(Clutter.ActorAlign.START);
_init: function(boxpointer) {
this.parent({ style_class: 'notification-close'});
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
// to respect the alignments.
closeButton.set_x_expand(true);
closeButton.set_y_expand(true);
// This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for
// Clutter 2.0. Since St.Bin doesn't define its own setters, the
// setters are a workaround to get Clutter's version.
this.set_x_align(Clutter.ActorAlign.END);
this.set_y_align(Clutter.ActorAlign.START);
closeButton.connect('style-changed', function() {
let themeNode = closeButton.get_theme_node();
closeButton.translation_x = themeNode.get_length('-shell-close-overlap-x');
closeButton.translation_y = themeNode.get_length('-shell-close-overlap-y');
});
// XXX Clutter 2.0 workaround: ClutterBinLayout needs expand
// to respect the alignments.
this.set_x_expand(true);
this.set_y_expand(true);
return closeButton;
this._boxPointer = boxpointer;
if (boxpointer)
this._boxPointer.connect('arrow-side-changed', Lang.bind(this, this._sync));
},
_computeBoxPointerOffset: function() {
if (!this._boxPointer || !this._boxPointer.actor.get_stage())
return 0;
let side = this._boxPointer.arrowSide;
if (side == St.Side.TOP)
return this._boxPointer.getArrowHeight();
else
return 0;
},
_sync: function() {
let themeNode = this.get_theme_node();
let offY = this._computeBoxPointerOffset();
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
},
vfunc_style_changed: function() {
this._sync();
this.parent();
},
});
function makeCloseButton(boxpointer) {
return new CloseButton(boxpointer);
}
function ensureActorVisibleInScrollView(scrollView, actor) {

View File

@ -355,10 +355,13 @@ const WindowSwitcherPopup = new Lang.Class({
Name: 'WindowSwitcherPopup',
Extends: SwitcherPopup.SwitcherPopup,
_init: function(items) {
this.parent(items);
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
},
_getWindowList: function() {
let settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
let workspace = settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace()
: null;
let workspace = this._settings.get_boolean('current-workspace-only') ? global.screen.get_active_workspace() : null;
return global.display.get_tab_list(Meta.TabList.NORMAL, global.screen, workspace);
},
@ -368,7 +371,8 @@ const WindowSwitcherPopup = new Lang.Class({
if (windows.length == 0)
return false;
this._switcherList = new WindowList(windows);
let mode = this._settings.get_enum('app-icon-mode');
this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons;
return true;
@ -663,7 +667,7 @@ const ThumbnailList = new Lang.Class({
const WindowIcon = new Lang.Class({
Name: 'WindowIcon',
_init: function(window) {
_init: function(window, mode) {
this.window = window;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -681,8 +685,7 @@ const WindowIcon = new Lang.Class({
this._icon.destroy_all_children();
let settings = new Gio.Settings({ schema: 'org.gnome.shell.window-switcher' });
switch (settings.get_enum('app-icon-mode')) {
switch (mode) {
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, WINDOW_PREVIEW_SIZE));
@ -720,7 +723,7 @@ const WindowList = new Lang.Class({
Name: 'WindowList',
Extends: SwitcherPopup.SwitcherList,
_init : function(windows) {
_init : function(windows, mode) {
this.parent(true);
this._label = new St.Label({ x_align: Clutter.ActorAlign.CENTER,
@ -732,7 +735,7 @@ const WindowList = new Lang.Class({
for (let i = 0; i < windows.length; i++) {
let win = windows[i];
let icon = new WindowIcon(win);
let icon = new WindowIcon(win, mode);
this.addItem(icon.actor, icon.label);
this.icons.push(icon);

File diff suppressed because it is too large Load Diff

View File

@ -14,15 +14,15 @@ const AppFavorites = new Lang.Class({
_init: function() {
this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
this._reload();
this.reload();
},
_onFavsChanged: function() {
this._reload();
this.reload();
this.emit('changed');
},
_reload: function() {
reload: function() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) {

View File

@ -319,9 +319,9 @@ const Background = new Lang.Class({
this._cancellable = new Gio.Cancellable();
this.isLoaded = false;
this._settings.connect('changed', Lang.bind(this, function() {
this.emit('changed');
}));
this._settingsChangedSignalId = this._settings.connect('changed', Lang.bind(this, function() {
this.emit('changed');
}));
this._load();
},
@ -362,6 +362,10 @@ const Background = new Lang.Class({
this.actor.disconnect(this._destroySignalId);
this._destroySignalId = 0;
if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0;
},
_setLoaded: function() {

View File

@ -3,8 +3,9 @@
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -61,6 +62,10 @@ const BoxPointer = new Lang.Class({
this._muteInput();
},
get arrowSide() {
return this._arrowSide;
},
_muteInput: function() {
if (this._capturedEventId == 0)
this._capturedEventId = this.actor.connect('captured-event',
@ -180,7 +185,9 @@ const BoxPointer = new Lang.Class({
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth);
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);
alloc.min_size = minSize;
alloc.natural_size = naturalSize;
this._adjustAllocationForArrow(false, alloc);
@ -612,6 +619,8 @@ const BoxPointer = new Lang.Class({
this._container.queue_relayout();
return false;
}));
this.emit('arrow-side-changed');
}
},
@ -639,5 +648,21 @@ const BoxPointer = new Lang.Class({
get opacity() {
return this.actor.opacity;
},
updateArrowSide: function(side) {
this._arrowSide = side;
this._border.queue_repaint();
this.emit('arrow-side-changed');
},
getPadding: function(side) {
return this.bin.get_theme_node().get_padding(side);
},
getArrowHeight: function() {
return this.actor.get_theme_node().get_length('-arrow-rise');
}
});
Signals.addSignalMethods(BoxPointer.prototype);

View File

@ -444,14 +444,17 @@ const Calendar = new Lang.Class({
{ row: 0, col: 0, col_span: offsetCols + 7 });
this._backButton = new St.Button({ style_class: 'calendar-change-month-back',
accessible_name: _("Previous month"),
can_focus: true });
this._topBox.add(this._backButton);
this._backButton.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
this._monthLabel = new St.Label({style_class: 'calendar-month-label'});
this._monthLabel = new St.Label({style_class: 'calendar-month-label',
can_focus: true });
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward',
accessible_name: _("Next month"),
can_focus: true });
this._topBox.add(this._forwardButton);
this._forwardButton.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));

View File

@ -13,8 +13,6 @@ const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const CheckBox = imports.ui.checkBox;
let prompter = null;
const KeyringDialog = new Lang.Class({
Name: 'KeyringDialog',
Extends: ModalDialog.ModalDialog,
@ -80,23 +78,26 @@ const KeyringDialog = new Lang.Class({
},
_buildControlTable: function() {
let table = new St.Table({ style_class: 'keyring-dialog-control-table' });
let layout = new Clutter.TableLayout();
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout });
layout.hookup_style(table);
let row = 0;
if (this.prompt.password_visible) {
let label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
let label = new St.Label({ style_class: 'prompt-dialog-password-label' });
label.set_text(_("Password:"));
table.add(label, { row: row, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true});
can_focus: 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));
table.add(this._passwordEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
layout.pack(this._passwordEntry, 1, row);
row++;
} else {
this._passwordEntry = null;
@ -105,17 +106,16 @@ const KeyringDialog = new Lang.Class({
if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
label.set_text(_("Type again:"));
table.add(label, { row: row, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true});
can_focus: 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));
table.add(this._confirmEntry, { row: row, col: 1, x_expand: true, x_fill: true, x_align: St.Align.START });
layout.pack(this._confirmEntry, 1, row);
row++;
} else {
this._confirmEntry = null;
@ -128,14 +128,14 @@ const KeyringDialog = new Lang.Class({
let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
table.add(choice.actor, { row: row, col: 1, x_expand: false, x_fill: true, x_align: St.Align.START });
layout.pack(choice.actor, 1, row);
row++;
}
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
warning.clutter_text.line_wrap = true;
table.add(warning, { row: row, col: 1, x_expand: false, x_fill: false, x_align: St.Align.START });
layout.pack(warning, 1, row);
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);
@ -221,27 +221,56 @@ const KeyringDialog = new Lang.Class({
},
});
const KeyringDummyDialog = new Lang.Class({
Name: 'KeyringDummyDialog',
_init: function() {
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));
},
_cancelPrompt: function() {
this.prompt.cancel();
}
});
const KeyringPrompter = new Lang.Class({
Name: 'KeyringPrompter',
_init: function() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', function(prompter) {
let dialog = new KeyringDialog();
return dialog.prompt;
});
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._dbusId = null;
this._registered = false;
this._enabled = false;
this._currentPrompt = null;
},
enable: function() {
this._prompter.register(Gio.DBus.session);
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
if (!this._registered) {
this._prompter.register(Gio.DBus.session);
this._dbusId = Gio.DBus.session.own_name('org.gnome.keyring.SystemPrompter',
Gio.BusNameOwnerFlags.ALLOW_REPLACEMENT, null, null);
this._registered = true;
}
this._enabled = true;
},
disable: function() {
this._prompter.unregister(false);
Gio.DBus.session.unown_name(this._dbusId);
this._enabled = false;
if (this._prompter.prompting)
this._currentPrompt.cancel();
this._currentPrompt = null;
}
});

View File

@ -72,13 +72,18 @@ const NetworkSecretDialog = new Lang.Class({
expand: true });
}
let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
let layout = new Clutter.TableLayout();
let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
layout_manager: layout });
layout.hookup_style(secretTable);
let initialFocusSet = false;
let pos = 0;
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
text: secret.label });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let reactive = secret.key != null;
@ -111,11 +116,10 @@ const NetworkSecretDialog = new Lang.Class({
} else
secret.valid = true;
secretTable.add(label, { row: pos, col: 0,
x_expand: false, x_fill: true,
x_align: St.Align.START,
y_fill: false, y_align: St.Align.MIDDLE });
secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
layout.pack(label, 0, pos);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
layout.pack(secret.entry, 1, pos);
pos++;
if (secret.password)
@ -380,11 +384,7 @@ const VPNRequestHandler = new Lang.Class({
this._childPid = pid;
this._stdin = new Gio.UnixOutputStream({ fd: stdin, close_fd: true });
this._stdout = new Gio.UnixInputStream({ fd: stdout, close_fd: true });
// We need this one too, even if don't actually care of what the process
// has to say on stderr, because otherwise the fd opened by g_spawn_async_with_pipes
// is kept open indefinitely
let stderrStream = new Gio.UnixInputStream({ fd: stderr, close_fd: true });
stderrStream.close(null);
GLib.close(stderr);
this._dataStdout = new Gio.DataInputStream({ base_stream: this._stdout });
if (this._newStylePlugin)

View File

@ -13,7 +13,6 @@ const Tp = imports.gi.TelepathyGLib;
const History = imports.misc.history;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
@ -416,7 +415,7 @@ const TelepathyClient = new Lang.Class({
_ensureAppSource: function() {
if (this._appSource == null) {
this._appSource = new MessageTray.Source(_("Chat"), 'empathy');
this._appSource.policy = new NotificationDaemon.NotificationApplicationPolicy('empathy');
this._appSource.policy = new MessageTray.NotificationApplicationPolicy('empathy');
Main.messageTray.add(this._appSource);
this._appSource.connect('destroy', Lang.bind(this, function () {
@ -488,7 +487,7 @@ const ChatSource = new Lang.Class({
},
_createPolicy: function() {
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
return new MessageTray.NotificationApplicationPolicy('empathy');
},
_updateAlias: function() {
@ -1061,7 +1060,7 @@ const ApproverSource = new Lang.Class({
},
_createPolicy: function() {
return new NotificationDaemon.NotificationApplicationPolicy('empathy');
return new MessageTray.NotificationApplicationPolicy('empathy');
},
destroy: function() {

View File

@ -423,7 +423,10 @@ const Dash = new Lang.Class({
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
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));
@ -502,15 +505,21 @@ const Dash = new Lang.Class({
Main.queueDeferredWork(this._workId);
},
_hookUpLabel: function(item) {
_hookUpLabel: function(item, appIcon) {
item.child.connect('notify::hover', Lang.bind(this, function() {
this._onHover(item);
this._syncLabel(item, appIcon);
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
this._labelShowing = false;
item.hideLabel();
}));
if (appIcon) {
appIcon.connect('sync-tooltip', Lang.bind(this, function() {
this._syncLabel(item, appIcon);
}));
}
},
_createAppItem: function(app) {
@ -539,7 +548,7 @@ const Dash = new Lang.Class({
item.setLabelText(app.get_name());
appIcon.icon.setIconSize(this.iconSize);
this._hookUpLabel(item);
this._hookUpLabel(item, appIcon);
return item;
},
@ -557,8 +566,10 @@ const Dash = new Lang.Class({
}
},
_onHover: function (item) {
if (item.child.get_hover()) {
_syncLabel: function (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,

View File

@ -50,6 +50,7 @@ const DateMenuButton = new Lang.Class({
this.parent(menuAlignment);
this._clockDisplay = new St.Label({ y_align: Clutter.ActorAlign.CENTER });
this.actor.label_actor = this._clockDisplay;
this.actor.add_actor(this._clockDisplay);
this.actor.add_style_class_name ('clock-display');
@ -62,9 +63,8 @@ const DateMenuButton = new Lang.Class({
hbox.add(vbox);
// Date
this._date = new St.Label();
this.actor.label_actor = this._clockDisplay;
this._date.style_class = 'datemenu-date-label';
this._date = new St.Label({ style_class: 'datemenu-date-label',
can_focus: true });
vbox.add(this._date);
this._eventList = new Calendar.EventsList();

View File

@ -5,6 +5,7 @@ const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const St = imports.gi.St;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Tweener = imports.ui.tweener;
@ -27,9 +28,9 @@ const DragMotionResult = {
};
const DRAG_CURSOR_MAP = {
0: Shell.Cursor.DND_UNSUPPORTED_TARGET,
1: Shell.Cursor.DND_COPY,
2: Shell.Cursor.DND_MOVE
0: Meta.Cursor.DND_UNSUPPORTED_TARGET,
1: Meta.Cursor.DND_COPY,
2: Meta.Cursor.DND_MOVE
};
const DragDropResult = {
@ -85,11 +86,6 @@ const _Draggable = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, function() {
this._actorDestroyed = true;
// If the drag actor is destroyed and we were going to fix
// up its hover state, fix up the parent hover state instead
if (this.actor == this._firstLeaveActor)
this._firstLeaveActor = this._dragOrigParent;
if (this._dragInProgress && this._dragCancellable)
this._cancelDrag(global.get_current_time());
this.disconnectAll();
@ -105,12 +101,6 @@ const _Draggable = new Lang.Class({
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
this._dragCancellable = true;
// During the drag, we eat enter/leave events so that actors don't prelight.
// But we remember the actors that we first left/last entered so we can
// fix up the hover state after the drag ends.
this._firstLeaveActor = null;
this._lastEnterActor = null;
this._eventsGrabbed = false;
},
@ -196,11 +186,6 @@ const _Draggable = new Lang.Class({
this._cancelDrag(event.get_time());
return true;
}
} else if (event.type() == Clutter.EventType.LEAVE) {
if (this._firstLeaveActor == null)
this._firstLeaveActor = event.get_source();
} else if (event.type() == Clutter.EventType.ENTER) {
this._lastEnterActor = event.get_source();
}
return false;
@ -244,7 +229,7 @@ const _Draggable = new Lang.Class({
if (this._onEventId)
this._ungrabActor();
this._grabEvents();
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
this._dragX = this._dragStartX = stageX;
this._dragY = this._dragStartY = stageY;
@ -374,7 +359,7 @@ const _Draggable = new Lang.Class({
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
return false;
}
}
@ -392,13 +377,13 @@ const _Draggable = new Lang.Class({
targY,
0);
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
global.screen.set_cursor(DRAG_CURSOR_MAP[result]);
return false;
}
}
target = target.get_parent();
}
global.set_cursor(Shell.Cursor.DND_IN_DRAG);
global.screen.set_cursor(Meta.Cursor.DND_IN_DRAG);
return false;
},
@ -470,7 +455,7 @@ const _Draggable = new Lang.Class({
}
this._dragInProgress = false;
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
@ -517,17 +502,12 @@ const _Draggable = new Lang.Class({
},
_cancelDrag: function(eventTime) {
if (this._updateHoverId) {
GLib.source_remove(this._updateHoverId);
this._updateHoverId = 0;
}
this.emit('drag-cancelled', eventTime);
this._dragInProgress = false;
let [snapBackX, snapBackY, snapBackScale] = this._getRestoreLocation();
if (this._actorDestroyed) {
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
if (!this._buttonDown)
this._dragComplete();
this.emit('drag-end', eventTime, false);
@ -581,7 +561,7 @@ const _Draggable = new Lang.Class({
} else {
dragActor.destroy();
}
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
this.emit('drag-end', eventTime, false);
this._animationInProgress = false;
@ -589,32 +569,16 @@ const _Draggable = new Lang.Class({
this._dragComplete();
},
// Actor is an actor we have entered or left during the drag; call
// st_widget_sync_hover on all StWidget ancestors
_syncHover: function(actor) {
while (actor) {
let parent = actor.get_parent();
if (actor instanceof St.Widget)
actor.sync_hover();
actor = parent;
}
},
_dragComplete: function() {
if (!this._actorDestroyed)
Shell.util_set_hidden_from_pick(this._dragActor, false);
this._ungrabEvents();
global.sync_pointer();
if (this._firstLeaveActor) {
this._syncHover(this._firstLeaveActor);
this._firstLeaveActor = null;
}
if (this._lastEnterActor) {
this._syncHover(this._lastEnterActor);
this._lastEnterActor = null;
if (this._updateHoverId) {
GLib.source_remove(this._updateHoverId);
this._updateHoverId = 0;
}
this._dragActor = undefined;

View File

@ -20,7 +20,6 @@
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
@ -32,7 +31,7 @@ const St = imports.gi.St;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
const LoginManager = imports.misc.loginManager;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const UserWidget = imports.ui.userWidget;
@ -62,63 +61,96 @@ const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessi
const logoutDialogContent = {
subjectWithUser: C_("title", "Log Out %s"),
subject: C_("title", "Log Out"),
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: function(user, seconds) {
descriptionWithUser: function(user, seconds) {
return ngettext("%s will be logged out automatically in %d second.",
"%s will be logged out automatically in %d seconds.",
seconds).format(user, seconds);
},
uninhibitedDescription: function(seconds) {
description: function(seconds) {
return ngettext("You will be logged out automatically in %d second.",
"You will be logged out automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Logging out of the system."),
confirmButtons: [{ signal: 'ConfirmedLogout',
label: C_("button", "Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon'
iconStyleClass: 'end-session-dialog-logout-icon',
showOtherSessions: false,
};
const shutdownDialogContent = {
subject: C_("title", "Power Off"),
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
uninhibitedDescription: function(seconds) {
description: function(seconds) {
return ngettext("The system will power off automatically in %d second.",
"The system will power off automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Powering off the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }],
iconName: 'system-shutdown-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon'
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const restartDialogContent = {
subject: C_("title", "Restart"),
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: function(seconds) {
description: function(seconds) {
return ngettext("The system will restart automatically in %d second.",
"The system will restart automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon'
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const restartInstallDialogContent = {
subject: C_("title", "Restart & Install Updates"),
description: function(seconds) {
return ngettext("The system will automatically restart and install updates in %d second.",
"The system will automatically restart and install updates in %d seconds.",
seconds).format(seconds);
},
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart & Install") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const DialogContent = {
0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent
2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent,
3: restartInstallDialogContent
};
const MAX_USERS_IN_SESSION_DIALOG = 5;
const LogindSessionIface = <interface name='org.freedesktop.login1.Session'>
<property name="Id" type="s" access="read"/>
<property name="Remote" type="b" access="read"/>
<property name="Class" type="s" access="read"/>
<property name="Type" type="s" access="read"/>
<property name="State" type="s" access="read"/>
</interface>;
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
function findAppFromInhibitor(inhibitor) {
let [desktopFile] = inhibitor.GetAppIdSync();
let desktopFile;
try {
[desktopFile] = inhibitor.GetAppIdSync();
} catch(e) {
// XXX -- sometimes JIT inhibitors generated by gnome-session
// get removed too soon. Don't fail in this case.
log('gnome-session gave us a dead inhibitor: %s'.format(inhibitor.get_object_path()));
return null;
}
if (!GLib.str_has_suffix(desktopFile, '.desktop'))
desktopFile += '.desktop';
@ -126,58 +158,6 @@ function findAppFromInhibitor(inhibitor) {
return Shell.AppSystem.get_default().lookup_heuristic_basename(desktopFile);
}
const ListItem = new Lang.Class({
Name: 'ListItem',
_init: function(app, reason) {
this._app = app;
this._reason = reason;
if (this._reason == null)
this._reason = '';
let layout = new St.BoxLayout({ vertical: false});
this.actor = new St.Button({ style_class: 'end-session-dialog-app-list-item',
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._icon = this._app.create_icon_texture(_ITEM_ICON_SIZE);
let iconBin = new St.Bin({ style_class: 'end-session-dialog-app-list-item-icon',
child: this._icon });
layout.add(iconBin);
let textLayout = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item-text-box',
vertical: true });
layout.add(textLayout);
this._nameLabel = new St.Label({ text: this._app.get_name(),
style_class: 'end-session-dialog-app-list-item-name' });
textLayout.add(this._nameLabel,
{ expand: false,
x_fill: true });
this._descriptionLabel = new St.Label({ text: this._reason,
style_class: 'end-session-dialog-app-list-item-description' });
this.actor.label_actor = this._nameLabel;
textLayout.add(this._descriptionLabel,
{ expand: true,
x_fill: true });
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
_onClicked: function() {
this.emit('activate');
this._app.activate();
}
});
Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds
// until the last 10 seconds, then it shows updates every
// second. This function takes a given time and returns
@ -228,22 +208,23 @@ const EndSessionDialog = new Lang.Class({
this.parent({ styleClass: 'end-session-dialog',
destroyOnClose: false });
this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
this._updatesFile = Gio.File.new_for_path('/system-update');
this._secondsLeft = 0;
this._totalSecondsToStayOpen = 0;
this._inhibitors = [];
this._applications = [];
this._sessions = [];
this.connect('destroy',
Lang.bind(this, this._onDestroy));
this.connect('opened',
Lang.bind(this, this._onOpened));
this._userLoadedId = this._user.connect('notify::is_loaded',
Lang.bind(this, this._updateContent));
this._userChangedId = this._user.connect('changed',
Lang.bind(this, this._updateContent));
this._userLoadedId = this._user.connect('notify::is_loaded', Lang.bind(this, this._sync));
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._sync));
let mainContentLayout = new St.BoxLayout({ vertical: false });
this.contentLayout.add(mainContentLayout,
@ -275,28 +256,28 @@ const EndSessionDialog = new Lang.Class({
{ y_fill: true,
y_align: St.Align.START });
let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list'});
scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(scrollView,
this._scrollView = new St.ScrollView({ style_class: 'end-session-dialog-list' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(this._scrollView,
{ x_fill: true,
y_fill: true });
scrollView.hide();
this._scrollView.hide();
this._inhibitorSection = new St.BoxLayout({ vertical: true,
style_class: 'end-session-dialog-inhibitor-layout' });
this._scrollView.add_actor(this._inhibitorSection);
this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Some applications are busy or have unsaved work.") });
this._applicationList = new St.BoxLayout({ vertical: true });
scrollView.add_actor(this._applicationList);
this._inhibitorSection.add_actor(this._applicationHeader);
this._inhibitorSection.add_actor(this._applicationList);
this._applicationList.connect('actor-added',
Lang.bind(this, function() {
if (this._applicationList.get_n_children() == 1)
scrollView.show();
}));
this._applicationList.connect('actor-removed',
Lang.bind(this, function() {
if (this._applicationList.get_n_children() == 0)
scrollView.hide();
}));
this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Other users are logged in.") });
this._sessionList = new St.BoxLayout({ vertical: true });
this._inhibitorSection.add_actor(this._sessionHeader);
this._inhibitorSection.add_actor(this._sessionList);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
@ -307,52 +288,42 @@ const EndSessionDialog = new Lang.Class({
this._user.disconnect(this._userChangedId);
},
_updateDescription: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
_sync: function() {
let open = (this.state == ModalDialog.State.OPENING || this.state == ModalDialog.State.OPENED);
if (!open)
return;
if (this._type == 2 && this._updatesFile.query_exists(null))
this._type = 3;
let dialogContent = DialogContent[this._type];
let subject = dialogContent.subject;
let description;
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
this._secondsLeft,
10);
if (this._inhibitors.length > 0) {
this._stopTimer();
description = dialogContent.inhibitedDescription;
} else if (this._secondsLeft > 0 && this._inhibitors.length == 0) {
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
this._secondsLeft,
10);
if (this._user.is_loaded) {
let realName = this._user.get_real_name();
if (this._user.is_loaded) {
let realName = this._user.get_real_name();
if (realName != null) {
if (dialogContent.subjectWithUser)
subject = dialogContent.subjectWithUser.format(realName);
if (realName != null) {
if (dialogContent.subjectWithUser)
subject = dialogContent.subjectWithUser.format(realName);
if (dialogContent.uninhibitedDescriptionWithUser)
description = dialogContent.uninhibitedDescriptionWithUser(realName, displayTime);
else
description = dialogContent.uninhibitedDescription(displayTime);
}
if (dialogContent.descriptionWithUser)
description = dialogContent.descriptionWithUser(realName, displayTime);
else
description = dialogContent.description(displayTime);
}
if (!description)
description = dialogContent.uninhibitedDescription(displayTime);
} else {
description = dialogContent.endDescription;
}
_setLabelText(this._subjectLabel, subject);
_setLabelText(this._descriptionLabel, description);
},
if (!description)
description = dialogContent.description(displayTime);
_updateContent: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
_setLabelText(this._descriptionLabel, description);
_setLabelText(this._subjectLabel, subject);
let dialogContent = DialogContent[this._type];
if (dialogContent.iconName) {
@ -367,7 +338,11 @@ const EndSessionDialog = new Lang.Class({
avatarWidget.update();
}
this._updateDescription();
let hasApplications = this._applications.length > 0;
let hasSessions = this._sessions.length > 0;
this._scrollView.visible = hasApplications || hasSessions;
this._applicationHeader.visible = hasApplications;
this._sessionHeader.visible = hasSessions;
},
_updateButtons: function() {
@ -413,14 +388,12 @@ const EndSessionDialog = new Lang.Class({
},
_onOpened: function() {
if (this._inhibitors.length == 0)
this._startTimer();
this._sync();
},
_startTimer: function() {
let startTime = GLib.get_monotonic_time();
this._secondsLeft = this._totalSecondsToStayOpen;
this._updateDescription();
this._timerId = Mainloop.timeout_add_seconds(1, Lang.bind(this,
function() {
@ -429,7 +402,7 @@ const EndSessionDialog = new Lang.Class({
this._secondsLeft = this._totalSecondsToStayOpen - secondsElapsed;
if (this._secondsLeft > 0) {
this._updateDescription();
this._sync();
return true;
}
@ -442,7 +415,7 @@ const EndSessionDialog = new Lang.Class({
},
_stopTimer: function() {
if (this._timerId != 0) {
if (this._timerId > 0) {
Mainloop.source_remove(this._timerId);
this._timerId = 0;
}
@ -450,8 +423,33 @@ const EndSessionDialog = new Lang.Class({
this._secondsLeft = 0;
},
_constructListItemForApp: function(inhibitor, app) {
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item',
can_focus: true });
actor.add(app.create_icon_texture(_ITEM_ICON_SIZE));
let textLayout = new St.BoxLayout({ vertical: true,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
actor.add(textLayout);
let nameLabel = new St.Label({ text: app.get_name(),
style_class: 'end-session-dialog-app-list-item-name' });
textLayout.add(nameLabel);
actor.label_actor = nameLabel;
let [reason] = inhibitor.GetReasonSync();
if (reason) {
let reasonLabel = new St.Label({ text: reason,
style_class: 'end-session-dialog-app-list-item-description' });
textLayout.add(reasonLabel);
}
return actor;
},
_onInhibitorLoaded: function(inhibitor) {
if (this._inhibitors.indexOf(inhibitor) < 0) {
if (this._applications.indexOf(inhibitor) < 0) {
// Stale inhibitor
return;
}
@ -459,29 +457,92 @@ const EndSessionDialog = new Lang.Class({
let app = findAppFromInhibitor(inhibitor);
if (app) {
let [reason] = inhibitor.GetReasonSync();
let item = new ListItem(app, reason);
item.connect('activate',
Lang.bind(this, function() {
this.close();
}));
this._applicationList.add(item.actor, { x_fill: true });
this._stopTimer();
let actor = this._constructListItemForApp(inhibitor, app);
this._applicationList.add(actor);
} else {
// inhibiting app is a service, not an application
this._inhibitors.splice(this._inhibitors.indexOf(inhibitor), 1);
this._applications.splice(this._applications.indexOf(inhibitor), 1);
}
this._updateContent();
this._sync();
},
_constructListItemForSession: function(session) {
let avatar = new UserWidget.Avatar(session.user, { iconSize: _ITEM_ICON_SIZE });
avatar.update();
let userName = session.user.get_real_name() ? session.user.get_real_name() : session.username;
let userLabelText;
if (session.remote)
/* Translators: Remote here refers to a remote session, like a ssh login */
userLabelText = _("%s (remote)").format(userName);
else if (session.type == "tty")
/* Translators: Console here refers to a tty like a VT console */
userLabelText = _("%s (console)").format(userName);
else
userLabelText = userName;
let actor = new St.BoxLayout({ style_class: 'end-session-dialog-session-list-item',
can_focus: true });
actor.add(avatar.actor);
let nameLabel = new St.Label({ text: userLabelText,
style_class: 'end-session-dialog-session-list-item-name',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
actor.add(nameLabel);
actor.label_actor = nameLabel;
return actor;
},
_loadSessions: function() {
this._loginManager.listSessions(Lang.bind(this, function(result) {
let n = 0;
for (let i = 0; i < result.length; i++) {
let[id, uid, userName, seat, sessionPath] = result[i];
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
continue;
if (proxy.State == 'closing')
continue;
if (proxy.Id == GLib.getenv('XDG_SESSION_ID'))
continue;
let session = { user: this._userManager.get_user(userName),
username: userName,
type: proxy.Type,
remote: proxy.Remote };
this._sessions.push(session);
let actor = this._constructListItemForSession(session);
this._sessionList.add(actor);
// limit the number of entries
n++;
if (n == MAX_USERS_IN_SESSION_DIALOG)
break;
}
this._sync();
}));
},
OpenAsync: function(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._inhibitors = [];
this._applicationList.destroy_all_children();
this._type = type;
this._applications = [];
this._applicationList.destroy_all_children();
this._sessions = [];
this._sessionList.destroy_all_children();
if (!(this._type in DialogContent)) {
invocation.return_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
@ -493,9 +554,12 @@ const EndSessionDialog = new Lang.Class({
this._onInhibitorLoaded(proxy);
}));
this._inhibitors.push(inhibitor);
this._applications.push(inhibitor);
}
if (DialogContent[type].showOtherSessions)
this._loadSessions();
this._updateButtons();
if (!this.open(timestamp)) {
@ -504,7 +568,8 @@ const EndSessionDialog = new Lang.Class({
return;
}
this._updateContent();
this._startTimer();
this._sync();
let signalId = this.connect('opened',
Lang.bind(this, function() {

View File

@ -0,0 +1,65 @@
/** -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2012 Inclusive Design Research Centre, OCAD University.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
* Author:
* Joseph Scheuhammer <clown@alum.mit.edu>
* Contributor:
* Magdalen Berns <m.berns@sms.ed.ac.uk>
*/
const Atspi = imports.gi.Atspi;
const Lang = imports.lang;
const Signals = imports.signals;
const CARETMOVED = 'object:text-caret-moved';
const STATECHANGED = 'object:state-changed';
const FocusCaretTracker = new Lang.Class({
Name: 'FocusCaretTracker',
_init: function() {
Atspi.init();
Atspi.set_timeout(250, 250);
this._atspiListener = Atspi.EventListener.new(Lang.bind(this, this._onChanged));
},
_onChanged: function(event) {
if (event.type.indexOf(STATECHANGED) == 0)
this.emit('focus-changed', event);
else if (event.type == CARETMOVED)
this.emit('caret-moved', event);
},
registerFocusListener: function() {
return this._atspiListener.register(STATECHANGED + ':focused') &&
this._atspiListener.register(STATECHANGED + ':selected');
},
registerCaretListener: function() {
return this._atspiListener.register(CARETMOVED);
},
deregisterFocusListener: function() {
return this._atspiListener.deregister(STATECHANGED + ':focused') &&
this._atspiListener.deregister(STATECHANGED + ':selected');
},
deregisterCaretListener: function() {
return this._atspiListener.deregister(CARETMOVED);
}
});
Signals.addSignalMethods(FocusCaretTracker.prototype);

View File

@ -1,14 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Lang = imports.lang;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const ICON_SIZE = 48;
const ICON_SIZE = 96;
const MIN_ICON_SIZE = 16;
const EXTRA_SPACE_ANIMATION_TIME = 0.25;
const BaseIcon = new Lang.Class({
Name: 'BaseIcon',
@ -17,7 +23,12 @@ const BaseIcon = new Lang.Class({
params = Params.parse(params, { createIcon: null,
setSizeManually: false,
showLabel: true });
this.actor = new St.Bin({ style_class: 'overview-icon',
let styleClass = 'overview-icon';
if (params.showLabel)
styleClass += ' overview-icon-with-label';
this.actor = new St.Bin({ style_class: styleClass,
x_fill: true,
y_fill: true });
this.actor._delegate = this;
@ -176,19 +187,31 @@ const IconGrid = new Lang.Class({
_init: function(params) {
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
minRows: 1,
minColumns: 1,
fillParent: false,
xAlign: St.Align.MIDDLE });
xAlign: St.Align.MIDDLE,
padWithSpacing: false });
this._rowLimit = params.rowLimit;
this._colLimit = params.columnLimit;
this._minRows = params.minRows;
this._minColumns = params.minColumns;
this._xAlign = params.xAlign;
this._fillParent = params.fillParent;
this._padWithSpacing = params.padWithSpacing;
this.topPadding = 0;
this.bottomPadding = 0;
this.rightPadding = 0;
this.leftPadding = 0;
this.actor = new St.BoxLayout({ style_class: 'icon-grid',
vertical: true });
this._items = [];
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._hItemSize = this._vItemSize = ICON_SIZE;
this._fixedHItemSize = this._fixedVItemSize = undefined;
this._grid = new Shell.GenericContainer();
this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
@ -208,12 +231,12 @@ const IconGrid = new Lang.Class({
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
let totalSpacing = Math.max(0, nColumns - 1) * this._spacing;
let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing();
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
alloc.min_size = this._hItemSize;
alloc.natural_size = nColumns * this._hItemSize + totalSpacing;
alloc.min_size = this._getHItemSize() + this.leftPadding + this.rightPadding;
alloc.natural_size = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
},
_getVisibleChildren: function() {
@ -231,13 +254,11 @@ const IconGrid = new Lang.Class({
return;
let children = this._getVisibleChildren();
let nColumns, spacing;
if (forWidth < 0) {
let nColumns;
if (forWidth < 0)
nColumns = children.length;
spacing = this._spacing;
} else {
[nColumns, , spacing] = this._computeLayout(forWidth);
}
else
[nColumns, ] = this._computeLayout(forWidth);
let nRows;
if (nColumns > 0)
@ -246,8 +267,8 @@ const IconGrid = new Lang.Class({
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * spacing;
let height = nRows * this._vItemSize + totalSpacing;
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
alloc.min_size = height;
alloc.natural_size = height;
},
@ -263,48 +284,30 @@ const IconGrid = new Lang.Class({
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let [nColumns, usedWidth, spacing] = this._computeLayout(availWidth);
let leftPadding;
let leftEmptySpace;
switch(this._xAlign) {
case St.Align.START:
leftPadding = 0;
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftPadding = Math.floor((availWidth - usedWidth) / 2);
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftPadding = availWidth - usedWidth;
leftEmptySpace = availWidth - usedWidth;
}
let x = box.x1 + leftPadding;
let y = box.y1;
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
for (let i = 0; i < children.length; i++) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
= children[i].get_preferred_size();
/* Center the item in its allocation horizontally */
let width = Math.min(this._hItemSize, childNaturalWidth);
let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
let height = Math.min(this._vItemSize, childNaturalHeight);
let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
let childBox = new Clutter.ActorBox();
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
let _x = box.x2 - (x + width);
childBox.x1 = Math.floor(_x - childXSpacing);
} else {
childBox.x1 = Math.floor(x + childXSpacing);
}
childBox.y1 = Math.floor(y + childYSpacing);
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
let childBox = this._calculateChildBox(children[i], x, y, box);
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight) {
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
this._grid.set_skip_paint(children[i], true);
} else {
children[i].allocate(childBox, flags);
@ -318,15 +321,38 @@ const IconGrid = new Lang.Class({
}
if (columnIndex == 0) {
y += this._vItemSize + spacing;
x = box.x1 + leftPadding;
y += this._getVItemSize() + spacing;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else {
x += this._hItemSize + spacing;
x += this._getHItemSize() + spacing;
}
}
},
childrenInRow: function(rowWidth) {
_calculateChildBox: function(child, x, y, box) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] =
child.get_preferred_size();
/* Center the item in its allocation horizontally */
let width = Math.min(this._getHItemSize(), childNaturalWidth);
let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
let height = Math.min(this._getVItemSize(), childNaturalHeight);
let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
let childBox = new Clutter.ActorBox();
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
let _x = box.x2 - (x + width);
childBox.x1 = Math.floor(_x - childXSpacing);
} else {
childBox.x1 = Math.floor(x + childXSpacing);
}
childBox.y1 = Math.floor(y + childYSpacing);
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
return childBox;
},
columnsForWidth: function(rowWidth) {
return this._computeLayout(rowWidth)[0];
},
@ -336,26 +362,19 @@ const IconGrid = new Lang.Class({
_computeLayout: function (forWidth) {
let nColumns = 0;
let usedWidth = 0;
let spacing = this._spacing;
if (this._colLimit) {
let itemWidth = this._hItemSize * this._colLimit;
let emptyArea = forWidth - itemWidth;
spacing = Math.max(this._spacing, emptyArea / (2 * this._colLimit));
spacing = Math.round(spacing);
}
let usedWidth = this.leftPadding + this.rightPadding;
let spacing = this._getSpacing();
while ((this._colLimit == null || nColumns < this._colLimit) &&
(usedWidth + this._hItemSize <= forWidth)) {
usedWidth += this._hItemSize + spacing;
(usedWidth + this._getHItemSize() <= forWidth)) {
usedWidth += this._getHItemSize() + spacing;
nColumns += 1;
}
if (nColumns > 0)
usedWidth -= spacing;
return [nColumns, usedWidth, spacing];
return [nColumns, usedWidth];
},
_onStyleChanged: function() {
@ -366,15 +385,49 @@ const IconGrid = new Lang.Class({
this._grid.queue_relayout();
},
nRows: function(forWidth) {
let children = this._getVisibleChildren();
let nColumns = (forWidth < 0) ? children.length : this._computeLayout(forWidth)[0];
let nRows = (nColumns > 0) ? Math.ceil(children.length / nColumns) : 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
return nRows;
},
rowsForHeight: function(forHeight) {
return Math.floor((forHeight - (this.topPadding + this.bottomPadding) + this._getSpacing()) / (this._getVItemSize() + this._getSpacing()));
},
usedHeightForNRows: function(nRows) {
return (this._getVItemSize() + this._getSpacing()) * nRows - this._getSpacing() + this.topPadding + this.bottomPadding;
},
usedWidth: function(forWidth) {
return this.usedWidthForNColumns(this.columnsForWidth(forWidth));
},
usedWidthForNColumns: function(columns) {
let usedWidth = columns * (this._getHItemSize() + this._getSpacing());
usedWidth -= this._getSpacing();
return usedWidth + this.leftPadding + this.rightPadding;
},
removeAll: function() {
this._items = [];
this._grid.destroy_all_children();
},
addItem: function(actor, index) {
addItem: function(item, index) {
if (!item.icon || !item.icon instanceof BaseIcon) {
log('Only items with a BaseIcon icon property can be added to IconGrid');
return;
}
this._items.push(item);
if (index !== undefined)
this._grid.insert_child_at_index(actor, index);
this._grid.insert_child_at_index(item.actor, index);
else
this._grid.add_actor(actor);
this._grid.add_actor(item.actor);
},
getItemAtIndex: function(index) {
@ -383,5 +436,311 @@ const IconGrid = new Lang.Class({
visibleItemsCount: function() {
return this._grid.get_n_children() - this._grid.get_n_skip_paint();
},
setSpacing: function(spacing) {
this._fixedSpacing = spacing;
},
_getSpacing: function() {
return this._fixedSpacing ? this._fixedSpacing : this._spacing;
},
_getHItemSize: function() {
return this._fixedHItemSize ? this._fixedHItemSize : this._hItemSize;
},
_getVItemSize: function() {
return this._fixedVItemSize ? this._fixedVItemSize : this._vItemSize;
},
_updateSpacingForSize: function(availWidth, availHeight) {
let maxEmptyVArea = availHeight - this._minRows * this._getVItemSize();
let maxEmptyHArea = availWidth - this._minColumns * this._getHItemSize();
let maxHSpacing, maxVSpacing;
if (this._padWithSpacing) {
// minRows + 1 because we want to put spacing before the first row, so it is like we have one more row
// to divide the empty space
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows +1));
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns +1));
} else {
if (this._minRows <= 1)
maxVSpacing = maxEmptyVArea;
else
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows - 1));
if (this._minColumns <= 1)
maxHSpacing = maxEmptyHArea;
else
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns - 1));
}
let maxSpacing = Math.min(maxHSpacing, maxVSpacing);
// Limit spacing to the item size
maxSpacing = Math.min(maxSpacing, Math.min(this._getVItemSize(), this._getHItemSize()));
// The minimum spacing, regardless of whether it satisfies the row/columng minima,
// is the spacing we get from CSS.
let spacing = Math.max(this._spacing, maxSpacing);
this.setSpacing(spacing);
if (this._padWithSpacing)
this.topPadding = this.rightPadding = this.bottomPadding = this.leftPadding = spacing;
},
/**
* This function must to be called before iconGrid allocation,
* to know how much spacing can the grid has
*/
adaptToSize: function(availWidth, availHeight) {
this._fixedHItemSize = this._hItemSize;
this._fixedVItemSize = this._vItemSize;
this._updateSpacingForSize(availWidth, availHeight);
let spacing = this._getSpacing();
if (this.columnsForWidth(availWidth) < this._minColumns || this.rowsForHeight(availHeight) < this._minRows) {
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight ;
let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
if (this._fixedHItemSize < MIN_ICON_SIZE)
this._fixedHItemSize = MIN_ICON_SIZE;
if (this._fixedVItemSize < MIN_ICON_SIZE)
this._fixedVItemSize = MIN_ICON_SIZE;
this._updateSpacingForSize(availWidth, availHeight);
}
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateChildrenScale(scale); }));
},
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateChildrenScale: function(scale) {
for (let i in this._items) {
let newIconSize = Math.floor(ICON_SIZE * scale);
this._items[i].icon.setIconSize(newIconSize);
}
}
});
const PaginatedIconGrid = new Lang.Class({
Name: 'PaginatedIconGrid',
Extends: IconGrid,
_init: function(params) {
this.parent(params);
this._nPages = 0;
this._rowsPerPage = 0;
this._spaceBetweenPages = 0;
this._childrenPerPage = 0;
},
_getPreferredHeight: function (grid, forWidth, alloc) {
alloc.min_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
alloc.natural_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
},
_allocate: function (grid, box, flags) {
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
if (this._fillParent) {
// Reset the passed in box to fill the parent
let parentBox = this.actor.get_parent().allocation;
let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
box = this._grid.get_theme_node().get_content_box(gridBox);
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch(this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
children[i].allocate(childBox, flags);
this._grid.set_skip_paint(children[i], false);
columnIndex++;
if (columnIndex == nColumns) {
columnIndex = 0;
rowIndex++;
}
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage == 0)
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else
x += this._getHItemSize() + spacing;
}
},
_computePages: function (availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let nRows;
let children = this._getVisibleChildren();
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
else
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let spacing = this._getSpacing();
// We want to contain the grid inside the parent box with padding
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
this._nPages = Math.ceil(nRows / this._rowsPerPage);
this._spaceBetweenPages = availHeightPerPage - (this.topPadding + this.bottomPadding) - this._availableHeightPerPageForItems();
this._childrenPerPage = nColumns * this._rowsPerPage;
},
adaptToSize: function(availWidth, availHeight) {
this.parent(availWidth, availHeight);
this._computePages(availWidth, availHeight);
},
_availableHeightPerPageForItems: function() {
return this.usedHeightForNRows(this._rowsPerPage) - (this.topPadding + this.bottomPadding);
},
nPages: function() {
return this._nPages;
},
getPageY: function(pageNumber) {
if (!this._nPages)
return 0;
let firstPageItem = pageNumber * this._childrenPerPage
let childBox = this._getVisibleChildren()[firstPageItem].get_allocation_box();
return childBox.y1 - this.topPadding;
},
getItemPage: function(item) {
let children = this._getVisibleChildren();
let index = children.indexOf(item);
if (index == -1) {
throw new Error('Item not found.');
return 0;
}
return Math.floor(index / this._childrenPerPage);
},
/**
* openExtraSpace:
* @sourceItem: the item for which to create extra space
* @side: where @sourceItem should be located relative to the created space
* @nRows: the amount of space to create
*
* Pan view to create extra space for @nRows above or below @sourceItem.
*/
openExtraSpace: function(sourceItem, side, nRows) {
let children = this._getVisibleChildren();
let index = children.indexOf(sourceItem.actor);
if (index == -1) {
throw new Error('Item not found.');
return;
}
let pageIndex = Math.floor(index / this._childrenPerPage);
let pageOffset = pageIndex * this._childrenPerPage;
let childrenPerRow = this._childrenPerPage / this._rowsPerPage;
let sourceRow = Math.floor((index - pageOffset) / childrenPerRow);
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1
: sourceRow;
let nRowsBelow = this._rowsPerPage - nRowsAbove;
let nRowsUp, nRowsDown;
if (side == St.Side.TOP) {
nRowsDown = Math.min(nRowsBelow, nRows);
nRowsUp = nRows - nRowsDown;
} else {
nRowsUp = Math.min(nRowsAbove, nRows);
nRowsDown = nRows - nRowsUp;
}
let childrenDown = children.splice(pageOffset +
nRowsAbove * childrenPerRow,
nRowsBelow * childrenPerRow);
let childrenUp = children.splice(pageOffset,
nRowsAbove * childrenPerRow);
// Special case: On the last row with no rows below the icon,
// there's no need to move any rows either up or down
if (childrenDown.length == 0 && nRowsUp == 0) {
this._translatedChildren = [];
this.emit('space-opened');
} else {
this._translateChildren(childrenUp, Gtk.DirectionType.UP, nRowsUp);
this._translateChildren(childrenDown, Gtk.DirectionType.DOWN, nRowsDown);
this._translatedChildren = childrenUp.concat(childrenDown);
}
},
_translateChildren: function(children, direction, nRows) {
let translationY = nRows * (this._getVItemSize() + this._getSpacing());
if (translationY == 0)
return;
if (direction == Gtk.DirectionType.UP)
translationY *= -1;
for (let i = 0; i < children.length; i++) {
children[i].translation_y = 0;
let params = { translation_y: translationY,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad'
};
if (i == (children.length - 1))
params.onComplete = Lang.bind(this,
function() {
this.emit('space-opened');
});
Tweener.addTween(children[i], params);
}
},
closeExtraSpace: function() {
if (!this._translatedChildren || !this._translatedChildren.length) {
this.emit('space-closed');
return;
}
for (let i = 0; i < this._translatedChildren.length; i++) {
if (!this._translatedChildren[i].translation_y)
continue;
Tweener.addTween(this._translatedChildren[i],
{ translation_y: 0,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad',
onComplete: Lang.bind(this,
function() {
this.emit('space-closed');
})
});
}
}
});
Signals.addSignalMethods(PaginatedIconGrid.prototype);

View File

@ -251,7 +251,7 @@ const LayoutManager = new Lang.Class({
this._inOverview = true;
this._updateVisibility();
this._queueUpdateRegions();
this._updateRegions();
},
hideOverview: function() {
@ -362,7 +362,7 @@ const LayoutManager = new Lang.Class({
BackgroundMenu.addBackgroundMenu(bgManager.background.actor);
}));
this._bgManagers.push(bgManager);
this._bgManagers[monitorIndex] = bgManager;
return bgManager.background;
},

View File

@ -920,7 +920,7 @@ const LookingGlass = new Lang.Class({
let text = o.get_text();
// Ensure we don't get newlines in the command; the history file is
// newline-separated.
text.replace('\n', ' ');
text = text.replace('\n', ' ');
// Strip leading and trailing whitespace
text = text.replace(/^\s+/g, '').replace(/\s+$/g, '');
if (text == '')
@ -1072,15 +1072,15 @@ const LookingGlass = new Lang.Class({
let myWidth = primary.width * 0.7;
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.actor.x = (primary.width - myWidth) / 2;
this._hiddenY = Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
this.actor.x = primary.x + (primary.width - myWidth) / 2;
this._hiddenY = primary.y + Main.layoutManager.panelBox.height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
this.actor.width = myWidth;
this.actor.height = myHeight;
this._objInspector.actor.set_size(Math.floor(myWidth * 0.8), Math.floor(myHeight * 0.8));
this._objInspector.actor.set_position(primary.x + this.actor.x + Math.floor(myWidth * 0.1),
primary.y + this._targetY + Math.floor(myHeight * 0.1));
this._objInspector.actor.set_position(this.actor.x + Math.floor(myWidth * 0.1),
this._targetY + Math.floor(myHeight * 0.1));
},
insertObject: function(obj) {

View File

@ -1,5 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Atspi = imports.gi.Atspi;
const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
@ -10,6 +11,7 @@ const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const FocusCaretTracker = imports.ui.focusCaretTracker;
const Main = imports.ui.main;
const MagnifierDBus = imports.ui.magnifierDBus;
const Params = imports.misc.params;
@ -37,6 +39,8 @@ const CONTRAST_BLUE_KEY = 'contrast-blue';
const LENS_MODE_KEY = 'lens-mode';
const CLAMP_MODE_KEY = 'scroll-at-edges';
const MOUSE_TRACKING_KEY = 'mouse-tracking';
const FOCUS_TRACKING_KEY = 'focus-tracking';
const CARET_TRACKING_KEY = 'caret-tracking';
const SHOW_CROSS_HAIRS_KEY = 'show-cross-hairs';
const CROSS_HAIRS_THICKNESS_KEY = 'cross-hairs-thickness';
const CROSS_HAIRS_COLOR_KEY = 'cross-hairs-color';
@ -53,6 +57,20 @@ const Magnifier = new Lang.Class({
// Magnifier is a manager of ZoomRegions.
this._zoomRegions = [];
// Export to dbus.
magDBusService = new MagnifierDBus.ShellMagnifier();
let showAtLaunch = this._settingsInit();
this.setActive(showAtLaunch);
},
_initialize: function() {
if (this._initialized)
return;
this._initialized = true;
this._settingsInitLate();
// Create small clutter tree for the magnified mouse.
let cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
this._mouseSprite = new Clutter.Texture();
@ -68,15 +86,11 @@ const Magnifier = new Lang.Class({
let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
this._zoomRegions.push(aZoomRegion);
let showAtLaunch = this._settingsInit(aZoomRegion);
this._settingsInitRegion(aZoomRegion);
aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
cursorTracker.connect('cursor-changed', Lang.bind(this, this._updateMouseSprite));
this._cursorTracker = cursorTracker;
// Export to dbus.
magDBusService = new MagnifierDBus.ShellMagnifier();
this.setActive(showAtLaunch);
},
/**
@ -84,7 +98,7 @@ const Magnifier = new Lang.Class({
* Show the system mouse pointer.
*/
showSystemCursor: function() {
global.stage.show_cursor();
this._cursorTracker.set_pointer_visible(true);
},
/**
@ -92,7 +106,7 @@ const Magnifier = new Lang.Class({
* Hide the system mouse pointer.
*/
hideSystemCursor: function() {
global.stage.hide_cursor();
this._cursorTracker.set_pointer_visible(false);
},
/**
@ -101,6 +115,12 @@ const Magnifier = new Lang.Class({
* @activate: Boolean to activate or de-activate the magnifier.
*/
setActive: function(activate) {
if (activate == this.isActive())
return;
if (activate)
this._initialize();
this._zoomRegions.forEach (function(zoomRegion, index, array) {
zoomRegion.setActive(activate);
});
@ -113,7 +133,7 @@ const Magnifier = new Lang.Class({
// Make sure system mouse pointer is shown when all zoom regions are
// invisible.
if (!activate)
global.stage.show_cursor();
this._cursorTracker.set_pointer_visible(true);
// Notify interested parties of this change
this.emit('active-changed', activate);
@ -428,56 +448,68 @@ const Magnifier = new Lang.Class({
this._mouseSprite.set_anchor_point(xHot, yHot);
},
_settingsInit: function(zoomRegion) {
_settingsInitRegion: function(zoomRegion) {
// Mag factor is accurate to two decimal places.
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
if (aPref != 0.0)
zoomRegion.setMagFactor(aPref, aPref);
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
if (aPref)
zoomRegion.setScreenPosition(aPref);
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
if (aPref)
zoomRegion.setMouseTrackingMode(aPref);
aPref = this._settings.get_enum(FOCUS_TRACKING_KEY);
if (aPref)
zoomRegion.setFocusTrackingMode(aPref);
aPref = this._settings.get_enum(CARET_TRACKING_KEY);
if (aPref)
zoomRegion.setCaretTrackingMode(aPref);
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
if (aPref)
zoomRegion.setInvertLightness(aPref);
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
if (aPref)
zoomRegion.setColorSaturation(aPref);
let bc = {};
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
zoomRegion.setBrightness(bc);
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
zoomRegion.setContrast(bc);
},
_settingsInit: function() {
this._appSettings = new Gio.Settings({ schema: APPLICATIONS_SCHEMA });
this._settings = new Gio.Settings({ schema: MAGNIFIER_SCHEMA });
if (zoomRegion) {
// Mag factor is accurate to two decimal places.
let aPref = parseFloat(this._settings.get_double(MAG_FACTOR_KEY).toFixed(2));
if (aPref != 0.0)
zoomRegion.setMagFactor(aPref, aPref);
this._appSettings.connect('changed::' + SHOW_KEY, Lang.bind(this, function() {
let active = this._appSettings.get_boolean(SHOW_KEY);
this.setActive(active);
}));
aPref = this._settings.get_enum(SCREEN_POSITION_KEY);
if (aPref)
zoomRegion.setScreenPosition(aPref);
zoomRegion.setLensMode(this._settings.get_boolean(LENS_MODE_KEY));
zoomRegion.setClampScrollingAtEdges(!this._settings.get_boolean(CLAMP_MODE_KEY));
aPref = this._settings.get_enum(MOUSE_TRACKING_KEY);
if (aPref)
zoomRegion.setMouseTrackingMode(aPref);
aPref = this._settings.get_boolean(INVERT_LIGHTNESS_KEY);
if (aPref)
zoomRegion.setInvertLightness(aPref);
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
if (aPref)
zoomRegion.setColorSaturation(aPref);
let bc = {};
bc.r = this._settings.get_double(BRIGHT_RED_KEY);
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
bc.b = this._settings.get_double(BRIGHT_BLUE_KEY);
zoomRegion.setBrightness(bc);
bc.r = this._settings.get_double(CONTRAST_RED_KEY);
bc.g = this._settings.get_double(CONTRAST_GREEN_KEY);
bc.b = this._settings.get_double(CONTRAST_BLUE_KEY);
zoomRegion.setContrast(bc);
}
return this._appSettings.get_boolean(SHOW_KEY);
},
_settingsInitLate: function() {
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
this.addCrosshairs();
this.setCrosshairsVisible(showCrosshairs);
this._appSettings.connect('changed::' + SHOW_KEY,
Lang.bind(this, function() {
this.setActive(this._appSettings.get_boolean(SHOW_KEY));
}));
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
Lang.bind(this, this._updateScreenPosition));
this._settings.connect('changed::' + MAG_FACTOR_KEY,
@ -488,6 +520,10 @@ const Magnifier = new Lang.Class({
Lang.bind(this, this._updateClampMode));
this._settings.connect('changed::' + MOUSE_TRACKING_KEY,
Lang.bind(this, this._updateMouseTrackingMode));
this._settings.connect('changed::' + FOCUS_TRACKING_KEY,
Lang.bind(this, this._updateFocusTrackingMode));
this._settings.connect('changed::' + CARET_TRACKING_KEY,
Lang.bind(this, this._updateCaretTrackingMode));
this._settings.connect('changed::' + INVERT_LIGHTNESS_KEY,
Lang.bind(this, this._updateInvertLightness));
@ -537,8 +573,6 @@ const Magnifier = new Lang.Class({
Lang.bind(this, function() {
this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY));
}));
return this._appSettings.get_boolean(SHOW_KEY);
},
_updateScreenPosition: function() {
@ -585,6 +619,24 @@ const Magnifier = new Lang.Class({
}
},
_updateFocusTrackingMode: function() {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setFocusTrackingMode(
this._settings.get_enum(FOCUS_TRACKING_KEY)
);
}
},
_updateCaretTrackingMode: function() {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setCaretTrackingMode(
this._settings.get_enum(CARET_TRACKING_KEY)
);
}
},
_updateInvertLightness: function() {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
@ -623,7 +675,7 @@ const Magnifier = new Lang.Class({
contrast.b = this._settings.get_double(CONTRAST_BLUE_KEY);
this._zoomRegions[0].setContrast(contrast);
}
},
}
});
Signals.addSignalMethods(Magnifier.prototype);
@ -632,8 +684,11 @@ const ZoomRegion = new Lang.Class({
_init: function(magnifier, mouseSourceActor) {
this._magnifier = magnifier;
this._focusCaretTracker = new FocusCaretTracker.FocusCaretTracker();
this._mouseTrackingMode = GDesktopEnums.MagnifierMouseTrackingMode.NONE;
this._focusTrackingMode = GDesktopEnums.MagnifierFocusTrackingMode.NONE;
this._caretTrackingMode = GDesktopEnums.MagnifierCaretTrackingMode.NONE;
this._clampScrollingAtEdges = false;
this._lensMode = false;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
@ -659,9 +714,35 @@ const ZoomRegion = new Lang.Class({
this._xMagFactor = 1;
this._yMagFactor = 1;
this._followingCursor = false;
this._xFocus = 0;
this._yFocus = 0;
this._xCaret = 0;
this._yCaret = 0;
Main.layoutManager.connect('monitors-changed',
Lang.bind(this, this._monitorsChanged));
this._focusCaretTracker.connect('caret-moved',
Lang.bind(this, this._updateCaret));
this._focusCaretTracker.connect('focus-changed',
Lang.bind(this, this._updateFocus));
},
_updateFocus: function(caller, event) {
let component = event.source.get_component_iface();
if (!component || event.detail1 != 1)
return;
let extents = component.get_extents(Atspi.CoordType.SCREEN);
[this._xFocus, this._yFocus] = [extents.x, extents.y]
this._centerFromFocusPosition();
},
_updateCaret: function(caller, event) {
let text = event.source.get_text_iface();
if (!text)
return;
let extents = text.get_character_extents(text.get_caret_offset(), 0);
[this._xCaret, this._yCaret] = [extents.x, extents.y];
this._centerFromCaretPosition();
},
/**
@ -669,14 +750,17 @@ const ZoomRegion = new Lang.Class({
* @activate: Boolean to show/hide the ZoomRegion.
*/
setActive: function(activate) {
if (activate && !this.isActive()) {
if (activate == this.isActive())
return;
if (activate) {
this._createActors();
if (this._isMouseOverRegion())
this._magnifier.hideSystemCursor();
this._updateMagViewGeometry();
this._updateCloneGeometry();
this._updateMousePosition();
} else if (!activate && this.isActive()) {
} else {
this._destroyActors();
}
},
@ -732,6 +816,30 @@ const ZoomRegion = new Lang.Class({
return this._mouseTrackingMode;
},
/**
* setFocusTrackingMode
* @mode: One of the enum FocusTrackingMode values.
*/
setFocusTrackingMode: function(mode) {
this._focusTrackingMode = mode;
if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.NONE)
this._focusCaretTracker.deregisterFocusListener();
else
this._focusCaretTracker.registerFocusListener();
},
/**
* setCaretTrackingMode
* @mode: One of the enum CaretTrackingMode values.
*/
setCaretTrackingMode: function(mode) {
this._caretTrackingMode = mode;
if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.NONE)
this._focusCaretTracker.deregisterCaretListener();
else
this._focusCaretTracker.registerCaretListener();
},
/**
* setViewPort
* Sets the position and size of the ZoomRegion on screen.
@ -1023,20 +1131,6 @@ const ZoomRegion = new Lang.Class({
this._magShaderEffects.setBrightness(this._brightness);
},
/**
* getBrightness:
* Retrive the current brightness of the Zoom Region.
* @return Object containing the brightness change for the red, green,
* and blue channels.
*/
getBrightness: function() {
let brightness = {};
brightness.r = this._brightness.r;
brightness.g = this._brightness.g;
brightness.b = this._brightness.b;
return brightness;
},
/**
* setContrast:
* Alter the contrast of the magnified view.
@ -1243,19 +1337,47 @@ const ZoomRegion = new Lang.Class({
let yMouse = this._magnifier.yMouse;
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
return this._centerFromMouseProportional(xMouse, yMouse);
return this._centerFromPointProportional(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
return this._centerFromMousePush(xMouse, yMouse);
return this._centerFromPointPush(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
return this._centerFromMouseCentered(xMouse, yMouse);
return this._centerFromPointCentered(xMouse, yMouse);
}
return null; // Should never be hit
},
_centerFromMousePush: function(xMouse, yMouse) {
_centerFromCaretPosition: function() {
let xCaret = this._xCaret;
let yCaret = this._yCaret;
if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.PROPORTIONAL)
[xCaret, yCaret] = this._centerFromPointProportional(xCaret, yCaret);
else if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.PUSH)
[xCaret, yCaret] = this._centerFromPointPush(xCaret, yCaret);
else if (this._caretTrackingMode == GDesktopEnums.MagnifierCaretTrackingMode.CENTERED)
[xCaret, yCaret] = this._centerFromPointCentered(xCaret, yCaret);
this.scrollContentsTo(xCaret, yCaret);
},
_centerFromFocusPosition: function() {
let xFocus = this._xFocus;
let yFocus = this._yFocus;
if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.PROPORTIONAL)
[xFocus, yFocus] = this._centerFromPointProportional(xFocus, yFocus);
else if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.PUSH)
[xFocus, yFocus] = this._centerFromPointPush(xFocus, yFocus);
else if (this._focusTrackingMode == GDesktopEnums.MagnifierFocusTrackingMode.CENTERED)
[xFocus, yFocus] = this._centerFromPointCentered(xFocus, yFocus);
this.scrollContentsTo(xFocus, yFocus);
},
_centerFromPointPush: function(xPoint, yPoint) {
let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI();
let [cursorWidth, cursorHeight] = this._mouseSourceActor.get_size();
let xPos = xRoi + widthRoi / 2;
@ -1263,20 +1385,20 @@ const ZoomRegion = new Lang.Class({
let xRoiRight = xRoi + widthRoi - cursorWidth;
let yRoiBottom = yRoi + heightRoi - cursorHeight;
if (xMouse < xRoi)
xPos -= (xRoi - xMouse);
else if (xMouse > xRoiRight)
xPos += (xMouse - xRoiRight);
if (xPoint < xRoi)
xPos -= (xRoi - xPoint);
else if (xPoint > xRoiRight)
xPos += (xPoint - xRoiRight);
if (yMouse < yRoi)
yPos -= (yRoi - yMouse);
else if (yMouse > yRoiBottom)
yPos += (yMouse - yRoiBottom);
if (yPoint < yRoi)
yPos -= (yRoi - yPoint);
else if (yPoint > yRoiBottom)
yPos += (yPoint - yRoiBottom);
return [xPos, yPos];
},
_centerFromMouseProportional: function(xMouse, yMouse) {
_centerFromPointProportional: function(xPoint, yPoint) {
let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI();
let halfScreenWidth = global.screen_width / 2;
let halfScreenHeight = global.screen_height / 2;
@ -1285,16 +1407,16 @@ const ZoomRegion = new Lang.Class({
let unscaledPadding = Math.min(this._viewPortWidth, this._viewPortHeight) / 5;
let xPadding = unscaledPadding / this._xMagFactor;
let yPadding = unscaledPadding / this._yMagFactor;
let xProportion = (xMouse - halfScreenWidth) / halfScreenWidth; // -1 ... 1
let yProportion = (yMouse - halfScreenHeight) / halfScreenHeight; // -1 ... 1
let xPos = xMouse - xProportion * (widthRoi / 2 - xPadding);
let yPos = yMouse - yProportion * (heightRoi /2 - yPadding);
let xProportion = (xPoint - halfScreenWidth) / halfScreenWidth; // -1 ... 1
let yProportion = (yPoint - halfScreenHeight) / halfScreenHeight; // -1 ... 1
let xPos = xPoint - xProportion * (widthRoi / 2 - xPadding);
let yPos = yPoint - yProportion * (heightRoi /2 - yPadding);
return [xPos, yPos];
},
_centerFromMouseCentered: function(xMouse, yMouse) {
return [xMouse, yMouse];
_centerFromPointCentered: function(xPoint, yPoint) {
return [xPoint, yPoint];
},
_screenToViewPort: function(screenX, screenY) {
@ -1511,15 +1633,6 @@ const Crosshairs = new Lang.Class({
this._vertBottomHair.set_opacity(opacity);
},
/**
* getOpacity:
* Retriev how opaque the crosshairs are.
* @return: A value between 0 (transparent) and 255 (opaque).
*/
getOpacity: function() {
return this._horizLeftHair.get_opacity();
},
/**
* setLength:
* Set the length of the vertical and horizontal lines in the crosshairs.
@ -1563,15 +1676,6 @@ const Crosshairs = new Lang.Class({
}
},
/**
* getClip:
* Get the dimensions of the clip rectangle.
* @return: An array of the form [width, height].
*/
getClip: function() {
return this._clipSize;
},
/**
* show:
* Show the crosshairs.
@ -1667,23 +1771,10 @@ const MagShaderEffects = new Lang.Class({
this._inverse.set_enabled(invertFlag);
},
/**
* getInvertLightness:
* Report whether the inversion effect is enabled.
* @return: Boolean.
*/
getInvertLightness: function() {
return this._inverse.get_enabled();
},
setColorSaturation: function(factor) {
this._colorDesaturation.set_factor(1.0 - factor);
},
getColorSaturation: function() {
return 1.0 - this._colorDesaturation.get_factor();
},
/**
* setBrightness:
* Set the brightness of the magnified view.
@ -1708,24 +1799,6 @@ const MagShaderEffects = new Lang.Class({
);
},
/**
* getBrightness:
* Retrieve current brightness of the magnified view.
* @return: Object containing the brightness for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* brightness (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed brightness, respectively.
*/
getBrightness: function() {
let result = {};
let [bRed, bGreen, bBlue] = this._brightnessContrast.get_brightness();
result.r = bRed;
result.g = bGreen;
result.b = bBlue;
return result;
},
/**
* Set the contrast of the magnified view.
* @contrast: Object containing the contrast for the red, green,
@ -1750,21 +1823,4 @@ const MagShaderEffects = new Lang.Class({
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
);
},
/**
* Retrieve current contrast of the magnified view.
* @return: Object containing the contrast for the red, green,
* and blue channels. Values of 0.0 represent "standard"
* contrast (no change), whereas values less or greater than
* 0.0 indicate decreased or incresaed contrast, respectively.
*/
getContrast: function() {
let resutl = {};
let [cRed, cGreen, cBlue] = this._brightnessContrast.get_contrast();
result.r = cRed;
result.g = cGreen;
result.b = cBlue;
return result;
}
});

View File

@ -4,14 +4,12 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Main = imports.ui.main;
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
const MAG_SERVICE_PATH = '/org/gnome/Magnifier';
const ZOOM_SERVICE_NAME = 'org.gnome.Magnifier.ZoomRegion';
const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
const MagnifierIface = <interface name="org.gnome.Magnifier">
<method name="setActive">
<arg type="b" direction="in" />
</method>
@ -66,7 +64,7 @@ const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
const ZoomRegionIface = <interface name="org.gnome.Magnifier.ZoomRegion">
<method name="setMagFactor">
<arg type="d" direction="in" />
<arg type="d" direction="in" />

View File

@ -90,8 +90,12 @@ function _sessionUpdated() {
Shell.KeyBindingMode.OVERVIEW,
sessionMode.hasRunDialog ? openRunDialog : null);
if (!sessionMode.hasRunDialog && lookingGlass)
lookingGlass.close();
if (!sessionMode.hasRunDialog) {
if (runDialog)
runDialog.close();
if (lookingGlass)
lookingGlass.close();
}
}
function start() {
@ -99,6 +103,9 @@ function start() {
global.logError = window.log;
global.log = window.log;
if (!Meta.is_wayland_compositor)
Meta.is_wayland_compositor = function () { return false; };
// Chain up async errors reported from C
global.connect('notify-error', function (global, msg, detail) { notifyError(msg, detail); });

View File

@ -215,10 +215,10 @@ const URLHighlighter = new Lang.Class({
let urlId = this._findUrlAtPos(event);
if (urlId != -1 && !this._cursorChanged) {
global.set_cursor(Shell.Cursor.POINTING_HAND);
global.screen.set_cursor(Meta.Cursor.POINTING_HAND);
this._cursorChanged = true;
} else if (urlId == -1) {
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
this._cursorChanged = false;
}
return false;
@ -229,7 +229,7 @@ const URLHighlighter = new Lang.Class({
if (this._cursorChanged) {
this._cursorChanged = false;
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
}
}));
},
@ -310,6 +310,126 @@ const NotificationPolicy = new Lang.Class({
});
Signals.addSignalMethods(NotificationPolicy.prototype);
const NotificationGenericPolicy = new Lang.Class({
Name: 'NotificationGenericPolicy',
Extends: NotificationPolicy,
_init: function() {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
},
store: function() { },
destroy: function() {
this._masterSettings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
get enable() {
return true;
},
get enableSound() {
return true;
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners');
},
get forceExpanded() {
return false;
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return false;
}
});
const NotificationApplicationPolicy = new Lang.Class({
Name: 'NotificationApplicationPolicy',
Extends: NotificationPolicy,
_init: function(id) {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = id;
this._canonicalId = this._canonicalizeId(id);
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
this._settings.connect('changed', Lang.bind(this, this._changed));
},
store: function() {
this._settings.set_string('application-id', this.id + '.desktop');
let apps = this._masterSettings.get_strv('application-children');
if (apps.indexOf(this._canonicalId) < 0) {
apps.push(this._canonicalId);
this._masterSettings.set_strv('application-children', apps);
}
},
destroy: function() {
this._masterSettings.run_dispose();
this._settings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
_canonicalizeId: function(id) {
// Keys are restricted to lowercase alphanumeric characters and dash,
// and two dashes cannot be in succession
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
},
get enable() {
return this._settings.get_boolean('enable');
},
get enableSound() {
return this._settings.get_boolean('enable-sound-alerts');
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners') &&
this._settings.get_boolean('show-banners');
},
get forceExpanded() {
return this._settings.get_boolean('force-expanded');
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen') &&
this._settings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen');
}
});
// Notification:
// @source: the notification's Source
// @title: the title
@ -438,7 +558,12 @@ const Notification = new Lang.Class({
this._bannerLabel = this._bannerUrlHighlighter.actor;
this._bannerBox.add_actor(this._bannerLabel);
this.update(title, banner, params);
// If called with only one argument we assume the caller
// will call .update() later on. This is the case of
// NotificationDaemon, which wants to use the same code
// for new and updated notifications
if (arguments.length != 1)
this.update(title, banner, params);
},
// update:
@ -723,7 +848,6 @@ const Notification = new Lang.Class({
// %action-invoked signal with @id as a parameter
addButton: function(id, label) {
if (!this._buttonBox) {
let box = new St.BoxLayout({ style_class: 'notification-actions' });
this.setActionArea(box, { x_expand: false,
y_expand: false,
@ -731,6 +855,7 @@ const Notification = new Lang.Class({
y_fill: false,
x_align: St.Align.END });
this._buttonBox = box;
global.focus_manager.add_group(this._buttonBox);
}
let button = new St.Button({ can_focus: true });
@ -745,11 +870,7 @@ const Notification = new Lang.Class({
button.label = label;
}
if (this._buttonBox.get_n_children() > 0)
global.focus_manager.remove_group(this._buttonBox);
this._buttonBox.add(button);
global.focus_manager.add_group(this._buttonBox);
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id));
this.updated();
@ -1206,6 +1327,10 @@ const Source = new Lang.Class({
return this.count > 1;
},
get isClearable() {
return !this.trayIcon && !this.isChat && !this.resident;
},
countUpdated: function() {
this.emit('count-updated');
},
@ -1277,25 +1402,27 @@ const Source = new Lang.Class({
return this._mainIcon.actor;
},
_onNotificationDestroy: function(notification) {
let index = this.notifications.indexOf(notification);
if (index < 0)
return;
this.notifications.splice(index, 1);
if (this.notifications.length == 0)
this._lastNotificationRemoved();
this.countUpdated();
},
pushNotification: function(notification) {
if (this.notifications.indexOf(notification) < 0) {
this.notifications.push(notification);
this.emit('notification-added', notification);
}
if (this.notifications.indexOf(notification) >= 0)
return;
notification.connect('clicked', Lang.bind(this, this.open));
notification.connect('destroy', Lang.bind(this,
function () {
let index = this.notifications.indexOf(notification);
if (index < 0)
return;
notification.connect('destroy', Lang.bind(this, this._onNotificationDestroy));
this.notifications.splice(index, 1);
if (this.notifications.length == 0)
this._lastNotificationRemoved();
this.countUpdated();
}));
this.notifications.push(notification);
this.emit('notification-added', notification);
this.countUpdated();
},
@ -1507,26 +1634,42 @@ const MessageTrayMenu = new Lang.Class({
this._tray = tray;
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
if (error) {
logError(error, 'Error while reading gnome-session presence');
return;
}
this._onStatusChanged(proxy.status);
}));
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._onStatusChanged(status);
}));
this._accountManager = Tp.AccountManager.dup();
this._accountManager.connect('most-available-presence-changed',
Lang.bind(this, this._onIMPresenceChanged));
this._accountManager.prepare_async(null, Lang.bind(this, this._onIMPresenceChanged));
this.actor.hide();
Main.layoutManager.addChrome(this.actor);
this._busyItem = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
this._busyItem.connect('toggled', Lang.bind(this, this._updatePresence));
this.addMenuItem(this._busyItem);
let separator = new PopupMenu.PopupSeparatorMenuItem();
this.addMenuItem(separator);
this._clearItem = this.addAction(_("Clear Messages"), function() {
let toDestroy = [];
let sources = tray.getSources();
for (let i = 0; i < sources.length; i++) {
// We exclude trayIcons, chat and resident sources
if (sources[i].trayIcon ||
sources[i].isChat ||
sources[i].resident)
continue;
toDestroy.push(sources[i]);
}
let toDestroy = tray.getSources().filter(function(source) {
return source.isClearable;
})
for (let i = 0; i < toDestroy.length; i++) {
toDestroy[i].destroy();
}
toDestroy.forEach(function(source) {
source.destroy();
});
toDestroy = null;
tray.close();
});
@ -1541,9 +1684,43 @@ const MessageTrayMenu = new Lang.Class({
settingsItem.connect('activate', function() { tray.close(); });
},
_onStatusChanged: function(status) {
this._sessionStatus = status;
this._busyItem.setToggleState(status != GnomeSession.PresenceStatus.BUSY);
},
_onIMPresenceChanged: function(am, type) {
if (type == Tp.ConnectionPresenceType.AVAILABLE &&
this._sessionStatus == GnomeSession.PresenceStatus.BUSY)
this._presence.SetStatusRemote(GnomeSession.PresenceStatus.AVAILABLE);
},
_updateClearSensitivity: function() {
this._clearItem.setSensitive(this._tray.clearableCount > 0);
},
_updatePresence: function(item, state) {
let status = state ? GnomeSession.PresenceStatus.AVAILABLE
: GnomeSession.PresenceStatus.BUSY;
this._presence.SetStatusRemote(status);
let [type, s ,msg] = this._accountManager.get_most_available_presence();
let newType = 0;
let newStatus;
if (status == GnomeSession.PresenceStatus.BUSY &&
type == Tp.ConnectionPresenceType.AVAILABLE) {
newType = Tp.ConnectionPresenceType.BUSY;
newStatus = 'busy';
} else if (status == GnomeSession.PresenceStatus.AVAILABLE &&
type == Tp.ConnectionPresenceType.BUSY) {
newType = Tp.ConnectionPresenceType.AVAILABLE;
newStatus = 'available';
}
if (newType > 0)
this._accountManager.set_all_requested_presences(newType,
newStatus, msg);
}
});
const MessageTrayMenuButton = new Lang.Class({
@ -1685,7 +1862,7 @@ const MessageTray = new Lang.Class({
this._userActiveWhileNotificationShown = false;
this.idleMonitor = new GnomeDesktop.IdleMonitor();
this.idleMonitor = Meta.IdleMonitor.get_core();
this._grabHelper = new GrabHelper.GrabHelper(this.actor,
{ keybindingMode: Shell.KeyBindingMode.MESSAGE_TRAY });
@ -1805,8 +1982,9 @@ const MessageTray = new Lang.Class({
},
_sessionUpdated: function() {
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) {
Main.ctrlAltTabManager.removeGroup(this._summary);
if (Main.sessionMode.isLocked || Main.sessionMode.isGreeter) {
if (this._inCtrlAltTab)
Main.ctrlAltTabManager.removeGroup(this._summary);
this._inCtrlAltTab = false;
} else if (!this._inCtrlAltTab) {
Main.ctrlAltTabManager.addGroup(this._summary, _("Message Tray"), 'user-available-symbolic',
@ -1925,7 +2103,7 @@ const MessageTray = new Lang.Class({
this._summary.insert_child_at_index(summaryItem.actor, this._chatSummaryItemsCount);
}
if (!source.trayIcon && !source.isChat && !source.resident)
if (source.isClearable)
this.clearableCount++;
this._sources.set(source, obj);
@ -1969,7 +2147,7 @@ const MessageTray = new Lang.Class({
if (source.isChat)
this._chatSummaryItemsCount--;
if (!source.trayIcon && !source.isChat && !source.resident)
if (source.isClearable)
this.clearableCount--;
source.disconnect(obj.notifyId);
@ -2732,6 +2910,7 @@ const MessageTray = new Lang.Class({
_onSummaryBoxPointerUngrabbed: function() {
this._summaryBoxPointerState = State.HIDING;
this._setClickedSummaryItem(null);
if (this._summaryBoxPointerContentUpdatedId) {
this._summaryBoxPointerItem.disconnect(this._summaryBoxPointerContentUpdatedId);

View File

@ -103,126 +103,6 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'keyboard'
};
const NotificationGenericPolicy = new Lang.Class({
Name: 'NotificationGenericPolicy',
Extends: MessageTray.NotificationPolicy,
_init: function() {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = 'generic';
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
},
store: function() { },
destroy: function() {
this._masterSettings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
get enable() {
return true;
},
get enableSound() {
return true;
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners');
},
get forceExpanded() {
return false;
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return false;
}
});
const NotificationApplicationPolicy = new Lang.Class({
Name: 'NotificationApplicationPolicy',
Extends: MessageTray.NotificationPolicy,
_init: function(id) {
// Don't chain to parent, it would try setting
// our properties to the defaults
this.id = id;
this._canonicalId = this._canonicalizeId(id)
this._masterSettings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.notifications.application',
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
this._masterSettings.connect('changed', Lang.bind(this, this._changed));
this._settings.connect('changed', Lang.bind(this, this._changed));
},
store: function() {
this._settings.set_string('application-id', this.id + '.desktop');
let apps = this._masterSettings.get_strv('application-children');
if (apps.indexOf(this._canonicalId) < 0) {
apps.push(this._canonicalId);
this._masterSettings.set_strv('application-children', apps);
}
},
destroy: function() {
this._masterSettings.run_dispose();
this._settings.run_dispose();
},
_changed: function(settings, key) {
this.emit('policy-changed', key);
},
_canonicalizeId: function(id) {
// Keys are restricted to lowercase alphanumeric characters and dash,
// and two dashes cannot be in succession
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
},
get enable() {
return this._settings.get_boolean('enable');
},
get enableSound() {
return this._settings.get_boolean('enable-sound-alerts');
},
get showBanners() {
return this._masterSettings.get_boolean('show-banners') &&
this._settings.get_boolean('show-banners');
},
get forceExpanded() {
return this._settings.get_boolean('force-expanded');
},
get showInLockScreen() {
return this._masterSettings.get_boolean('show-in-lock-screen') &&
this._settings.get_boolean('show-in-lock-screen');
},
get detailsInLockScreen() {
return this._settings.get_boolean('details-in-lock-screen');
}
});
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
@ -396,12 +276,13 @@ const NotificationDaemon = new Lang.Class({
if (!hints['image-path'] && hints['image_path'])
hints['image-path'] = hints['image_path']; // version 1.1 of the spec
if (!hints['image-data'])
if (!hints['image-data']) {
if (hints['image_data'])
hints['image-data'] = hints['image_data']; // version 1.1 of the spec
else if (hints['icon_data'] && !hints['image-path'])
// early versions of the spec; 'icon_data' should only be used if 'image-path' is not available
hints['image-data'] = hints['icon_data'];
}
let ndata = { appName: appName,
icon: icon,
@ -674,9 +555,9 @@ const Source = new Lang.Class({
_createPolicy: function() {
if (this.app) {
let id = this.app.get_id().replace(/\.desktop$/,'');
return new NotificationApplicationPolicy(id);
return new MessageTray.NotificationApplicationPolicy(id);
} else {
return new NotificationGenericPolicy();
return new MessageTray.NotificationGenericPolicy();
}
},
@ -752,22 +633,6 @@ const Source = new Lang.Class({
return null;
},
_setApp: function(appId) {
if (this.app)
return;
this.app = this._getApp(appId);
if (!this.app)
return;
// Only override the icon if we were previously using
// notification-based icons (ie, not a trayicon) or if it was unset before
if (!this.trayIcon) {
this.useNotificationIcon = false;
this.iconUpdated();
}
},
setTitle: function(title) {
// Do nothing if .app is set, we don't want to override the
// app name with whatever is provided through libnotify (usually
@ -779,8 +644,8 @@ const Source = new Lang.Class({
},
open: function(notification) {
this.destroyNonResidentNotifications();
this.openApp();
this.destroyNonResidentNotifications();
},
_lastNotificationRemoved: function() {
@ -792,11 +657,8 @@ const Source = new Lang.Class({
if (this.app == null)
return;
let windows = this.app.get_windows();
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.activateWindow(mostRecentWindow);
}
this.app.activate();
Main.overview.hide();
},
destroy: function() {

View File

@ -148,7 +148,7 @@ const Overview = new Lang.Class({
// Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Actor({ opacity: 0,
reactive: true });
this._stack.add_actor(this._coverPane);
Main.layoutManager.overviewGroup.add_child(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
this._stack.add_actor(this._overview);
@ -265,7 +265,7 @@ const Overview = new Lang.Class({
// Create controls
this._controls = new OverviewControls.ControlsManager(this._searchEntry);
this._dash = this._controls.dash;
this._viewSelector = this._controls.viewSelector;
this.viewSelector = this._controls.viewSelector;
// Add our same-line elements after the search entry
this._overview.add(this._controls.actor, { y_fill: true, expand: true });
@ -285,11 +285,11 @@ const Overview = new Lang.Class({
},
addSearchProvider: function(provider) {
this._viewSelector.addSearchProvider(provider);
this.viewSelector.addSearchProvider(provider);
},
removeSearchProvider: function(provider) {
this._viewSelector.removeSearchProvider(provider);
this.viewSelector.removeSearchProvider(provider);
},
//
@ -513,7 +513,7 @@ const Overview = new Lang.Class({
this._activationTime = Date.now() / 1000;
Meta.disable_unredirect_for_screen(global.screen);
this._viewSelector.show();
this.viewSelector.show();
this._stack.opacity = 0;
Tweener.addTween(this._stack,
@ -620,7 +620,7 @@ const Overview = new Lang.Class({
this.animationInProgress = true;
this.visibleTarget = false;
this._viewSelector.zoomFromOverview();
this.viewSelector.zoomFromOverview();
// Make other elements fade out.
Tweener.addTween(this._stack,
@ -655,7 +655,7 @@ const Overview = new Lang.Class({
// Re-enable unredirection
Meta.enable_unredirect_for_screen(global.screen);
this._viewSelector.hide();
this.viewSelector.hide();
this._desktopFade.hide();
this._coverPane.hide();

View File

@ -55,18 +55,21 @@ const SlideLayout = new Lang.Class({
vfunc_allocate: function(container, box, flags) {
let child = container.get_first_child();
let [, , natWidth, natHeight] = child.get_preferred_size();
let availWidth = Math.round(box.x2 - box.x1);
let availHeight = Math.round(box.y2 - box.y1);
let [, natWidth] = child.get_preferred_width(availHeight);
// Align the actor inside the clipped box, as the actor's alignment
// flags only determine what to do if the allocated box is bigger
// than the actor's box.
let realDirection = getRtlSlideDirection(this._direction, child);
let translationX = (realDirection == SlideDirection.LEFT) ?
(availWidth - natWidth) : (natWidth - availWidth);
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
let actorBox = new Clutter.ActorBox({ x1: translationX,
y1: 0,
x2: child.x_expand ? availWidth : natWidth,
y2: child.y_expand ? availHeight : natHeight });
let actorBox = new Clutter.ActorBox();
actorBox.x1 = alignX;
actorBox.x2 = actorBox.x1 + child.x_expand ? availWidth : natWidth;
actorBox.y1 = 0;
actorBox.y2 = actorBox.y1 + availHeight;
child.allocate(actorBox, flags);
},
@ -236,11 +239,6 @@ const ThumbnailsSlider = new Lang.Class({
this._thumbnailsBox = thumbnailsBox;
// SlideLayout reads the actor's expand flags to decide
// whether to allocate the natural size to its child, or the whole
// available allocation
this._thumbnailsBox.actor.y_expand = true;
this.actor.request_mode = Clutter.RequestMode.WIDTH_FOR_HEIGHT;
this.actor.reactive = true;
this.actor.track_hover = true;
@ -324,7 +322,6 @@ const DashSlider = new Lang.Class({
// whether to allocate the natural size to its child, or the whole
// available allocation
this._dash.actor.x_expand = true;
this._dash.actor.y_expand = true;
this.actor.x_align = Clutter.ActorAlign.START;
this.actor.y_expand = true;
@ -504,6 +501,17 @@ const MessagesIndicator = new Lang.Class({
}
});
const ControlsLayout = new Lang.Class({
Name: 'ControlsLayout',
Extends: Clutter.BinLayout,
Signals: { 'allocation-changed': { flags: GObject.SignalFlags.RUN_LAST } },
vfunc_allocate: function(container, box, flags) {
this.parent(container, box, flags);
this.emit('allocation-changed');
}
});
const ControlsManager = new Lang.Class({
Name: 'ControlsManager',
@ -524,7 +532,8 @@ const ControlsManager = new Lang.Class({
this._indicator = new MessagesIndicator(this.viewSelector);
this.indicatorActor = this._indicator.actor;
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
let layout = new ControlsLayout();
this.actor = new St.Widget({ layout_manager: layout,
reactive: true,
x_expand: true, y_expand: true,
clip_to_allocation: true });
@ -539,7 +548,7 @@ const ControlsManager = new Lang.Class({
expand: true });
this._group.add_actor(this._thumbnailsSlider.actor);
this._group.connect('notify::allocation', Lang.bind(this, this._updateWorkspacesGeometry));
layout.connect('allocation-changed', Lang.bind(this, this._updateWorkspacesGeometry));
Main.overview.connect('showing', Lang.bind(this, this._updateSpacerVisibility));
Main.overview.connect('item-drag-begin', Lang.bind(this,

View File

@ -213,9 +213,7 @@ const AppMenuButton = new Lang.Class({
this._label = new TextShadower();
this._label.actor.y_align = Clutter.ActorAlign.CENTER;
this._hbox.add_actor(this._label.actor);
this._arrow = new St.Label({ text: '\u25BE',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this._arrow = PopupMenu.unicodeArrow(St.Side.BOTTOM);
this._hbox.add_actor(this._arrow);
this._iconBottomClip = 0;
@ -249,6 +247,7 @@ const AppMenuButton = new Lang.Class({
this._visible = true;
this.actor.reactive = true;
this.actor.show();
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 255,
time: Overview.ANIMATION_TIME,
@ -261,6 +260,7 @@ const AppMenuButton = new Lang.Class({
this._visible = false;
this.actor.reactive = false;
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 0,
time: Overview.ANIMATION_TIME,
@ -609,6 +609,7 @@ const ActivitiesButton = new Lang.Class({
_onButtonRelease: function() {
Main.overview.toggle();
this.menu.close();
},
_onKeyRelease: function(actor, event) {
@ -802,14 +803,19 @@ const AggregateMenu = new Lang.Class({
Extends: PanelMenu.Button,
_init: function() {
this.parent(0.0, _("Settings Menu"), false);
this.parent(0.0, _("Settings"), false);
this.menu.actor.add_style_class_name('aggregate-menu');
this._indicators = new St.BoxLayout({ style_class: 'panel-status-indicators-box' });
this.actor.add_child(this._indicators);
this._network = new imports.ui.status.network.NMApplet();
this._bluetooth = new imports.ui.status.bluetooth.Indicator();
if (Config.HAVE_BLUETOOTH) {
this._bluetooth = new imports.ui.status.bluetooth.Indicator();
} else {
this._bluetooth = null;
}
this._power = new imports.ui.status.power.Indicator();
this._rfkill = new imports.ui.status.rfkill.Indicator();
this._volume = new imports.ui.status.volume.Indicator();
@ -819,19 +825,21 @@ const AggregateMenu = new Lang.Class({
this._indicators.add_child(this._screencast.indicators);
this._indicators.add_child(this._network.indicators);
this._indicators.add_child(this._bluetooth.indicators);
if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators);
}
this._indicators.add_child(this._rfkill.indicators);
this._indicators.add_child(this._volume.indicators);
this._indicators.add_child(this._power.indicators);
this._indicators.add_child(new St.Label({ text: '\u25BE',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER }));
this._indicators.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
this.menu.addMenuItem(this._volume.menu);
this.menu.addMenuItem(this._brightness.menu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addMenuItem(this._network.menu);
this.menu.addMenuItem(this._bluetooth.menu);
if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu);
}
this.menu.addMenuItem(this._rfkill.menu);
this.menu.addMenuItem(this._power.menu);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());

View File

@ -2,6 +2,7 @@
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Shell = imports.gi.Shell;
@ -41,7 +42,7 @@ const PointerWatcher = new Lang.Class({
Name: 'PointerWatcher',
_init: function() {
this._idleMonitor = new GnomeDesktop.IdleMonitor();
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleMonitor.add_idle_watch(IDLE_TIME, Lang.bind(this, this._onIdleMonitorBecameIdle));
this._idle = this._idleMonitor.get_idletime() > IDLE_TIME;
this._watches = [];

View File

@ -35,6 +35,40 @@ function _ensureStyle(actor) {
actor.ensure_style();
}
function isPopupMenuItemVisible(child) {
if (child._delegate instanceof PopupMenuSection)
if (child._delegate.isEmpty())
return false;
return child.visible;
}
/**
* @side Side to which the arrow points.
*/
function unicodeArrow(side) {
let arrowChar;
switch (side) {
case St.Side.TOP:
arrowChar = '\u25B4';
break;
case St.Side.RIGHT:
arrowChar = '\u25B8';
break;
case St.Side.BOTTOM:
arrowChar = '\u25BE';
break;
case St.Side.LEFT:
arrowChar = '\u25C2';
break;
}
return new St.Label({ text: arrowChar,
style_class: 'unicode-arrow',
accessible_role: Atk.Role.ARROW,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
}
const PopupBaseMenuItem = new Lang.Class({
Name: 'PopupBaseMenuItem',
@ -437,7 +471,7 @@ const PopupMenuBase = new Lang.Class({
let hasVisibleChildren = this.box.get_children().some(function(child) {
if (child._delegate instanceof PopupSeparatorMenuItem)
return false;
return child.visible;
return isPopupMenuItemVisible(child);
});
return !hasVisibleChildren;
@ -518,7 +552,7 @@ const PopupMenuBase = new Lang.Class({
let childBeforeIndex = index - 1;
while (childBeforeIndex >= 0 && !children[childBeforeIndex].visible)
while (childBeforeIndex >= 0 && !isPopupMenuItemVisible(children[childBeforeIndex]))
childBeforeIndex--;
if (childBeforeIndex < 0
@ -529,7 +563,7 @@ const PopupMenuBase = new Lang.Class({
let childAfterIndex = index + 1;
while (childAfterIndex < children.length && !children[childAfterIndex].visible)
while (childAfterIndex < children.length && !isPopupMenuItemVisible(children[childAfterIndex]))
childAfterIndex++;
if (childAfterIndex >= children.length
@ -872,20 +906,20 @@ const PopupSubMenu = new Lang.Class({
{ _arrow_rotation: 0,
height: 0,
time: 0.25,
onUpdateScope: this,
onUpdate: function() {
this._arrow.rotation_angle_z = this.actor._arrow_rotation;
},
onCompleteScope: this,
onComplete: function() {
this.actor.hide();
this.actor.set_height(-1);
},
onUpdateScope: this,
onUpdate: function() {
this._arrow.rotation_angle_z = this.actor._arrow_rotation;
}
});
} else {
this._arrow.rotation_angle_z = 0;
this.actor.hide();
}
} else {
this._arrow.rotation_angle_z = 0;
this.actor.hide();
}
},
_onKeyPressEvent: function(actor, event) {
@ -941,18 +975,21 @@ const PopupSubMenuMenuItem = new Lang.Class({
this.actor.add_child(this.icon);
}
this.label = new St.Label({ text: text });
this.label = new St.Label({ text: text,
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.actor.add_child(this.label);
this.actor.label_actor = this.label;
let expander = new St.Bin({ style_class: 'popup-menu-item-expander' });
this.actor.add(expander, { expand: true });
this.status = new St.Label({ style_class: 'popup-status-menu-item' });
this.status = new St.Label({ style_class: 'popup-status-menu-item',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER });
this.actor.add_child(this.status);
this._triangle = new St.Label({ text: '\u25B8',
style_class: 'popup-submenu-menu-item-triangle' });
this._triangle = unicodeArrow(St.Side.RIGHT);
this._triangle.pivot_point = new Clutter.Point({ x: 0.5, y: 0.6 });
this._triangleBin = new St.Widget({ y_expand: true,
@ -962,6 +999,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
this._triangleBin.set_scale(-1.0, 1.0);
this.actor.add_child(this._triangleBin);
this.actor.add_accessible_state (Atk.StateType.EXPANDABLE);
this.menu = new PopupSubMenu(this.actor, this._triangle);
this.menu.connect('open-state-changed', Lang.bind(this, this._subMenuOpenStateChanged));
@ -983,9 +1021,11 @@ const PopupSubMenuMenuItem = new Lang.Class({
if (open) {
this.actor.add_style_pseudo_class('open');
this._getTopMenu()._setOpenedSubMenu(this.menu);
this.actor.add_accessible_state (Atk.StateType.EXPANDED);
} else {
this.actor.remove_style_pseudo_class('open');
this._getTopMenu()._setOpenedSubMenu(null);
this.actor.remove_accessible_state (Atk.StateType.EXPANDED);
}
},

View File

@ -207,6 +207,16 @@ const RemoteSearchProvider = new Lang.Class({
icon_size: size });
},
filterResults: function(results, maxNumber) {
if (results.length <= maxNumber)
return results;
let regularResults = results.filter(function(r) { return !r.startsWith('special:'); });
let specialResults = results.filter(function(r) { return r.startsWith('special:'); });
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
},
_getResultsFinished: function(results, error) {
if (error)
return;

View File

@ -19,6 +19,7 @@ const Background = imports.ui.background;
const GnomeSession = imports.misc.gnomeSession;
const Hash = imports.misc.hash;
const Layout = imports.ui.layout;
const OVirt = imports.gdm.oVirt;
const LoginManager = imports.misc.loginManager;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
@ -52,12 +53,10 @@ const SUMMARY_ICON_SIZE = 48;
// or when cancelling the dialog
// - BACKGROUND_FADE_TIME is used when the background changes to crossfade to new background
// - CURTAIN_SLIDE_TIME is used when raising the shield before unlocking
// - INITIAL_FADE_IN_TIME is used for the initial fade in at startup
const STANDARD_FADE_TIME = 10;
const MANUAL_FADE_TIME = 0.3;
const BACKGROUND_FADE_TIME = 1.0;
const CURTAIN_SLIDE_TIME = 0.3;
const INITIAL_FADE_IN_TIME = 0.25;
const Clock = new Lang.Class({
Name: 'ScreenShieldClock',
@ -520,16 +519,9 @@ const ScreenShield = new Lang.Class({
this._lockDialogGroup = new St.Widget({ x_expand: true,
y_expand: true,
reactive: true,
opacity: 0,
pivot_point: new Clutter.Point({ x: 0.5, y: 0.5 }),
name: 'lockDialogGroup' });
Tweener.addTween(this._lockDialogGroup,
{ opacity: 255,
time: INITIAL_FADE_IN_TIME,
transition: 'easeInQuad',
});
this.actor.add_actor(this._lockDialogGroup);
this.actor.add_actor(this._lockScreenGroup);
@ -554,6 +546,13 @@ const ScreenShield = new Lang.Class({
this._liftShield(true, 0);
}));
this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager();
this._oVirtCredentialsManager.connect('user-authenticated',
Lang.bind(this, function() {
if (this._isLocked)
this._liftShield(true, 0);
}));
this._inhibitor = null;
this._aboutToSuspend = false;
this._loginManager = LoginManager.getLoginManager();
@ -592,7 +591,8 @@ const ScreenShield = new Lang.Class({
fadeFactor: 1 });
this._shortLightbox.connect('shown', Lang.bind(this, this._onShortLightboxShown));
this.idleMonitor = new GnomeDesktop.IdleMonitor();
this.idleMonitor = Meta.IdleMonitor.get_core();
this._cursorTracker = Meta.CursorTracker.get_for_screen(global.screen);
},
_createBackground: function(monitorIndex) {
@ -732,6 +732,8 @@ const ScreenShield = new Lang.Class({
this.lock(true);
} else {
this._inhibitSuspend();
this._onUserBecameActive();
}
},
@ -960,7 +962,7 @@ const ScreenShield = new Lang.Class({
this._hideLockScreenComplete();
}
global.stage.show_cursor();
this._cursorTracker.set_pointer_visible(true);
},
_ensureUnlockDialog: function(onPrimary, allowCancel) {
@ -993,7 +995,6 @@ const ScreenShield = new Lang.Class({
_onUnlockFailed: function() {
this._resetLockScreen({ animateLockScreen: true,
animateLockDialog: false,
fadeToBlack: false });
},
@ -1033,17 +1034,6 @@ const ScreenShield = new Lang.Class({
animateFade: false });
}
if (params.animateLockDialog) {
this._lockDialogGroup.opacity = 0;
Tweener.removeTweens(this._lockDialogGroup);
Tweener.addTween(this._lockDialogGroup,
{ opacity: 255,
time: MANUAL_FADE_TIME,
transition: 'easeOutQuad' });
} else {
this._lockDialogGroup.opacity = 255;
}
this._lockScreenGroup.grab_key_focus();
if (Main.sessionMode.currentMode != 'lock-screen')
@ -1105,15 +1095,15 @@ const ScreenShield = new Lang.Class({
this._checkArrowAnimation();
let motionId = global.stage.connect('captured-event', function(stage, event) {
let motionId = global.stage.connect('captured-event', Lang.bind(this, function(stage, event) {
if (event.type() == Clutter.EventType.MOTION) {
global.stage.show_cursor();
this._cursorTracker.set_pointer_visible(true);
global.stage.disconnect(motionId);
}
return false;
});
global.stage.hide_cursor();
}));
this._cursorTracker.set_pointer_visible(false);
this._lockScreenState = MessageTray.State.SHOWN;
this._lockScreenGroup.fixed_position_set = false;
@ -1294,7 +1284,6 @@ const ScreenShield = new Lang.Class({
}
this._resetLockScreen({ animateLockScreen: animate,
animateLockDialog: animate,
fadeToBlack: true });
global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true));

View File

@ -6,6 +6,7 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
@ -167,7 +168,7 @@ const SelectArea = new Lang.Class({
if (!Main.pushModal(this._group) || this._group.visible)
return;
global.set_cursor(Shell.Cursor.CROSSHAIR);
global.screen.set_cursor(Meta.Cursor.CROSSHAIR);
this._group.visible = true;
},
@ -238,7 +239,7 @@ const SelectArea = new Lang.Class({
function() {
Main.popModal(this._group);
this._group.destroy();
global.unset_cursor();
global.screen.set_cursor(Meta.Cursor.DEFAULT);
this.emit('finished', geometry);
})

View File

@ -126,23 +126,25 @@ const GridSearchResult = new Lang.Class({
this.actor.style_class = 'grid-search-result';
let content = provider.createResultActor(metaInfo, terms);
let content = provider.createResultObject(metaInfo, terms);
let dragSource = null;
if (content == null) {
content = new St.Bin();
let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
content.set_child(icon.actor);
content.label_actor = icon.label;
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content);
this.actor.label_actor = content.label_actor;
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
@ -212,8 +214,8 @@ const SearchResultsBase = new Lang.Class({
this.actor.hide();
},
_keyFocusIn: function(icon) {
this.emit('key-focus-in', icon);
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_setMoreIconVisible: function(visible) {
@ -228,7 +230,7 @@ const SearchResultsBase = new Lang.Class({
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = providerResults.slice(0, maxResults);
let results = this.provider.filterResults(providerResults, maxResults);
let hasMoreResults = results.length < providerResults.length;
this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
@ -257,6 +259,7 @@ const ListSearchResults = new Lang.Class({
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
@ -320,14 +323,14 @@ const GridSearchResults = new Lang.Class({
},
_getMaxDisplayedResults: function() {
return this._grid.childrenInRow(this._bin.width) * this._grid.getRowLimit();
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i], this._terms);
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display.actor);
this._grid.addItem(display);
}
},
@ -402,8 +405,8 @@ const SearchResults = new Lang.Class({
return false;
},
_keyFocusIn: function(provider, icon) {
Util.ensureActorVisibleInScrollView(this._scrollView, icon);
_keyFocusIn: function(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
createProviderDisplay: function(provider) {

View File

@ -13,6 +13,7 @@ const ExtensionUtils = imports.misc.extensionUtils;
const Hash = imports.misc.hash;
const Main = imports.ui.main;
const Screenshot = imports.ui.screenshot;
const ViewSelector = imports.ui.viewSelector;
const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
@ -24,6 +25,10 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="FocusApp">
<arg type="s" direction="in" name="id"/>
</method>
<method name="ShowApplications" />
<method name="GrabAccelerator">
<arg type="s" direction="in" name="accelerator"/>
<arg type="u" direction="in" name="flags"/>
@ -135,6 +140,15 @@ const GnomeShell = new Lang.Class({
Main.osdWindow.show();
},
FocusApp: function(id) {
this.ShowApplications();
Main.overview.viewSelector.appDisplay.selectApp(id);
},
ShowApplications: function() {
Main.overview.viewSelector.showApps();
},
GrabAcceleratorAsync: function(params, invocation) {
let [accel, flags] = params;
let sender = invocation.get_sender();

View File

@ -5,6 +5,7 @@ const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const SLIDER_SCROLL_STEP = 0.05; /* Slider scrolling step in % */
@ -19,14 +20,26 @@ const Slider = new Lang.Class({
this.actor = new St.DrawingArea({ style_class: 'slider',
can_focus: true,
reactive: true });
reactive: true,
accessible_role: Atk.Role.SLIDER });
this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint));
this.actor.connect('button-press-event', Lang.bind(this, this._startDragging));
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-press-event', Lang.bind(this, this.onKeyPressEvent));
this._releaseId = this._motionId = 0;
this._dragging = false;
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', Lang.bind(this, this._getCurrentValue));
this._customAccessible.connect('get-minimum-value', Lang.bind(this, this._getMinimumValue));
this._customAccessible.connect('get-maximum-value', Lang.bind(this, this._getMaximumValue));
this._customAccessible.connect('get-minimum-increment', Lang.bind(this, this._getMinimumIncrement));
this._customAccessible.connect('set-current-value', Lang.bind(this, this._setCurrentValue));
this.connect('value-changed', Lang.bind(this, this._valueChanged));
},
setValue: function(value) {
@ -168,12 +181,12 @@ const Slider = new Lang.Class({
return true;
},
_onKeyPressEvent: function (actor, event) {
onKeyPressEvent: function (actor, event) {
let key = event.get_key_symbol();
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
this._value = Math.max(0, Math.min(this._value + delta, 1));
this._slider.queue_repaint();
this.actor.queue_repaint();
this.emit('value-changed', this._value);
this.emit('drag-end');
return true;
@ -202,6 +215,30 @@ const Slider = new Lang.Class({
this.emit('value-changed', this._value);
},
_getCurrentValue: function (actor) {
return this._value;
},
_getMinimumValue: function (actor) {
return 0;
},
_getMaximumValue: function (actor) {
return 1;
},
_getMinimumIncrement: function (actor) {
return 0.1;
},
_setCurrentValue: function (actor, value) {
this._value = value;
},
_valueChanged: function (slider, value, property) {
this._customAccessible.notify ("accessible-value");
},
get value() {
return this._value;
}

View File

@ -43,9 +43,7 @@ const ATIndicator = new Lang.Class({
this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
this._hbox.add_child(new St.Icon({ style_class: 'system-status-icon',
icon_name: 'preferences-desktop-accessibility-symbolic' }));
this._hbox.add_child(new St.Label({ text: '\u25BE',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER }));
this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
this.actor.add_child(this._hbox);

View File

@ -9,7 +9,6 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@ -31,6 +30,7 @@ const Indicator = new Lang.Class({
this._applet.killswitch_state = GnomeBluetooth.KillswitchState.SOFT_BLOCKED;
}));
this._item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-bluetooth-panel.desktop');
this.menu.addMenuItem(this._item);
this._applet = new GnomeBluetoothApplet.Applet();
this._applet.connect('devices-changed', Lang.bind(this, this._sync));
@ -54,13 +54,13 @@ const Indicator = new Lang.Class({
this._item.actor.visible = on;
if (on)
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices").format(nDevices);
this._item.status.text = ngettext("%d Connected Device", "%d Connected Devices", nDevices).format(nDevices);
},
_ensureSource: function() {
if (!this._source) {
this._source = new MessageTray.Source(_("Bluetooth"), 'bluetooth-active');
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-bluetooth-panel');
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-bluetooth-panel');
Main.messageTray.add(this._source);
}
},

View File

@ -39,6 +39,7 @@ const Indicator = new Lang.Class({
this._slider = new Slider.Slider(0);
this._slider.connect('value-changed', Lang.bind(this, this._sliderChanged));
this._slider.actor.accessible_name = _("Brightness");
let icon = new St.Icon({ icon_name: 'display-brightness-symbolic',
style_class: 'popup-menu-icon' });
@ -47,6 +48,10 @@ const Indicator = new Lang.Class({
this._item.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
this._slider.startDragging(event);
}));
this._item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
return this._slider.onKeyPressEvent(actor, event);
}));
},
_sliderChanged: function(slider, value) {

View File

@ -41,8 +41,7 @@ const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
const KeyboardManagerInterface =
<interface name="org.gnome.SettingsDaemon.Keyboard">
const KeyboardManagerInterface = <interface name="org.gnome.SettingsDaemon.Keyboard">
<method name="SetInputSource">
<arg type="u" direction="in" />
</method>
@ -340,9 +339,7 @@ const InputSourceIndicator = new Lang.Class({
this._hbox = new St.BoxLayout({ style_class: 'panel-status-menu-box' });
this._hbox.add_child(this._container);
this._hbox.add_child(new St.Label({ text: '\u25BE',
y_expand: true,
y_align: Clutter.ActorAlign.CENTER }));
this._hbox.add_child(PopupMenu.unicodeArrow(St.Side.BOTTOM));
this.actor.add_child(this._hbox);
this.actor.add_style_class_name('panel-status-button');

View File

@ -16,7 +16,6 @@ const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const ModalDialog = imports.ui.modalDialog;
const ModemManager = imports.misc.modemManager;
const Util = imports.misc.util;
@ -73,6 +72,27 @@ function ssidToLabel(ssid) {
return label;
}
function ensureActiveConnectionProps(active, settings) {
if (!active._connection) {
active._connection = settings.get_connection_by_path(active.connection);
// This list is guaranteed to have only one device in it.
let device = active.get_devices()[0]._delegate;
active._primaryDevice = device;
}
}
function createSettingsAction(label, device) {
let item = new PopupMenu.PopupMenuItem(label);
item.connect('activate', function() {
Util.spawnApp(['gnome-control-center', 'network', 'show-device',
device.get_path()]);
});
return item;
}
const NMConnectionItem = new Lang.Class({
Name: 'NMConnectionItem',
@ -97,14 +117,14 @@ const NMConnectionItem = new Lang.Class({
},
getName: function() {
return this.connection.get_id();
return this._connection.get_id();
},
isActive: function() {
if (this._activeConnection == null)
return false;
return this._activeConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED;
return this._activeConnection.state <= NetworkManager.ActiveConnectionState.ACTIVATED;
},
_sync: function() {
@ -141,7 +161,7 @@ const NMConnectionItem = new Lang.Class({
this._activeConnection = activeConnection;
if (this._activeConnection)
this._activeConnectionChangedId = this._activeConnection.connect('state-changed',
this._activeConnectionChangedId = this._activeConnection.connect('notify::state',
Lang.bind(this, this._connectionStateChanged));
this._sync();
@ -170,8 +190,7 @@ const NMConnectionSection = new Lang.Class({
},
destroy: function() {
this.statusItem.destroy();
this.section.destroy();
this.item.destroy();
},
_sync: function() {
@ -182,7 +201,14 @@ const NMConnectionSection = new Lang.Class({
this.item.status.text = this._getStatus();
this.item.icon.icon_name = this._getMenuIcon();
this.item.label.text = this._getDescription();
// desc can be undefined at cold-plug, before we called
// NMGtk.disambiguate_device_names() at least once
let desc = this._getDescription();
if (desc)
this.item.label.text = desc;
else
this.item.label.text = '';
},
_getStatus: function() {
@ -237,7 +263,7 @@ const NMConnectionSection = new Lang.Class({
this.emit('activation-failed', reason);
}));
let pos = Util.insertSorted(this._connections, connection, this._connectionSortFunction);
let pos = Util.insertSorted(this._connections, connection, Lang.bind(this, this._connectionSortFunction));
this._labelSection.addMenuItem(item.labelItem, pos);
this._switchSection.addMenuItem(item.switchItem, pos);
this._connectionItems.set(connection.get_uuid(), item);
@ -261,12 +287,12 @@ const NMConnectionDevice = new Lang.Class({
Extends: NMConnectionSection,
Abstract: true,
_init: function(client, device) {
_init: function(client, device, settings) {
this.parent(client);
this._device = device;
this._settings = settings;
this._autoConnectItem = this.item.menu.addAction(_("Connect"), Lang.bind(this, this._autoConnect));
this.item.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
this._activeConnectionChangedId = this._device.connect('notify::active-connection', Lang.bind(this, this._activeConnectionChanged));
@ -294,6 +320,7 @@ const NMConnectionDevice = new Lang.Class({
this._activeConnection = this._device.active_connection;
if (this._activeConnection) {
ensureActiveConnectionProps(this._activeConnection, this._settings);
let item = this._connectionItems.get(this._activeConnection._connection.get_uuid());
item.setActiveConnection(this._activeConnection);
}
@ -345,12 +372,13 @@ const NMConnectionDevice = new Lang.Class({
_getStatus: function() {
if (!this._device)
return null;
return '';
switch(this._device.state) {
case NetworkManager.DeviceState.DISCONNECTED:
return _("Off");
case NetworkManager.DeviceState.ACTIVATED:
return null;
return this.parent();
case NetworkManager.DeviceState.UNMANAGED:
/* Translators: this is for network devices that are physically present but are not
under NetworkManager's control (and thus cannot be used in the menu) */
@ -392,8 +420,11 @@ const NMDeviceModem = new Lang.Class({
Extends: NMConnectionDevice,
category: NMConnectionCategory.WWAN,
_init: function(client, device) {
this.parent(client, device);
_init: function(client, device, settings) {
this.parent(client, device, settings);
this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device));
this._mobileDevice = null;
let capabilities = device.current_capabilities;
@ -407,16 +438,7 @@ const NMDeviceModem = new Lang.Class({
this._mobileDevice = new ModemManager.ModemGsm(device.udi);
if (this._mobileDevice) {
this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, function() {
if (this._operatorItem) {
let name = this._mobileDevice.operator_name;
if (name) {
this._operatorItem.label.text = name;
this._operatorItem.actor.show();
} else
this._operatorItem.actor.hide();
}
}));
this._operatorNameId = this._mobileDevice.connect('notify::operator-name', Lang.bind(this, this._sync));
this._signalQualityId = this._mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
this.emit('icon-changed');
}));
@ -441,6 +463,20 @@ const NMDeviceModem = new Lang.Class({
this.parent();
},
_getStatus: function() {
if (!this._client.wwan_hardware_enabled)
return _("Hardware Disabled");
else if (!this._client.wwan_enabled)
/* Translators: this is for a network device that cannot be activated
because it's disabled by rfkill (airplane mode) */
return _("Disabled");
else if (this._device.state == NetworkManager.DeviceState.ACTIVATED &&
this._mobileDevice && this._mobileDevice.operator_name)
return this._mobileDevice.operator_name;
else
return this.parent();
},
_getMenuIcon: function() {
if (this._device.active_connection)
return this.getIndicatorIcon();
@ -470,6 +506,12 @@ const NMDeviceBluetooth = new Lang.Class({
Extends: NMConnectionDevice,
category: NMConnectionCategory.WWAN,
_init: function(client, device, settings) {
this.parent(client, device, settings);
this.item.menu.addMenuItem(createSettingsAction(_("Mobile Broadband Settings"), device));
},
_autoConnect: function() {
// FIXME: DUN devices are configured like modems, so
// We need to spawn the mobile wizard
@ -517,6 +559,8 @@ const NMWirelessDialogItem = new Lang.Class({
this.actor.grab_key_focus();
}));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._content = new St.BoxLayout({ style_class: 'nm-dialog-item-box' });
this.actor.set_child(this._content);
@ -540,22 +584,38 @@ const NMWirelessDialogItem = new Lang.Class({
this._signalIcon = new St.Icon({ style_class: 'nm-dialog-icon' });
this._icons.add_actor(this._signalIcon);
this._sync();
},
_sync: function() {
this._signalIcon.icon_name = this._getSignalIcon();
},
updateBestAP: function(ap) {
this._ap = ap;
this._signalIcon.icon_name = this._getIcon();
this._sync();
},
setActive: function(isActive) {
this._selectedIcon.opacity = isActive ? 255 : 0;
},
_getIcon: function() {
_getSignalIcon: function() {
if (this._ap.mode == NM80211Mode.ADHOC)
return 'network-workgroup-symbolic';
else
return 'network-wireless-signal-' + signalToIcon(this._ap.strength) + '-symbolic';
},
_onKeyPressEvent: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return
|| symbol == Clutter.KEY_KP_Enter) {
this.emit('connect');
return true;
}
return false;
}
});
Signals.addSignalMethods(NMWirelessDialogItem.prototype);
@ -924,6 +984,9 @@ const NMWirelessDialog = new Lang.Class({
Util.ensureActorVisibleInScrollView(this._scrollView, network.item.actor);
this._selectNetwork(network);
}));
network.item.connect('connect', Lang.bind(this, function() {
this._connect();
}));
},
});
@ -945,9 +1008,10 @@ const NMDeviceWireless = new Lang.Class({
this._toggleItem.connect('activate', Lang.bind(this, this._toggleWifi));
this.item.menu.addMenuItem(this._toggleItem);
this.item.menu.addSettingsAction(_("Network Settings"), 'gnome-network-panel.desktop');
this.item.menu.addMenuItem(createSettingsAction(_("Wi-Fi Settings"), device));
this._wirelessEnabledChangedId = this._device.connect('notify::wireless-enabled', Lang.bind(this, this._sync));
this._wirelessEnabledChangedId = this._client.connect('notify::wireless-enabled', Lang.bind(this, this._sync));
this._wirelessHwEnabledChangedId = this._client.connect('notify::wireless-hardware-enabled', Lang.bind(this, this._sync));
this._activeApChangedId = this._device.connect('notify::active-access-point', Lang.bind(this, this._activeApChanged));
this._stateChangedId = this._device.connect('state-changed', Lang.bind(this, this._deviceStateChanged));
@ -967,6 +1031,14 @@ const NMDeviceWireless = new Lang.Class({
this._activeAccessPoint.disconnect(this._strengthChangedId);
this._strengthChangedId = 0;
}
if (this._wirelessEnabledChangedId) {
this._client.disconnect(this._wirelessEnabledChangedId);
this._wirelessEnabledChangedId = 0;
}
if (this._wirelessHwEnabledChangedId) {
this._client.disconnect(this._wirelessHwEnabledChangedId);
this._wirelessHwEnabledChangedId = 0;
}
this.item.destroy();
},
@ -1025,6 +1097,7 @@ const NMDeviceWireless = new Lang.Class({
_sync: function() {
this._toggleItem.label.text = this._client.wireless_enabled ? _("Turn Off") : _("Turn On");
this._toggleItem.actor.visible = this._client.wireless_hardware_enabled;
this.item.status.text = this._getStatus();
this.item.icon.icon_name = this._getMenuIcon();
@ -1038,10 +1111,17 @@ const NMDeviceWireless = new Lang.Class({
_getStatus: function() {
let ap = this._device.active_access_point;
if (!ap)
return _("Off"); // XXX -- interpret actual status
return ssidToLabel(ap.get_ssid());
if (ap)
return ssidToLabel(ap.get_ssid());
else if (!this._client.wireless_hardware_enabled)
return _("Hardware Disabled");
else if (!this._client.wireless_enabled)
return _("Off");
else if (this._device.state == NetworkManager.DeviceState.DISCONNECTED)
return _("Not Connected");
else
return '';
},
_getMenuIcon: function() {
@ -1052,7 +1132,8 @@ const NMDeviceWireless = new Lang.Class({
},
getIndicatorIcon: function() {
if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
if (this._device.state >= NetworkManager.DeviceState.PREPARE &&
this._device.state < NetworkManager.DeviceState.ACTIVATED)
return 'network-wireless-acquiring-symbolic';
let ap = this._device.active_access_point;
@ -1076,7 +1157,7 @@ const NMVPNConnectionItem = new Lang.Class({
if (this._activeConnection == null)
return false;
return this._activeConnection.vpn_state == NetworkManager.VPNConnectionState.ACTIVATED;
return this._activeConnection.vpn_state != NetworkManager.VPNConnectionState.DISCONNECTED;
},
_getStatus: function() {
@ -1110,6 +1191,7 @@ const NMVPNConnectionItem = new Lang.Class({
this.emit('activation-failed', reason);
}
this.emit('icon-changed');
this.parent();
},
@ -1130,7 +1212,7 @@ const NMVPNConnectionItem = new Lang.Class({
getIndicatorIcon: function() {
if (this._activeConnection) {
if (this._activeConnection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
if (this._activeConnection.vpn_state < NetworkManager.VPNConnectionState.ACTIVATED)
return 'network-vpn-acquiring-symbolic';
else
return 'network-vpn-symbolic';
@ -1172,14 +1254,14 @@ const NMVPNSection = new Lang.Class({
this._client.deactivate_connection(activeConnection);
},
addActiveConnection: function(activeConnection) {
let item = this._connectionItems.get(activeConnection._connection.get_uuid());
item.setActiveConnection(activeConnection);
},
removeActiveConnection: function(activeConnection) {
let item = this._connectionItems.get(activeConnection._connection.get_uuid());
item.setActiveConnection(null);
setActiveConnections: function(vpnConnections) {
this._connectionItems.values().forEach(function(item) {
item.setActiveConnection(null);
});
vpnConnections.forEach(Lang.bind(this, function(a) {
let item = this._connectionItems.get(a._connection.get_uuid());
item.setActiveConnection(a);
}));
},
_makeConnectionItem: function(connection) {
@ -1250,6 +1332,8 @@ const NMApplet = new Lang.Class({
this._mainConnection = null;
this._mainConnectionIconChangedId = 0;
this._notification = null;
this._nmDevices = [];
this._devices = { };
@ -1277,7 +1361,9 @@ const NMApplet = new Lang.Class({
this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState));
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncActiveConnections));
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
@ -1295,7 +1381,7 @@ const NMApplet = new Lang.Class({
if (!this._source) {
this._source = new MessageTray.Source(_("Network Manager"),
'network-transmit-receive');
this._source.policy = new NotificationDaemon.NotificationApplicationPolicy('gnome-network-panel');
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
this._source.connect('destroy', Lang.bind(this, function() {
this._source = null;
@ -1312,32 +1398,29 @@ const NMApplet = new Lang.Class({
this._syncDeviceNames();
},
_notifyForDevice: function(device, iconName, title, text, urgency) {
if (device._notification)
device._notification.destroy();
_notify: function(iconName, title, text, urgency) {
if (this._notification)
this._notification.destroy();
/* must call after destroying previous notification,
or this._source will be cleared */
this._ensureSource();
let gicon = new Gio.ThemedIcon({ name: iconName });
device._notification = new MessageTray.Notification(this._source, title, text,
{ gicon: gicon });
device._notification.setUrgency(urgency);
device._notification.setTransient(true);
device._notification.connect('destroy', function() {
device._notification = null;
this._notification = new MessageTray.Notification(this._source, title, text, { gicon: gicon });
this._notification.setUrgency(urgency);
this._notification.setTransient(true);
this._notification.connect('destroy', function() {
this._notification = null;
});
this._source.notify(device._notification);
this._source.notify(this._notification);
},
_onActivationFailed: function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
this._notifyForDevice(device, 'network-error-symbolic',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
this._notify('network-error-symbolic',
_("Connection failed"),
_("Activation of network connection failed"),
MessageTray.Urgency.HIGH);
},
_syncDeviceNames: function() {
@ -1410,136 +1493,63 @@ const NMApplet = new Lang.Class({
devices.splice(pos, 1);
},
_getSupportedActiveConnections: function() {
let activeConnections = this._client.get_active_connections() || [ ];
let supportedConnections = [];
_getMainConnection: function() {
let connection;
for (let i = 0; i < activeConnections.length; i++) {
let devices = activeConnections[i].get_devices();
if (!devices || !devices[0])
continue;
// Ignore connections via unrecognized device types
if (!this._dtypes[devices[0].device_type])
continue;
// Ignore slave connections
let connectionPath = activeConnections[i].connection;
let connection = this._settings.get_connection_by_path(connectionPath);
// connection might be null, if libnm-glib fails to create
// the object due to version incompatibility, or if the
// connection is not visible to the current user
if (connection && this._ignoreConnection(connection))
continue;
supportedConnections.push(activeConnections[i]);
connection = this._client.get_primary_connection();
if (connection) {
ensureActiveConnectionProps(connection, this._settings);
return connection;
}
return supportedConnections;
connection = this._client.get_activating_connection();
if (connection) {
ensureActiveConnectionProps(connection, this._settings);
return connection;
}
return null;
},
_syncActiveConnections: function() {
let closedConnections = [ ];
let newActiveConnections = this._getSupportedActiveConnections();
for (let i = 0; i < this._activeConnections.length; i++) {
let a = this._activeConnections[i];
if (newActiveConnections.indexOf(a) == -1) // connection is removed
closedConnections.push(a);
}
for (let i = 0; i < closedConnections.length; i++) {
let a = closedConnections[i];
if (a._type == NetworkManager.SETTING_VPN_SETTING_NAME)
this._vpnSection.removeActiveConnection(a);
if (a._inited) {
a.disconnect(a._notifyStateId);
a.disconnect(a._notifyDefaultId);
a.disconnect(a._notifyDefault6Id);
a._inited = false;
}
}
_syncMainConnection: function() {
if (this._mainConnectionIconChangedId > 0) {
this._mainConnection._primaryDevice.disconnect(this._mainConnectionIconChangedId);
this._mainConnectionIconChangedId = 0;
}
this._activeConnections = newActiveConnections;
this._mainConnection = null;
let activating = null;
let default_ip4 = null;
let default_ip6 = null;
let active_any = null;
for (let i = 0; i < this._activeConnections.length; i++) {
let a = this._activeConnections[i];
if (!a._inited) {
a._notifyDefaultId = a.connect('notify::default', Lang.bind(this, this._syncActiveConnections));
a._notifyDefault6Id = a.connect('notify::default6', Lang.bind(this, this._syncActiveConnections));
a._notifyStateId = a.connect('notify::state', Lang.bind(this, this._notifyActivated));
a._inited = true;
}
if (!a._connection) {
a._connection = this._settings.get_connection_by_path(a.connection);
if (a._connection) {
a._type = a._connection._type;
a._section = this._ctypes[a._type];
} else {
a._connection = null;
a._type = null;
a._section = null;
log('Cannot find connection for active (or connection cannot be read)');
}
}
if (a['default'])
default_ip4 = a;
if (a.default6)
default_ip6 = a;
if (a.state == NetworkManager.ActiveConnectionState.ACTIVATING)
activating = a;
else if (a.state == NetworkManager.ActiveConnectionState.ACTIVATED)
active_any = a;
if (!a._primaryDevice) {
if (a._type != NetworkManager.SETTING_VPN_SETTING_NAME) {
// This list is guaranteed to have one device in it.
a._primaryDevice = a.get_devices()[0]._delegate;
} else {
a._primaryDevice = this._vpnSection;
this._vpnSection.addActiveConnection(a);
}
if (a.state == NetworkManager.ActiveConnectionState.ACTIVATED
&& a._primaryDevice && a._primaryDevice._notification) {
a._primaryDevice._notification.destroy();
a._primaryDevice._notification = null;
}
}
if (this._mainConnectionStateChangedId > 0) {
this._mainConnection.disconnect(this._mainConnectionStateChangedId);
this._mainConnectionStateChangedId = 0;
}
this._mainConnection = default_ip4 || default_ip6 || active_any || activating || null;
this._mainConnection = this._getMainConnection();
if (this._mainConnection) {
let dev = this._mainConnection._primaryDevice;
this._mainConnectionIconChangedId = dev.connect('icon-changed', Lang.bind(this, this._updateIcon));
if (this._mainConnection._primaryDevice)
this._mainConnectionIconChangedId = this._mainConnection._primaryDevice.connect('icon-changed', Lang.bind(this, this._updateIcon));
this._mainConnectionStateChangedId = this._mainConnection.connect('notify::state', Lang.bind(this, this._mainConnectionStateChanged));
this._mainConnectionStateChanged();
}
this._updateIcon();
},
_notifyActivated: function(activeConnection) {
if (activeConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED
&& activeConnection._primaryDevice && activeConnection._primaryDevice._notification) {
activeConnection._primaryDevice._notification.destroy();
activeConnection._primaryDevice._notification = null;
}
_syncVPNConnections: function() {
let activeConnections = this._client.get_active_connections() || [];
let vpnConnections = activeConnections.filter(function(a) {
return (a instanceof NMClient.VPNConnection);
});
vpnConnections.forEach(Lang.bind(this, function(a) {
ensureActiveConnectionProps(a, this._settings);
}));
this._vpnSection.setActiveConnections(vpnConnections);
this._syncActiveConnections();
this._updateIcon();
},
_mainConnectionStateChanged: function() {
if (this._mainConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED && this._notification)
this._notification.destroy();
},
_ignoreConnection: function(connection) {
@ -1576,7 +1586,6 @@ const NMApplet = new Lang.Class({
_newConnection: function(settings, connection) {
this._addConnection(connection);
this._syncActiveConnections();
},
_connectionRemoved: function(connection) {
@ -1627,24 +1636,19 @@ const NMApplet = new Lang.Class({
},
_syncNMState: function() {
this._syncActiveConnections();
this.indicators.visible = this._client.manager_running;
this.menu.actor.visible = this._client.networking_enabled;
},
_updateIcon: function() {
let mc = this._mainConnection;
if (!this._client.networking_enabled || !mc) {
if (!this._client.networking_enabled || !this._mainConnection) {
this._primaryIndicator.icon_name = 'network-offline-symbolic';
this._primaryIndicator.visible = true;
} else {
let dev = this._mainConnection._primaryDevice;
if (!dev) {
log('Active connection with no primary device?');
return;
}
this._primaryIndicator.icon_name = dev.getIndicatorIcon(mc);
this._primaryIndicator.visible = (dev != null);
if (dev)
this._primaryIndicator.icon_name = dev.getIndicatorIcon();
}
this._vpnIndicator.icon_name = this._vpnSection.getIndicatorIcon();

View File

@ -74,50 +74,42 @@ const Indicator = new Lang.Class({
if (state == UPower.DeviceState.DISCHARGING) {
// Translators: this is <hours>:<minutes> Remaining (<percentage>)
return _("%d\u2236%02d Remaining (%d%%)".format(hours, minutes, percentage));
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, percentage);
}
if (state == UPower.DeviceState.CHARGING) {
// Translators: this is <hours>:<minutes> Until Full (<percentage>)
return _("%d\u2236%02d Until Full (%d%%)".format(hours, minutes, percentage));
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, percentage);
}
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
return _("Estimating…");
},
_syncStatusLabel: function() {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
if (error) {
this._item.actor.hide();
return;
}
_sync: function() {
function isBattery(result) {
if (!result)
return false;
let [device] = result;
let [device_id, device_type] = device;
if (device_type == UPower.DeviceKind.BATTERY) {
let [, deviceType] = device;
return (deviceType == UPower.DeviceKind.BATTERY);
}
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
if (isBattery(result)) {
let [device] = result;
let [,, icon] = device;
let gicon = Gio.icon_new_for_string(icon);
this._indicator.gicon = gicon;
this._item.icon.gicon = gicon;
this._item.status.text = this._statusForDevice(device);
this._item.actor.show();
} else {
// If there's no battery, then we use the power icon.
this._indicator.icon_name = 'system-shutdown-symbolic';
this._item.actor.hide();
}
}));
},
_syncIcon: function() {
let icon = this._proxy.Icon;
if (icon) {
let gicon = Gio.icon_new_for_string(icon);
this._indicator.gicon = gicon;
this._item.icon.gicon = gicon;
} else {
// If there's no battery, then we use the power icon.
this._indicator.icon_name = 'system-shutdown-symbolic';
}
},
_sync: function() {
this._syncIcon();
this._syncStatusLabel();
}
});

View File

@ -1,24 +1,20 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Clutter = imports.gi.Clutter;
const BoxPointer = imports.ui.boxpointer;
const GnomeSession = imports.misc.gnomeSession;
const LoginManager = imports.misc.loginManager;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const UserWidget = imports.ui.userWidget;
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
@ -28,17 +24,64 @@ const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
const MAX_USERS_IN_SESSION_DIALOG = 5;
const AltSwitcher = new Lang.Class({
Name: 'AltSwitcher',
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'>
<property name="Id" type="s" access="read"/>
<property name="Remote" type="b" access="read"/>
<property name="Class" type="s" access="read"/>
<property name="Type" type="s" access="read"/>
<property name="State" type="s" access="read"/>
</interface>;
_init: function(standard, alternate) {
this._standard = standard;
this._standard.connect('notify::visible', Lang.bind(this, this._sync));
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
this._alternate = alternate;
this._alternate.connect('notify::visible', Lang.bind(this, this._sync));
this._capturedEventId = global.stage.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor = new St.Bin();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
_sync: function() {
let childToShow = null;
if (this._standard.visible && this._alternate.visible) {
let [x, y, mods] = global.get_pointer();
let altPressed = (mods & Clutter.ModifierType.MOD1_MASK) != 0;
childToShow = altPressed ? this._alternate : this._standard;
} else if (this._standard.visible) {
childToShow = this._standard;
} else if (this._alternate.visible) {
childToShow = this._alternate;
}
if (this.actor.get_child() != childToShow) {
this.actor.set_child(childToShow);
// The actors might respond to hover, so
// sync the pointer to make sure they update.
global.sync_pointer();
}
this.actor.visible = (childToShow != null);
},
_onDestroy: function() {
if (this._capturedEventId > 0) {
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
}
},
_onCapturedEvent: function(actor, event) {
let type = event.type();
if (type == Clutter.EventType.KEY_PRESS || type == Clutter.EventType.KEY_RELEASE) {
let key = event.get_key_symbol();
if (key == Clutter.KEY_Alt_L || key == Clutter.KEY_Alt_R)
this._sync();
}
return false;
},
});
const Indicator = new Lang.Class({
Name: 'SystemIndicator',
@ -53,9 +96,10 @@ const Indicator = new Lang.Class({
this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' });
this._session = new GnomeSession.SessionManager();
this._haveShutdown = true;
this._loginManager = LoginManager.getLoginManager();
this._haveShutdown = true;
this._haveSuspend = true;
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
@ -90,6 +134,7 @@ const Indicator = new Lang.Class({
return;
this._updateHaveShutdown();
this._updateHaveSuspend();
}));
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
Lang.bind(this, this._updateHaveShutdown));
@ -117,7 +162,7 @@ const Indicator = new Lang.Class({
let visible = (this._settingsAction.visible ||
this._orientationLockAction.visible ||
this._lockScreenAction.visible ||
this._powerOffAction.visible);
this._altSwitcher.actor.visible);
this._actionsItem.actor.visible = visible;
},
@ -125,6 +170,7 @@ const Indicator = new Lang.Class({
_sessionUpdated: function() {
this._updateLockScreen();
this._updatePowerOff();
this._updateSuspend();
this._updateMultiUser();
this._settingsAction.visible = Main.sessionMode.allowSettings;
this._updateActionsVisibility();
@ -205,13 +251,13 @@ const Indicator = new Lang.Class({
},
_updateHaveShutdown: function() {
this._session.CanShutdownRemote(Lang.bind(this,
function(result, error) {
if (!error) {
this._haveShutdown = result[0];
this._updatePowerOff();
}
}));
this._session.CanShutdownRemote(Lang.bind(this, function(result, error) {
if (error)
return;
this._haveShutdown = result[0];
this._updatePowerOff();
}));
},
_updatePowerOff: function() {
@ -219,6 +265,18 @@ const Indicator = new Lang.Class({
this._updateActionsVisibility();
},
_updateHaveSuspend: function() {
this._loginManager.canSuspend(Lang.bind(this, function(result) {
this._haveSuspend = result;
this._updateSuspend();
}));
},
_updateSuspend: function() {
this._suspendAction.visible = this._haveSuspend && !Main.sessionMode.isLocked;
this._updateActionsVisibility();
},
_createActionButton: function(iconName, accessibleName) {
let icon = new St.Button({ reactive: true,
can_focus: true,
@ -276,9 +334,14 @@ const Indicator = new Lang.Class({
this._lockScreenAction.connect('clicked', Lang.bind(this, this._onLockScreenClicked));
item.actor.add(this._lockScreenAction, { expand: true, x_fill: false });
this._suspendAction = this._createActionButton('media-playback-pause-symbolic', _("Suspend"));
this._suspendAction.connect('clicked', Lang.bind(this, this._onSuspendClicked));
this._powerOffAction = this._createActionButton('system-shutdown-symbolic', _("Power Off"));
this._powerOffAction.connect('clicked', Lang.bind(this, this._onPowerOffClicked));
item.actor.add(this._powerOffAction, { expand: true, x_fill: false });
this._altSwitcher = new AltSwitcher(this._powerOffAction, this._suspendAction);
item.actor.add(this._altSwitcher.actor, { expand: true, x_fill: false });
this._actionsItem = item;
this.menu.addMenuItem(item);
@ -309,7 +372,11 @@ const Indicator = new Lang.Class({
Main.overview.hide();
if (Main.screenShield)
Main.screenShield.lock(false);
Gdm.goto_login_session_sync(null);
Clutter.threads_add_repaint_func_full(Clutter.RepaintFlags.POST_PAINT, function() {
Gdm.goto_login_session_sync(null);
return false;
});
},
_onQuitSessionActivate: function() {
@ -317,110 +384,14 @@ const Indicator = new Lang.Class({
this._session.LogoutRemote(0);
},
_openSessionWarnDialog: function(sessions) {
let dialog = new ModalDialog.ModalDialog();
let subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject',
text: _("Other users are logged in.") });
dialog.contentLayout.add(subjectLabel, { y_fill: true,
y_align: St.Align.START });
let descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description'});
descriptionLabel.set_text(_("Shutting down might cause them to lose unsaved work."));
descriptionLabel.clutter_text.line_wrap = true;
dialog.contentLayout.add(descriptionLabel, { x_fill: true,
y_fill: true,
y_align: St.Align.START });
let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list' });
scrollView.add_style_class_name('vfade');
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
dialog.contentLayout.add(scrollView, { x_fill: true, y_fill: true });
let userList = new St.BoxLayout({ vertical: true });
scrollView.add_actor(userList);
for (let i = 0; i < sessions.length; i++) {
let session = sessions[i];
let userEntry = new St.BoxLayout({ style_class: 'login-dialog-user-list-item',
vertical: false });
let avatar = new UserWidget.Avatar(session.user);
avatar.update();
userEntry.add(avatar.actor);
let userLabelText = "";;
let userName = session.user.get_real_name() ?
session.user.get_real_name() : session.username;
if (session.info.remote)
/* Translators: Remote here refers to a remote session, like a ssh login */
userLabelText = _("%s (remote)").format(userName);
else if (session.info.type == "tty")
/* Translators: Console here refers to a tty like a VT console */
userLabelText = _("%s (console)").format(userName);
else
userLabelText = userName;
let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
vertical: true });
textLayout.add(new St.Label({ text: userLabelText }),
{ y_fill: false,
y_align: St.Align.MIDDLE,
expand: true });
userEntry.add(textLayout, { expand: true });
userList.add(userEntry, { x_fill: true });
}
let cancelButton = { label: _("Cancel"),
action: function() { dialog.close(); },
key: Clutter.Escape };
let powerOffButton = { label: _("Power Off"), action: Lang.bind(this, function() {
dialog.close();
this._session.ShutdownRemote();
}), default: true };
dialog.setButtons([cancelButton, powerOffButton]);
dialog.open();
},
_onPowerOffClicked: function() {
this.menu.itemActivated();
Main.overview.hide();
this._loginManager.listSessions(Lang.bind(this, function(result) {
let sessions = [];
let n = 0;
for (let i = 0; i < result.length; i++) {
let[id, uid, userName, seat, sessionPath] = result[i];
let proxy = new SystemdLoginSession(Gio.DBus.system,
'org.freedesktop.login1',
sessionPath);
this._session.ShutdownRemote(0);
},
if (proxy.Class != 'user')
continue;
if (proxy.State == 'closing')
continue;
if (proxy.Id == GLib.getenv('XDG_SESSION_ID'))
continue;
sessions.push({ user: this._userManager.get_user(userName),
username: userName,
info: { type: proxy.Type,
remote: proxy.Remote }
});
// limit the number of entries
n++;
if (n == MAX_USERS_IN_SESSION_DIALOG)
break;
}
if (n != 0)
this._openSessionWarnDialog(sessions);
else
this._session.ShutdownRemote();
}));
}
_onSuspendClicked: function() {
this.menu.itemActivated();
this._loginManager.suspend();
},
});

View File

@ -44,6 +44,9 @@ const StreamSlider = new Lang.Class({
this.item.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
this._slider.startDragging(event);
}));
this.item.actor.connect('key-press-event', Lang.bind(this, function(actor, event) {
return this._slider.onKeyPressEvent(actor, event);
}));
this._stream = null;
},
@ -154,6 +157,11 @@ const OutputStreamSlider = new Lang.Class({
Name: 'OutputStreamSlider',
Extends: StreamSlider,
_init: function(control) {
this.parent(control);
this._slider.actor.accessible_name = _("Volume");
},
_connectStream: function(stream) {
this.parent(stream);
this._portChangedId = stream.connect('notify::port', Lang.bind(this, this._portChanged));
@ -202,6 +210,7 @@ const InputStreamSlider = new Lang.Class({
_init: function(control) {
this.parent(control);
this._slider.actor.accessible_name = _("Microphone");
this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
this._icon.icon_name = 'audio-input-microphone-symbolic';

View File

@ -9,6 +9,7 @@ const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@ -33,6 +34,7 @@ const UnlockDialog = new Lang.Class({
_init: function(parentActor) {
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
style_class: 'login-dialog',
layout_manager: new Clutter.BoxLayout(),
visible: false });
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
@ -42,11 +44,12 @@ const UnlockDialog = new Lang.Class({
this._userName = GLib.get_user_name();
this._user = this._userManager.get_user(this._userName);
this._promptBox = new St.BoxLayout({ vertical: true });
this._promptBox = new St.BoxLayout({ vertical: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true });
this.actor.add_child(this._promptBox);
this._promptBox.add_constraint(new Clutter.AlignConstraint({ source: this.actor,
align_axis: Clutter.AlignAxis.BOTH,
factor: 0.5 }));
this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
this._authPrompt.connect('failed', Lang.bind(this, this._fail));
@ -80,7 +83,7 @@ const UnlockDialog = new Lang.Class({
Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic');
this._idleMonitor = new GnomeDesktop.IdleMonitor();
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, Lang.bind(this, this._escape));
},

View File

@ -29,7 +29,9 @@ const Avatar = new Lang.Class({
this.actor = new St.Bin({ style_class: params.styleClass,
track_hover: params.reactive,
reactive: params.reactive });
reactive: params.reactive,
width: this._iconSize,
height: this._iconSize });
},
setSensitive: function(sensitive) {

View File

@ -85,8 +85,12 @@ const ViewSelector = new Lang.Class({
this._entry.set_primary_icon(new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-find-symbolic' }));
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-symbolic' });
if (this._entry.get_text_direction() == Clutter.TextDirection.RTL)
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-rtl-symbolic' });
else
this._clearIcon = new St.Icon({ style_class: 'search-entry-icon',
icon_name: 'edit-clear-symbolic' });
this._iconClickedId = 0;
this._capturedEventId = 0;
@ -95,8 +99,8 @@ const ViewSelector = new Lang.Class({
this._workspacesPage = this._addPage(this._workspacesDisplay.actor,
_("Windows"), 'emblem-documents-symbolic');
this._appDisplay = new AppDisplay.AppDisplay();
this._appsPage = this._addPage(this._appDisplay.actor,
this.appDisplay = new AppDisplay.AppDisplay();
this._appsPage = this._addPage(this.appDisplay.actor,
_("Applications"), 'view-grid-symbolic');
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem);
@ -165,6 +169,11 @@ const ViewSelector = new Lang.Class({
this._showAppsButton.checked = !this._showAppsButton.checked;
},
showApps: function() {
Main.overview.show();
this._showAppsButton.checked = true;
},
show: function() {
this._activePage = this._workspacesPage;
@ -525,6 +534,13 @@ const ViewSelector = new Lang.Class({
return ViewPage.SEARCH;
},
setActivePage: function(page) {
if (page == ViewPage.WINDOWS)
this._showPage(this._workspacesPage);
else
this._showPage(this._appsPage);
},
fadeIn: function() {
let actor = this._activePage;
Tweener.addTween(actor, { opacity: 255,

View File

@ -132,6 +132,10 @@ const WandaSearchProvider = new Lang.Class({
}]);
},
filterResults: function(results) {
return results;
},
getInitialResultSet: function(terms) {
if (terms.join(' ') == MAGIC_FISH_KEY) {
this.searchSystem.setResults(this, [ FISH_NAME ]);
@ -150,8 +154,7 @@ const WandaSearchProvider = new Lang.Class({
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
},
createResultActor: function (resultMeta, terms) {
let icon = new WandaIconBin(resultMeta.id, resultMeta.name);
return icon.actor;
createResultObject: function (resultMeta, terms) {
return new WandaIconBin(resultMeta.id, resultMeta.name);
}
});

View File

@ -250,9 +250,6 @@ const WorkspaceTracker = new Lang.Class({
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let removingCurrentWorkspace = (emptyWorkspaces[activeWorkspaceIndex] &&
activeWorkspaceIndex < emptyWorkspaces.length - 1);
// Don't enter the overview when removing multiple empty workspaces at startup
let showOverview = (removingCurrentWorkspace &&
!emptyWorkspaces.every(function(x) { return x; }));
if (removingCurrentWorkspace) {
// "Merge" the empty workspace we are removing with the one at the end
@ -268,9 +265,6 @@ const WorkspaceTracker = new Lang.Class({
if (removingCurrentWorkspace) {
global.screen.get_workspace_by_index(global.screen.n_workspaces - 1).activate(global.get_current_time());
this._wm.unblockAnimations();
if (!Main.overview.visible && showOverview)
Main.overview.show();
}
this._checkWorkspacesId = 0;

View File

@ -20,8 +20,6 @@ const FOCUS_ANIMATION_TIME = 0.15;
const WINDOW_DND_SIZE = 256;
const SCROLL_SCALE_AMOUNT = 100 / 5;
const WINDOW_CLONE_MAXIMUM_SCALE = 0.7;
const LIGHTBOX_FADE_TIME = 0.1;
@ -345,19 +343,6 @@ const WindowOverlay = new Lang.Class({
this._animateVisible();
},
fadeIn: function() {
if (!this._hidden)
return;
this.show();
this.title.opacity = 0;
this._parentActor.raise_top();
Tweener.addTween(this.title,
{ opacity: 255,
time: CLOSE_BUTTON_FADE_TIME,
transition: 'easeOutQuad' });
},
chromeHeights: function () {
return [Math.max(this.borderSize, this.closeButton.height - this.closeButton._overlap),
this.title.height + this.title._spacing];
@ -374,7 +359,6 @@ const WindowOverlay = new Lang.Class({
let border = this.border;
Tweener.removeTweens(button);
Tweener.removeTweens(title);
Tweener.removeTweens(border);
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
@ -876,7 +860,6 @@ const UnalignedLayoutStrategy = new Lang.Class({
row.windows.push(window);
row.fullWidth += width;
} else {
this._sortRow(row);
break;
}
}
@ -886,6 +869,8 @@ const UnalignedLayoutStrategy = new Lang.Class({
let maxRow;
for (let i = 0; i < numRows; i++) {
let row = rows[i];
this._sortRow(row);
if (!maxRow || row.fullWidth > maxRow.fullWidth)
maxRow = row;
gridHeight += row.fullHeight;
@ -1143,7 +1128,7 @@ const Workspace = new Lang.Class({
clone.actor.set_scale(scale, scale);
clone.actor.set_opacity(255);
clone.overlay.relayout(false);
this._showWindowOverlay(clone, overlay, isOnCurrentWorkspace);
this._showWindowOverlay(clone, overlay);
}
}
},
@ -1173,23 +1158,19 @@ const Workspace = new Lang.Class({
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._showWindowOverlay(clone, overlay, true);
this._showWindowOverlay(clone, overlay);
})
});
clone.overlay.relayout(true);
},
_showWindowOverlay: function(clone, overlay, fade) {
_showWindowOverlay: function(clone, overlay) {
if (clone.inDrag)
return;
if (overlay) {
if (fade)
overlay.fadeIn();
else
if (overlay && overlay._hidden)
overlay.show();
}
},
_delayedWindowRepositioning: function() {
@ -1433,6 +1414,10 @@ const Workspace = new Lang.Class({
if (this._positionWindowsId > 0)
Meta.later_remove(this._positionWindowsId);
if (this._actualGeometryLater > 0)
Meta.later_remove(this._actualGeometryLater);
this._windows = [];
},

View File

@ -536,20 +536,6 @@ const ThumbnailsBox = new Lang.Class({
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor._delegate = this;
// When we animate the scale, we don't animate the requested size of the thumbnails, rather
// we ask for our final size and then animate within that size. This slightly simplifies the
// interaction with the main workspace windows (instead of constantly reallocating them
// to a new size, they get a new size once, then use the standard window animation code
// allocate the windows to their new positions), however it causes problems for drawing
// the background and border wrapped around the thumbnail as we animate - we can't just pack
// the container into a box and set style properties on the box since that box would wrap
// around the final size not the animating size. So instead we fake the background with
// an actor underneath the content and adjust the allocation of our children to leave space
// for the border and padding of the background actor.
this._background = new St.Bin({ style_class: 'workspace-thumbnails-background' });
this.actor.add_actor(this._background);
let indicator = new St.Bin({ style_class: 'workspace-thumbnail-indicator' });
// We don't want the indicator to affect drag-and-drop
@ -1042,9 +1028,6 @@ const ThumbnailsBox = new Lang.Class({
},
_getPreferredHeight: function(actor, forWidth, alloc) {
// See comment about this._background in _init()
let themeNode = this._background.get_theme_node();
// Note that for getPreferredWidth/Height we cheat a bit and skip propagating
// the size request to our children because we know how big they are and know
// that the actors aren't depending on the virtual functions being called.
@ -1052,24 +1035,21 @@ const ThumbnailsBox = new Lang.Class({
if (this._thumbnails.length == 0)
return;
let spacing = this.actor.get_theme_node().get_length('spacing');
let themeNode = this.actor.get_theme_node();
let spacing = themeNode.get_length('spacing');
let nWorkspaces = global.screen.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
[alloc.min_size, alloc.natural_size] =
themeNode.adjust_preferred_height(totalSpacing,
totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE);
alloc.min_size = totalSpacing;
alloc.natural_size = totalSpacing + nWorkspaces * this._porthole.height * MAX_THUMBNAIL_SCALE;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
// See comment about this._background in _init()
let themeNode = this._background.get_theme_node();
if (this._thumbnails.length == 0)
return;
// We don't animate our preferred width, which is always reported according
// to the actual number of current workspaces, we just animate within that
let themeNode = this.actor.get_theme_node();
let spacing = this.actor.get_theme_node().get_length('spacing');
let nWorkspaces = global.screen.n_workspaces;
@ -1081,28 +1061,26 @@ const ThumbnailsBox = new Lang.Class({
scale = Math.min(scale, MAX_THUMBNAIL_SCALE);
let width = Math.round(this._porthole.width * scale);
[alloc.min_size, alloc.natural_size] =
themeNode.adjust_preferred_width(width, width);
alloc.min_size = width;
alloc.natural_size = width;
},
_allocate: function(actor, box, flags) {
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);
// See comment about this._background in _init()
let themeNode = this._background.get_theme_node();
let contentBox = themeNode.get_content_box(box);
if (this._thumbnails.length == 0) // not visible
return;
let themeNode = this.actor.get_theme_node();
let portholeWidth = this._porthole.width;
let portholeHeight = this._porthole.height;
let spacing = this.actor.get_theme_node().get_length('spacing');
let spacing = themeNode.get_length('spacing');
// Compute the scale we'll need once everything is updated
let nWorkspaces = global.screen.n_workspaces;
let totalSpacing = (nWorkspaces - 1) * spacing;
let avail = (contentBox.y2 - contentBox.y1) - totalSpacing;
let avail = (box.y2 - box.y1) - totalSpacing;
let newScale = (avail / nWorkspaces) / portholeHeight;
newScale = Math.min(newScale, MAX_THUMBNAIL_SCALE);
@ -1131,21 +1109,6 @@ const ThumbnailsBox = new Lang.Class({
else
slideOffset = thumbnailWidth + themeNode.get_padding(St.Side.RIGHT);
let childBox = new Clutter.ActorBox();
// The background is horizontally restricted to correspond to the current thumbnail size
// but otherwise covers the entire allocation
if (rtl) {
childBox.x1 = box.x1;
childBox.x2 = box.x2 - ((contentBox.x2 - contentBox.x1) - thumbnailWidth);
} else {
childBox.x1 = box.x1 + ((contentBox.x2 - contentBox.x1) - thumbnailWidth);
childBox.x2 = box.x2;
}
childBox.y1 = box.y1;
childBox.y2 = box.y2;
this._background.allocate(childBox, flags);
let indicatorY1 = this._indicatorY;
let indicatorY2;
// when not animating, the workspace position overrides this._indicatorY
@ -1157,7 +1120,7 @@ const ThumbnailsBox = new Lang.Class({
let indicatorLeftFullBorder = indicatorThemeNode.get_padding(St.Side.LEFT) + indicatorThemeNode.get_border_width(St.Side.LEFT);
let indicatorRightFullBorder = indicatorThemeNode.get_padding(St.Side.RIGHT) + indicatorThemeNode.get_border_width(St.Side.RIGHT);
let y = contentBox.y1;
let y = box.y1;
if (this._dropPlaceholderPos == -1) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
@ -1165,6 +1128,8 @@ const ThumbnailsBox = new Lang.Class({
}));
}
let childBox = new Clutter.ActorBox();
for (let i = 0; i < this._thumbnails.length; i++) {
let thumbnail = this._thumbnails[i];
@ -1173,10 +1138,10 @@ const ThumbnailsBox = new Lang.Class({
let x1, x2;
if (rtl) {
x1 = contentBox.x1 + slideOffset * thumbnail.slidePosition;
x1 = box.x1 + slideOffset * thumbnail.slidePosition;
x2 = x1 + thumbnailWidth;
} else {
x1 = contentBox.x2 - thumbnailWidth + slideOffset * thumbnail.slidePosition;
x1 = box.x2 - thumbnailWidth + slideOffset * thumbnail.slidePosition;
x2 = x1 + thumbnailWidth;
}
@ -1223,11 +1188,11 @@ const ThumbnailsBox = new Lang.Class({
}
if (rtl) {
childBox.x1 = contentBox.x1;
childBox.x2 = contentBox.x1 + thumbnailWidth;
childBox.x1 = box.x1;
childBox.x2 = box.x1 + thumbnailWidth;
} else {
childBox.x1 = contentBox.x2 - thumbnailWidth;
childBox.x2 = contentBox.x2;
childBox.x1 = box.x2 - thumbnailWidth;
childBox.x2 = box.x2;
}
childBox.x1 -= indicatorLeftFullBorder;
childBox.x2 += indicatorRightFullBorder;

View File

@ -62,7 +62,6 @@ const WorkspacesView = new Lang.Class({
this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling
this._animatingScroll = false; // programatically updating the adjustment
this._zoomOut = false; // zoom to a larger area
this._inDrag = false; // dragging a window
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
@ -168,14 +167,6 @@ const WorkspacesView = new Lang.Class({
this._workspaces[i].setActualGeometry(geom);
},
_lookupWorkspaceForMetaWindow: function (metaWindow) {
for (let i = 0; i < this._workspaces.length; i++) {
if (this._workspaces[i].containsMetaWindow(metaWindow))
return this._workspaces[i];
}
return null;
},
getActiveWorkspace: function() {
let active = global.screen.get_active_workspace_index();
return this._workspaces[active];
@ -433,10 +424,6 @@ const WorkspacesView = new Lang.Class({
this._workspaces[i].actor.y += dy;
}
},
_getWorkspaceIndexToRemove: function() {
return global.screen.get_active_workspace_index();
}
});
Signals.addSignalMethods(WorkspacesView.prototype);
@ -540,12 +527,6 @@ const WorkspacesDisplay = new Lang.Class({
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
this._workspacesViews = [];
for (let i = 0; i < this._workspaces.length; i++)
for (let w = 0; w < this._workspaces[i].length; w++) {
this._workspaces[i][w].disconnectAll();
this._workspaces[i][w].destroy();
}
},
_workspacesOnlyOnPrimaryChanged: function() {
@ -561,10 +542,6 @@ const WorkspacesDisplay = new Lang.Class({
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].destroy();
for (let i = 0; i < this._workspaces.length; i++)
for (let w = 0; w < this._workspaces[i].length; w++)
this._workspaces[i][w].destroy();
this._workspacesViews = [];
this._workspaces = [];
let monitors = Main.layoutManager.monitors;

View File

@ -3,6 +3,7 @@
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Main = imports.ui.main;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const DND = imports.ui.dnd;
@ -20,7 +21,8 @@ const XdndHandler = new Lang.Class({
Main.uiGroup.add_actor(this._dummy);
this._dummy.hide();
global.init_xdnd();
if (!Meta.is_wayland_compositor())
global.init_xdnd();
global.connect('xdnd-enter', Lang.bind(this, this._onEnter));
global.connect('xdnd-position-changed', Lang.bind(this, this._onPositionChanged));

View File

@ -4,6 +4,7 @@
data/50-gnome-shell-system.xml.in
data/gnome-shell.desktop.in.in
data/gnome-shell-extension-prefs.desktop.in.in
data/gnome-shell-wayland.desktop.in.in
data/org.gnome.shell.gschema.xml.in.in
js/extensionPrefs/main.js
js/gdm/authPrompt.js
@ -42,6 +43,7 @@ js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
js/ui/status/bluetooth.js
js/ui/status/brightness.js
js/ui/status/keyboard.js
js/ui/status/network.js
js/ui/status/power.js

745
po/ar.po

File diff suppressed because it is too large Load Diff

1771
po/as.po

File diff suppressed because it is too large Load Diff

1426
po/be.po

File diff suppressed because it is too large Load Diff

1866
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

873
po/cs.po

File diff suppressed because it is too large Load Diff

1565
po/da.po

File diff suppressed because it is too large Load Diff

1046
po/de.po

File diff suppressed because it is too large Load Diff

1616
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2921
po/eo.po

File diff suppressed because it is too large Load Diff

825
po/es.po

File diff suppressed because it is too large Load Diff

1007
po/et.po

File diff suppressed because it is too large Load Diff

1750
po/eu.po

File diff suppressed because it is too large Load Diff

1798
po/fa.po

File diff suppressed because it is too large Load Diff

1786
po/fi.po

File diff suppressed because it is too large Load Diff

1568
po/fr.po

File diff suppressed because it is too large Load Diff

656
po/ga.po

File diff suppressed because it is too large Load Diff

824
po/gl.po

File diff suppressed because it is too large Load Diff

1202
po/he.po

File diff suppressed because it is too large Load Diff

1154
po/hu.po

File diff suppressed because it is too large Load Diff

711
po/id.po

File diff suppressed because it is too large Load Diff

1225
po/it.po

File diff suppressed because it is too large Load Diff

1194
po/ja.po

File diff suppressed because it is too large Load Diff

1153
po/kk.po

File diff suppressed because it is too large Load Diff

1502
po/ko.po

File diff suppressed because it is too large Load Diff

967
po/lt.po

File diff suppressed because it is too large Load Diff

1814
po/lv.po

File diff suppressed because it is too large Load Diff

674
po/nb.po

File diff suppressed because it is too large Load Diff

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