Compare commits

...

103 Commits
3.5.3 ... 3.5.4

Author SHA1 Message Date
edb96cde70 Bump version to 3.5.4
Update NEWS
Require Mutter 3.5.4
2012-07-17 17:54:41 +02:00
e06ecb8f0c gdm: port from libgdmgreeter to libgdm
When GDM was moved over to GDBus it dropped the libgdmgreeter
library and introduced a new libgdm library with a somewhat
different API.

The main differences in the API are:

1) open_connection is now implicit and automatic
2) conversations don't need to be started explicitly, they're
   started just-in-time when verification is requested
3) The functions are split up between the client, and new
   helper objects that correspond to the dbus interfaces
   they were generated from (one for user verification,
   one for greeter specific operations, and a couple more
   that aren't used by gnome-shell).
4) libgdm supports reauthenticating in an already running
   session, so user switching should now affect the users
   session more like screen unlocking does.

This commit moves the shell over to the new library.

Based on work by Giovanni Campagna <gcampagna@src.gnome.org>

https://bugzilla.gnome.org/show_bug.cgi?id=676401
2012-07-17 11:38:28 -04:00
2791d948e9 UserMenu: move Install Updates at the end
Follow the design update and move the Install Updates item at
the end, together with Power Off.

https://bugzilla.gnome.org/show_bug.cgi?id=680080
2012-07-17 12:35:08 +02:00
360e6e790a lookingGlass: Use one red border effect
This makes the code a bit cleaner, and reduces the chances of
having a border effect "leaking", or having two at the same time.

https://bugzilla.gnome.org/show_bug.cgi?id=679944
2012-07-16 20:39:55 -04:00
d0807c8276 lookingGlass: Don't use a global
As part of wanting to reuse some of the looking glass components,
don't use Main.lookingGlass, but instead pass the parent around.
Don't adjust the evaluator just yet, though. We'll split it into
a separate class soon.

https://bugzilla.gnome.org/show_bug.cgi?id=679944
2012-07-16 20:39:55 -04:00
75d0362cd8 link: Remove
The looking glass is the only consumer of the Link, and it's such a
basic wrapper around a button that it's not worth it.

https://bugzilla.gnome.org/show_bug.cgi?id=679944
2012-07-16 20:39:55 -04:00
4f7c554d8d lookingGlass: Remove old signal handler
This 'selected' signal is from the days of the "Heirarchy" tab, before
it was replaced by the "Windows" tab. Those were the days.

https://bugzilla.gnome.org/show_bug.cgi?id=679944
2012-07-16 20:39:55 -04:00
8b81f23caf lookingGlass: Use a more standard chevron
'>>>' is used by the REPL history (as well as plenty of other REPLs).
Using 'js>>>' to enter things makes the history look unaligned and strange.

https://bugzilla.gnome.org/show_bug.cgi?id=679944
2012-07-16 20:39:55 -04:00
0098c2b7f7 Move ibus status icon under keyboard
This makes sense, since we are covering input methods and keyboard
layouts in the same keyboard menu. The effect of this change is that
the ibus status icon no longer appears in the system status area.
2012-07-16 13:31:12 -04:00
f0e03b5e82 WorkspaceSwitcherPopup: fix for dynamic workspace changes
Changing the number of workspaces while the popup was visible (which
happens when moving windows on the last non empty workspace) resulted
in a wrong layout. Fix that, by listening to workspace-added and
workspace-removed signals, and by always requesting an updated size
from the actor.

https://bugzilla.gnome.org/show_bug.cgi?id=679005
2012-07-16 19:15:53 +02:00
be2f1001a5 Updated Spanish translation 2012-07-16 16:44:43 +02:00
cf08b4d56a Updated Telugu Translation 2012-07-16 08:14:26 +05:30
04074f883f ibusCandidatePopup: A candidate popup for IBus input methods
This is an implementation of the org.freedesktop.IBus.Panel API which
shows a shell style popup (BoxPointer) when using an IBus input
method.

Based on code from the ibus-gjs project[1].

[1] https://github.com/fujiwarat/ibus-gjs

https://bugzilla.gnome.org/show_bug.cgi?id=641531
2012-07-16 00:59:13 +02:00
14d3235f1a status/keyboard: Add support for IBus input sources
We connect to the IBus daemon asyncronously and use it to query info
about input sources of the type 'ibus'. In case the daemon is or
becomes unreachable we just skip showing input sources of this type.

https://bugzilla.gnome.org/show_bug.cgi?id=641531
2012-07-16 00:59:11 +02:00
e00c1cbd20 Updated Belarusian translation. 2012-07-15 11:52:59 +03:00
3df3f0d9dc portability: use /bin/sh instead of /bin/bash
There is nothing requiring bash specific features in this script, so
just use /bin/sh which is portable amongst all Unices.

https://bugzilla.gnome.org/show_bug.cgi?id=679847
2012-07-15 10:17:24 +02:00
985db40547 test-gapplication: Untabify, add modeline 2012-07-14 18:27:10 -04:00
c9fa0fdff0 .gitignore: Update 2012-07-14 18:27:10 -04:00
fe69ea305b calendar: Fix grid lines in RTL locales
The calendar grid is build by giving each element right and bottom
borders, all top-most elements a top border, and all left-most
elements a left border. However in RTL locales, we currently add
the left border to the *right-most* elements, resulting in the grid
appearing clipped on the left side.

https://bugzilla.gnome.org/show_bug.cgi?id=679879
2012-07-14 23:27:14 +02:00
ff9088e42b tests: Fix make dist 2012-07-14 11:48:54 +02:00
f556cdf0ca Updated Traditional Chinese translation(Hong Kong and Taiwan) 2012-07-14 14:00:32 +08:00
c671ff74c6 windowManager: Replace custom shader with builtin ClutterEffects
While modal dialogs were attached to the parent's titlebar, it
made sense to leave the top of the parent window at full color.
With the new position of modal dialogs, it makes more sense to dim
the entire parent window, so we can use a combination of Clutter's
BrightnessContrast- and DesaturateEffect instead of our own custom
shader.

https://bugzilla.gnome.org/show_bug.cgi?id=674499
2012-07-14 03:33:57 +02:00
04570ac783 windowManager: Remove 'animate' parameter from (un)dimWindow()
The parameter has become rather pointless since we always pass the
same value.

https://bugzilla.gnome.org/show_bug.cgi?id=674499
2012-07-14 03:33:57 +02:00
6ab25cd791 windowManager: Update animation of attached modals
With modal dialogs no longer being attached to their parents'
titlebar, the current animation no longer works too well. Use
a simple fade animation instead.

https://bugzilla.gnome.org/show_bug.cgi?id=674499
2012-07-14 03:33:56 +02:00
a04350f7ce windowManager: Split _shouldAnimate() into two functions
... instead of using an optional parameter.

https://bugzilla.gnome.org/show_bug.cgi?id=674499
2012-07-14 03:33:56 +02:00
b7018de7e0 magnifier: Fix grayscale effect
Commit 8754b2767c added a grayscale effect to the magnifier,
but missed actually adding it to the actor.

https://bugzilla.gnome.org/show_bug.cgi?id=674499
2012-07-14 00:46:32 +02:00
d212d57466 shell-embedded-window: Remove hacks for old and fixed Clutter bug
We used to use realize/unrealize instead of map/unmap in ShellEmbeddedWindow
because there originally was no map/unmap. The days of this are long gone...

https://bugzilla.gnome.org/show_bug.cgi?id=672790
2012-07-13 17:28:50 -04:00
c4e7d8ed8c Assamese translation updated 2012-07-13 18:30:31 +05:30
464813ecbb Assorted test-gapplication fixes
Move this test toghether with the others, and set the appmenu
only after the application is registered (i.e. in startup)

https://bugzilla.gnome.org/show_bug.cgi?id=678978
2012-07-13 12:29:44 +02:00
9812771dcd dash: hide tooltips when overview begins hiding
Otherwise the tooltip remains visible until the overview animation is
completed, which is odd.

https://bugzilla.gnome.org/show_bug.cgi?id=674241
2012-07-12 23:50:30 -04:00
6f605598de global: don't run a garbage collection on tweeners end
This currently causes the shell to freeze very often in a thread
deadlock, and the gjs garbage collector behavior is currently getting
fixed at the right level in gjs itself.

https://bugzilla.gnome.org/show_bug.cgi?id=679832
2012-07-12 20:11:39 -04:00
85bc8ccccc shell-global: remove shell_global_gc()
It's unused now.

https://bugzilla.gnome.org/show_bug.cgi?id=679832
2012-07-12 20:11:39 -04:00
e756c2dbce js: use System.gc() instead of shell_global_gc()
gjs now offers a gc() method in the System module, no need to use our
own.

https://bugzilla.gnome.org/show_bug.cgi?id=679832
2012-07-12 20:11:38 -04:00
e82fe14f00 shell-global: remove unused shell_global_maybe_gc()
It's not used anywhere, and we're removing the manual garbage collection
invocations anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=679832
2012-07-12 20:11:38 -04:00
de65739c01 windowManager: Remove unused function
https://bugzilla.gnome.org/show_bug.cgi?id=679500
2012-07-12 10:11:57 -04:00
e1ec89a133 extensionSystem: Fix error emitting when enabling/disabling
We don't have an extension object here.
2012-07-11 22:46:59 -04:00
bdb3410d9d st-icon: Fix potential crash involving shadows
If the icon is painted before the new shadow is around, a stale
shadow material will be painted with a NULL shadow spec, resulting
in a crash.

https://bugzilla.gnome.org/show_bug.cgi?id=679776
2012-07-11 21:08:53 -04:00
168e0b5a42 mount-operation: implement show-unmount-progress
Show a notification when we receive a show-unmount-progress signal on
the mount operation we use for unmounting.
The notification will either turn fade out automatically with a
completion message when the unmount successfully completes, or will
disappear in case the operation is aborted underway (for example because
the device has been unplugged in the meantime).

https://bugzilla.gnome.org/show_bug.cgi?id=676125
2012-07-11 20:03:45 -04:00
f906cfe5f6 appMenu: Disable app menu during startup animations
When activating the app menu while displaying a startup notification
animation, the application shown in the menu does not match the
application providing the menu. To avoid this case, make the menu
button unreactive while playing the animation.

https://bugzilla.gnome.org/show_bug.cgi?id=672322
2012-07-10 22:36:45 +02:00
9faac81a37 panel: don't break when indicator has no menu
Status indicators don't have necessarily a menu. If they have not we don't
want to add the menu in the PopupMenuManager.

https://bugzilla.gnome.org/show_bug.cgi?id=678694
2012-07-10 22:21:07 +02:00
b90e7eb95c Updated Hebrew translation. 2012-07-10 23:09:02 +03:00
1e286e43ad extensionDownloader: Add update/blacklist support for extensions
This is a bare-bones copy/replace. It does not implement ChangeLog
support. If we cannot get System Updates integration, I will implement
notification support.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-10 14:36:41 -04:00
539993b4f4 extensionDownloader: Move extension loading code to the install dialog
Move the part that loads the extension to the callback. This makes the
next patch a lot cleaner.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-10 14:36:41 -04:00
1363d30f79 extensionUtils: Don't crash on startup for an empty directory
https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-10 14:36:41 -04:00
3a48daaa64 Don't build documentation for the recorder when it's disabled
When building with gtk-doc but no recorder, build fails trying to
get the GType of ShellRecorder. Fix it by skipping its header file
when disabled.
2012-07-10 19:36:57 +02:00
d2b4a65e65 Updated Norwegian nynorsk translation 2012-07-10 15:22:02 +02:00
1ead290c23 Updated Norwegian bokmål translation 2012-07-10 08:32:10 +02:00
6658660355 magnifier: fix a copy/paste typo
Introduced in 8754b2767c
2012-07-09 18:12:38 -04:00
85ab019987 Updated translations 2012-07-09 21:47:31 +02:00
460cda2aa1 recorder: Port to GStreamer 1.0 API
GStreamer developers are currently finishing the 0.11 version, which
will become 1.0. Port the screen recorder to the new API.

https://bugzilla.gnome.org/show_bug.cgi?id=679445
2012-07-09 16:35:06 +02:00
2d913578e1 messageTray: don't show the message tray when a new notification is shown
The message tray with its gradient background should only be displayed
when the summary is shown.

https://bugzilla.gnome.org/show_bug.cgi?id=677210
2012-07-08 12:56:09 -04:00
34831796f6 UserMenu: show "Install Updates & Restart" when appropriate
When PackageKit signals that it prepared an update, offer an option
to reboot and apply it, using a helper that will setup the next
reboot and then calling to gnome-session.

https://bugzilla.gnome.org/show_bug.cgi?id=677394
2012-07-07 18:21:35 +02:00
8754b2767c Add a grayscale effect
This commit adds a grayscale effect to the magnifier, similar to
the lightness, brightness and contrast effects that are already there.

The effect is configured with the
org.gnome.desktop.a11y.magnifier.color-saturation setting, which
can take values from 0.0 (grayscale) to 1.0 (full color).

Based on a patch by Matthias Clasen <mclasen@redhat.com>

https://bugzilla.gnome.org/show_bug.cgi?id=676782
2012-07-06 15:18:01 -04:00
04fb688f7d css: Re-add rule lost in commit fd256b6 2012-07-06 19:19:22 +02:00
58dbd285fc Updated Norwegian bokmål translation 2012-07-06 19:01:20 +02:00
cf6f149888 boxpointer: Change 'animate' parameter on show/hide to a bitmask
This allows us to have more control of the animation.

https://bugzilla.gnome.org/show_bug.cgi?id=678337
2012-07-06 16:04:42 +02:00
8d017ceaf1 boxpointer: Flip side if we would end outside the monitor
This flips the BoxPointer if it ends outside the monitor and we have
enough space to fit it inside, on the opposite side of the source
actor.

https://bugzilla.gnome.org/show_bug.cgi?id=678164
2012-07-06 16:03:59 +02:00
02428019fa messageTray: Remove unused method parameter
The alignment of the arrow tip regarding the source actor is set with
setSourceAlignment() and its default is already 0.5 .

https://bugzilla.gnome.org/show_bug.cgi?id=678164
2012-07-06 16:03:49 +02:00
b4464929cb Implemented banner support for the login screen
Based on a patch by Marius Rieder,
https://bugzilla.gnome.org/review?bug=665346
2012-07-06 09:01:25 -04:00
3ea22f8b0e Updated Spanish translation 2012-07-06 12:25:06 +02:00
9745e97e14 Add support for inhibiting automount
When connecting to virtual machines with usb-device redirection, such as Spice
enabled vms, automount may get in the way. Specifically if auto-usbredir is
enabled in the vm-viewer, then the usbredir code and the automount code race
for who gets to the device first.

If the automount code wins the race this is a problem, since usbredir causes a
device-disconnect (iow the usb mass storage driver sees an unplug), so in the
end usbredir always wins, and we end up with a non clean potentially corrupt
filesystem. Also see:
https://bugzilla.redhat.com/show_bug.cgi?id=812972

There for the need exists to be able to inhibit gnome-shell's automounting,
since all other inhibits run through gnome-session, I've chosen to do the same
for the automount-inhibiting. I've also submitted a patch to gnome-session to
reserve flag value 16 for this, see bug 678595.

This patch adds support to gnome-shell to honor this new inhibit flag.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>

https://bugzilla.gnome.org/show_bug.cgi?id=678597
2012-07-06 08:28:29 +02:00
6c6e182ecc Updated Bulgarian translation 2012-07-06 08:44:34 +03:00
7973dd45b7 Updated Bulgarian translation 2012-07-06 08:29:33 +03:00
a1837dde68 lookingGlass: Don't use a signal callback on 'paint' to draw the border
Instead, use a ClutterEffect, the proper API that has existed for since 1.0.
The 'paint' signal will go away for Clutter 2.0.

https://bugzilla.gnome.org/show_bug.cgi?id=679464
2012-07-05 14:20:50 -04:00
4448b65a18 telepathyClient: don't add log messages on presence changes
The log messages about presence changes unnecessarily cluttered the
notification.
Instead, we now present the presence states (online, offline, away, busy)
with an icon placed right next to the avatar. We also no longer show
notifications on presence changes.

https://bugzilla.gnome.org/show_bug.cgi?id=669508
2012-07-05 14:09:09 -04:00
2231c23c4d Updated Arabic translation 2012-07-05 16:58:17 +02:00
f17fc43d6e recorder: Don't crash on pipeline errors
In case of error, the recorder pipeline is reset to NULL, so don't
access current_pipeline->src in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=679445
2012-07-05 16:23:21 +02:00
f9dbe56785 recorder-src: Use normal GObject boilerplate
Gst will drop its own boilerplate in 1.0, so just use G_DEFINE_TYPE.

https://bugzilla.gnome.org/show_bug.cgi?id=679445
2012-07-05 16:23:20 +02:00
8845a2170c networkAgent: use absolute path if configured
Signed-off-by: Clemens Buchacher <drizzd@aon.at>

https://bugzilla.gnome.org/show_bug.cgi?id=679212
2012-07-04 19:39:26 +02:00
a4b1ebd8c3 Assamese translation reviewed 2012-07-04 22:07:11 +05:30
66adeef9bd dateMenu: Use .desktop file to launch calendar
When selecting "Open Calendar" in the date menu, the configured
application is launched via command line, so we don't get any
startup notification. If Evolution is used as calendar application,
launch it via the .desktop file added by the last commit instead in
order to fix the issue.

https://bugzilla.gnome.org/show_bug.cgi?id=677907
2012-07-04 00:24:05 +02:00
20769f68a7 calendar-server: Add .desktop file for evolution calendar
When selecting "Open Calendar" in the date menu, the configured
application is launched via command line, so we don't get any
startup notification. In order to fix the issue at least for our
default calendar, add a hidden .desktop file for evolution's
calendar component.

https://bugzilla.gnome.org/show_bug.cgi?id=677907
2012-07-04 00:24:05 +02:00
e92719b98d userMenu: Don't disconnect account signals when disabled
By disconnecting the 'notify::connection-status' signal as soon as the account
is disabled, we were missing the signal telling us when the status was moving
from CONNECTING/CONNECTED to DISCONNECTED and so the status icon was never
updated.

What we really want is to disconnect the signal when the account is removed
from the account manager as we don't care about it any more.

https://bugzilla.gnome.org/show_bug.cgi?id=669112
2012-07-03 12:37:58 +02:00
59246babea search: Remove createResultContainer() hook
It is now unused since the contacts search provider was the only
consumer, so remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=677442
2012-07-03 12:19:32 +02:00
23e86d7dd5 extensionDownloader: Clean up names of methods
FromUUID is redundant.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
c99e8eb29d extensionSystem: Be saner at error handling
Use our native JS error system in the "extension system" API, only
using the signal/log-based error reporting at the last mile. Additionally,
delete the directory if loading the extension failed, and report the error
back over DBus.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
7949397958 shellDBus: Add a real error reporting system to InstallExtensionRemote
Instead of using the 'extension-state-changed' signal to relay errors,
use DBus's native error mechanism to inform the method caller that the
call has failed. This requires making the method actually asynchronous
so that we don't block the browser, which is stuck waiting for a reply
from the browser plugin. To ensure this, we need to modify the browser
plugin API to ensure its extesion installation method is asynchronous.

Additionally, this lets us remove the awful, broken hacks that we used
when a user clicked the "Cancel" button, replacing it by a DBus return
value.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
1d1359b58f extensionDownloader: Properly error out when downloading/parsing infos
When the extension downloader was originally designed, the information
downloading part was inserted at the last minute, along with the modal
dialog as a security feature to make sure an extension didn't silently
get installed on the user's machines either due to a security issue in
the browser-plugin, or an XSS issue on the extensions website. Correct
the mistake I made when writing the code; instead of dropping an error
on the floor, log it correctly. This "bug" has already bitten a number
of users who forgot to configure proxy settings in the control center.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
8915bb4892 extensionDownloader: Fix errors during error paths during installation
https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
6a117ac12f browser-plugin: Rework scriptable method argument parsing and dispatch
Since we're going to move to a much more complicated (async!) solution
in a little bit, we're going to require a lot more machinery to handle
that. To help with that, let's rework invocation dispatch so that it's
more generic. Introduce a parse_args system similar to gjs_parse_args,
use X Macros to help with the repetitive parts of the method dispatch.
This shouldn't cause any API breaks, so API_VERSION should still be 4.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
67689f1a6d browser-plugin: Prevent a copy when checking for valid extension UUIDs
Instead of using g_strndup to copy the NPString that gets passed to us
by the plugin host, just use the equally-as-good NPString directly. We
still need to copy the string when passing it over DBus, as there's no
easy way to construct a string GVariant from a length-prefixed string.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
48b83f1ffd extensionDownloader: Fix loading of downloaded extensions
We refactored the ExtensionSystem API to take an extension object,
but forgot to update the downloader.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
7da0f398a5 shellDBus: Split extensions API out into a separate DBus interface
The generic "Shell" interface was getting a bit too crowded.

https://bugzilla.gnome.org/show_bug.cgi?id=679099
2012-07-02 18:29:56 -04:00
7e277fdd4a shellDBus: Clean up 2012-07-02 18:29:55 -04:00
5d10d8566b Updated Vietnamese translation 2012-07-01 11:05:01 +07:00
a10295f584 po/vi: import from Damned Lies 2012-07-01 11:02:53 +07:00
46cf9faa11 PolkitAgent: Look for the right password prompt
Pam seems to give us different strings, sometimes 'Password:',
sometimes 'Password: '. Look for both of these when replacing
them with a translated prompt.

https://bugzilla.gnome.org/show_bug.cgi?id=675300
2012-06-29 17:55:20 -04:00
971341bb53 Updated POTFILES.in 2012-06-29 19:44:23 +02:00
2b2a235a49 network: don't ask for always-ask secrets when interaction isn't allowed
Clearly a typo...

https://bugzilla.gnome.org/show_bug.cgi?id=679091
2012-06-29 09:32:45 -05:00
970b9deeaa shell: Remove ContactSystem
Remove the now unused ShellContactSystem. As a side effect, we no
longer depend on folks now.

https://bugzilla.gnome.org/show_bug.cgi?id=677442
2012-06-29 11:21:50 +02:00
fd256b624c overview: Remove contacts search provider
With gnome-contacts implementing a remote search provider, the
built-in contacts search is now unnecessary duplication; remote it.

https://bugzilla.gnome.org/show_bug.cgi?id=677442
2012-06-29 11:21:50 +02:00
698fb64be9 userMenu: Move "Power off" item to the bottom
The current position below "System Settings" is problematic - the
items are unrelated, and misclicks will result in a scary system
modal dialog that has to be cancelled.
Move items around a bit to avoid this problem.

https://bugzilla.gnome.org/show_bug.cgi?id=678887
2012-06-29 11:21:50 +02:00
9561f77b17 Main: fix ctrl-alt-arrow in the overview
Fixes a regression introduced in de72065, which changed the method names
but forgot to update this code path.

https://bugzilla.gnome.org/show_bug.cgi?id=679005
2012-06-27 22:17:47 +02:00
c3d3d346d4 WindowManager: ignore ctrl-alt-left/right
Fixes a regression introduced in de72065a

https://bugzilla.gnome.org/show_bug.cgi?id=679005
2012-06-27 22:17:46 +02:00
e43fe98263 windowManager: Hold the window on the stage while going between workspaces
Right now the "move to workspace" keyboard shortcut transition isn't smooth. It
shows the window disappearing, hopping to the next workspace, and then sliding
into view. "Pin" the window to the stage while the animation is in progress,
then release it afterwards.

https://bugzilla.gnome.org/show_bug.cgi?id=660839
2012-06-27 19:35:37 +02:00
04dbf15d9b WindowManager: handle move-to-workspace keybindings
Install a custom handler for move-to-workspace-* keybindings that
shows the workspace switcher, which gives the user a sense of
direction when navigating with the keyboard.

https://bugzilla.gnome.org/show_bug.cgi?id=674104
2012-06-27 19:35:37 +02:00
de72065a4a WorkspaceSwitcher: simplify code for handling keybindings
Most of code implementing workspace switches was repeated with
minor differences on each direction. Instead, consolidate it
and use the new meta_workspace_get_neighbor.

https://bugzilla.gnome.org/show_bug.cgi?id=674104
2012-06-27 19:35:37 +02:00
a1bb0ec738 WindowTracker: fix ref counting bug in get_app_for_window()
get_app_for_window() is (transfer full), but shell_app_system_lookup_wmclass()
is (transfer none), so we must reference the result, or crash
occur.

https://bugzilla.gnome.org/show_bug.cgi?id=678992
2012-06-27 19:27:30 +02:00
1a33cd9584 Updated Arabic translation 2012-06-27 12:49:54 +02:00
00279dbd04 theme: Center date label in calendar 2012-06-26 20:34:01 +02:00
eb759cf22f dateMenu: Fix regression that caused no date to be displayed
Commit ef0aa65774 broke the date
display; bring it back.
2012-06-26 14:00:35 -04:00
ae16da4e81 Fix wrong result handling of remote calls
When using dbus-glib, single return values were special-cased to
be returned verbatim rather than as array with a single element.
This is no longer true since switching to GDBus, so fix the places
where the change was overlooked.

https://bugzilla.gnome.org/show_bug.cgi?id=678852
2012-06-26 18:06:26 +02:00
965287e724 Updated Slovenian translation 2012-06-26 09:20:47 +02:00
84 changed files with 6385 additions and 6451 deletions

3
.gitignore vendored
View File

@ -50,6 +50,7 @@ po/gnome-shell.pot
po/*.header po/*.header
po/*.sed po/*.sed
po/*.sin po/*.sin
po/.intltool-merge-cache
po/Makefile.in.in po/Makefile.in.in
po/Makevars.template po/Makevars.template
po/POTFILES po/POTFILES
@ -62,6 +63,8 @@ src/*-enum-types.[ch]
src/*-marshal.[ch] src/*-marshal.[ch]
src/Makefile src/Makefile
src/Makefile.in src/Makefile.in
src/calendar-server/evolution-calendar.desktop
src/calendar-server/evolution-calendar.desktop.in
src/calendar-server/org.gnome.Shell.CalendarServer.service src/calendar-server/org.gnome.Shell.CalendarServer.service
src/gnome-shell src/gnome-shell
src/gnome-shell-calendar-server src/gnome-shell-calendar-server

57
NEWS
View File

@ -1,3 +1,60 @@
3.5.4
=====
* Fix wrong result handling of remote calls [Florian; #678852]
* dateMenu: Fix regression that caused no date to be displayed [Colin]
* WindowTracker: Fix refcounting bug in get_app_for_window() [Giovanni; #678992]
* Show the workspace switcher for move-to-workspace keybinding
[Giovanni, Jasper; #674104, #660839, #679005]
* userMenu: Move "Power off" item to the bottom [Florian; #678887]
* Remove contacts search provider [Florian, Rui; #677442]
* network: don't ask for always-ask secrets when interaction isn't allowed
[Dan; #679091]
* PolkitAgent: Look for the right password prompt [Matthias; #675300]
* Implement extension updates [Jasper; #679099]
* userMenu: Don't disconnect account signals when disabled [Guillaume; #669112]
* Fix startup notification when opening calendar [Florian; #677907]
* networkAgent: use absolute path if configured [Clemens; #679212]
* recorder: Port to GStreamer-1.0 API [Florian; #679445]
* telepathyClient: don't add log messages on presence changes [Ana; #669508]
* lookingGlass: Don't use a signal callback on 'paint' to draw the border
[Jasper; #679464]
* Add support for inhibiting automount [Hans; #678597]
* Implemented banner support for the login screen [Matthias, Marius; #665346]
* boxpointer: Flip side if we would end outside the monitor [Rui; #678164]
* boxpointer: Change 'animate' parameter on show/hide to a bitmask
[Rui; #678337]
* Add a grayscale effect [Matthias, Jasper, Florian: #676782, #674499]
* UserMenu: show "Install Updates & Restart" when appropriate
[Giovanni; #677394, #680080]
* messageTray: don't show the message tray when a new notification is shown
[Ana; #677210]
* panel: don't break when indicator has no menu [Jean-Philippe; #678694]
* appMenu: Disable app menu during startup animations [Florian; #672322]
* autorun: Add a notification when unmounting drives [Cosimo; #676125]
* st-icon: Fix potential crash involving shadows [Jasper; #679776]
* Remove manual garbage collection on tweeners end [Cosimo; #679832]
* dash: hide tooltips when overview begins hiding [Stefano; #674241]
* Update modal dialog animation for new centered position [Florian; #674499]
* calendar: Fix grid lines in RTL locales [Florian; #679879]
* Integrate IBus with keyboard indicator [Rui; #641531]
* Move ibus status icon under keyboard [Matthias]
* gdm: port from libgdmgreeter to libgdm [Ray; #676401]
* Misc bug fixes and cleanups [Antoine, Cosimo, Giovanni, Jasper, Rico;
#678978, #672790, #679847, #679944]
Contributors:
Jean-Philippe Braun, Clemens Buchacher, Giovanni Campagna, Cosimo Cecchi,
Matthias Clasen, Hans de Goede, Guillaume Desmottes, Stefano Facchini,
Antoine Jacoutot, Rui Matos, Florian Müllner, Marius Rieder, Ana Risteska,
Jasper St. Pierre, Rico Tzschichholz, Colin Walters, Dan Williams
Translations:
Matej Urbančič [sl], Khaled Hosny [ar], Nguyễn Thái Ngọc Duy [vi],
Nilamdyuti Goswami [as], Alexander Shopov [bg], Ivaylo Valkov [bg],
Daniel Mustieles [es], Kjartan Maraas [nb,nn], Yaron Shahrabani [he],
Nilamdyuti Goswami [as], Chao-Hsiung Liao [zh_HK, zh_TW], Ihar Hrachyshka [be],
Praveen Illa [te]
3.5.3 3.5.3
===== =====
* calendar: Adapt to Evolution-Data-Server API changes [Matthew; #677402] * calendar: Adapt to Evolution-Data-Server API changes [Matthew; #677402]

View File

@ -41,7 +41,7 @@
"It can be used only by extensions.gnome.org" "It can be used only by extensions.gnome.org"
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type"; #define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
#define PLUGIN_API_VERSION 4 #define PLUGIN_API_VERSION 5
typedef struct { typedef struct {
GDBusProxy *proxy; GDBusProxy *proxy;
@ -225,7 +225,7 @@ NPP_New(NPMIMEType mimetype,
NULL, /* interface info */ NULL, /* interface info */
"org.gnome.Shell", "org.gnome.Shell",
"/org/gnome/Shell", "/org/gnome/Shell",
"org.gnome.Shell", "org.gnome.Shell.Extensions",
NULL, /* GCancellable */ NULL, /* GCancellable */
&error); &error);
if (!data->proxy) if (!data->proxy)
@ -373,39 +373,14 @@ plugin_object_deallocate (NPObject *npobj)
g_slice_free (PluginObject, obj); g_slice_free (PluginObject, obj);
} }
static NPIdentifier api_version_id;
static NPIdentifier shell_version_id;
static NPIdentifier get_info_id;
static NPIdentifier list_extensions_id;
static NPIdentifier enable_extension_id;
static NPIdentifier install_extension_id;
static NPIdentifier uninstall_extension_id;
static NPIdentifier onextension_changed_id;
static NPIdentifier onrestart_id;
static NPIdentifier get_errors_id;
static NPIdentifier launch_extension_prefs_id;
static bool
plugin_object_has_method (NPObject *npobj,
NPIdentifier name)
{
return (name == get_info_id ||
name == list_extensions_id ||
name == enable_extension_id ||
name == install_extension_id ||
name == uninstall_extension_id ||
name == get_errors_id ||
name == launch_extension_prefs_id);
}
static inline gboolean static inline gboolean
uuid_is_valid (const gchar *uuid) uuid_is_valid (NPString string)
{ {
gsize i; gsize i;
for (i = 0; uuid[i]; i ++) for (i = 0; i < string.UTF8Length; i++)
{ {
gchar c = uuid[i]; gchar c = string.UTF8Characters[i];
if (c < 32 || c >= 127) if (c < 32 || c >= 127)
return FALSE; return FALSE;
@ -469,8 +444,73 @@ jsonify_variant (GVariant *variant,
} }
static gboolean static gboolean
plugin_list_extensions (PluginObject *obj, parse_args (const gchar *format_str,
NPVariant *result) uint32_t argc,
const NPVariant *argv,
...)
{
va_list args;
gsize i;
gboolean ret = FALSE;
if (strlen (format_str) != argc)
return FALSE;
va_start (args, argv);
for (i = 0; format_str[i]; i++)
{
gpointer arg_location;
const NPVariant arg = argv[i];
arg_location = va_arg (args, gpointer);
switch (format_str[i])
{
case 'u':
{
NPString string;
if (!NPVARIANT_IS_STRING (arg))
goto out;
string = NPVARIANT_TO_STRING (arg);
if (!uuid_is_valid (string))
goto out;
*(gchar **) arg_location = g_strndup (string.UTF8Characters, string.UTF8Length);
}
break;
case 'b':
if (!NPVARIANT_IS_BOOLEAN (arg))
goto out;
*(gboolean *) arg_location = NPVARIANT_TO_BOOLEAN (arg);
break;
case 'o':
if (!NPVARIANT_IS_OBJECT (arg))
goto out;
*(NPObject **) arg_location = NPVARIANT_TO_OBJECT (arg);
}
}
ret = TRUE;
out:
va_end (args);
return ret;
}
static gboolean
plugin_list_extensions (PluginObject *obj,
uint32_t argc,
const NPVariant *args,
NPVariant *result)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
@ -494,21 +534,20 @@ plugin_list_extensions (PluginObject *obj,
} }
static gboolean static gboolean
plugin_enable_extension (PluginObject *obj, plugin_enable_extension (PluginObject *obj,
NPString uuid, uint32_t argc,
gboolean enabled) const NPVariant *argv,
NPVariant *result)
{ {
gboolean ret; gboolean ret;
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); gchar *uuid;
gboolean enabled;
gsize length; gsize length;
gchar **uuids; gchar **uuids;
const gchar **new_uuids; const gchar **new_uuids;
if (!uuid_is_valid (uuid_str)) if (!parse_args ("ub", argc, argv, &uuid, &enabled))
{ return FALSE;
g_free (uuid_str);
return FALSE;
}
uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY); uuids = g_settings_get_strv (obj->settings, ENABLED_EXTENSIONS_KEY);
length = g_strv_length (uuids); length = g_strv_length (uuids);
@ -517,7 +556,7 @@ plugin_enable_extension (PluginObject *obj,
{ {
new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */ new_uuids = g_new (const gchar *, length + 2); /* New key, NULL */
memcpy (new_uuids, uuids, length * sizeof (*new_uuids)); memcpy (new_uuids, uuids, length * sizeof (*new_uuids));
new_uuids[length] = uuid_str; new_uuids[length] = uuid;
new_uuids[length + 1] = NULL; new_uuids[length + 1] = NULL;
} }
else else
@ -526,7 +565,7 @@ plugin_enable_extension (PluginObject *obj,
new_uuids = g_new (const gchar *, length); new_uuids = g_new (const gchar *, length);
for (i = 0; i < length; i ++) for (i = 0; i < length; i ++)
{ {
if (g_str_equal (uuids[i], uuid_str)) if (g_str_equal (uuids[i], uuid))
continue; continue;
new_uuids[j] = uuids[i]; new_uuids[j] = uuids[i];
@ -542,63 +581,112 @@ plugin_enable_extension (PluginObject *obj,
g_strfreev (uuids); g_strfreev (uuids);
g_free (new_uuids); g_free (new_uuids);
g_free (uuid_str); g_free (uuid);
return ret; return ret;
} }
static gboolean typedef struct _AsyncClosure AsyncClosure;
plugin_install_extension (PluginObject *obj,
NPString uuid)
{
gchar *uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length);
if (!uuid_is_valid (uuid_str)) struct _AsyncClosure {
PluginObject *obj;
NPObject *callback;
NPObject *errback;
};
static void
install_extension_cb (GObject *proxy,
GAsyncResult *async_res,
gpointer user_data)
{
AsyncClosure *async_closure = (AsyncClosure *) user_data;
GError *error = NULL;
GVariant *res;
NPVariant args[1];
NPVariant result = { NPVariantType_Void };
NPObject *callback;
res = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), async_res, &error);
if (res == NULL)
{ {
g_free (uuid_str); if (g_dbus_error_is_remote_error (error))
return FALSE; g_dbus_error_strip_remote_error (error);
STRINGZ_TO_NPVARIANT (error->message, args[0]);
callback = async_closure->errback;
} }
else
{
char *string_result;
g_variant_get (res, "(&s)", &string_result);
STRINGZ_TO_NPVARIANT (string_result, args[0]);
callback = async_closure->callback;
}
funcs.invokeDefault (async_closure->obj->instance,
callback, args, 1, &result);
funcs.releasevariantvalue (&result);
funcs.releaseobject (async_closure->callback);
funcs.releaseobject (async_closure->errback);
g_slice_free (AsyncClosure, async_closure);
}
static gboolean
plugin_install_extension (PluginObject *obj,
uint32_t argc,
const NPVariant *argv,
NPVariant *result)
{
gchar *uuid;
NPObject *callback, *errback;
AsyncClosure *async_closure;
if (!parse_args ("uoo", argc, argv, &uuid, &callback, &errback))
return FALSE;
async_closure = g_slice_new (AsyncClosure);
async_closure->obj = obj;
async_closure->callback = funcs.retainobject (callback);
async_closure->errback = funcs.retainobject (errback);
g_dbus_proxy_call (obj->proxy, g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension", "InstallRemoteExtension",
g_variant_new ("(s)", uuid_str), g_variant_new ("(s)", uuid),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
NULL, /* callback */ install_extension_cb,
NULL /* user_data */); async_closure);
g_free (uuid_str); g_free (uuid);
return TRUE; return TRUE;
} }
static gboolean static gboolean
plugin_uninstall_extension (PluginObject *obj, plugin_uninstall_extension (PluginObject *obj,
NPString uuid, uint32_t argc,
NPVariant *result) const NPVariant *argv,
NPVariant *result)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; gchar *uuid;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); if (!parse_args ("u", argc, argv, &uuid))
if (!uuid_is_valid (uuid_str)) return FALSE;
{
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"UninstallExtension", "UninstallExtension",
g_variant_new ("(s)", g_variant_new ("(s)", uuid),
uuid_str),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str); g_free (uuid);
if (!res) if (!res)
{ {
@ -611,30 +699,27 @@ plugin_uninstall_extension (PluginObject *obj,
} }
static gboolean static gboolean
plugin_get_info (PluginObject *obj, plugin_get_info (PluginObject *obj,
NPString uuid, uint32_t argc,
NPVariant *result) const NPVariant *argv,
NPVariant *result)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; gchar *uuid;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); if (!parse_args ("u", argc, argv, &uuid))
if (!uuid_is_valid (uuid_str)) return FALSE;
{
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionInfo", "GetExtensionInfo",
g_variant_new ("(s)", uuid_str), g_variant_new ("(s)", uuid),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str); g_free (uuid);
if (!res) if (!res)
{ {
@ -647,31 +732,26 @@ plugin_get_info (PluginObject *obj,
} }
static gboolean static gboolean
plugin_get_errors (PluginObject *obj, plugin_get_errors (PluginObject *obj,
NPString uuid, uint32_t argc,
NPVariant *result) const NPVariant *argv,
NPVariant *result)
{ {
GError *error = NULL; GError *error = NULL;
GVariant *res; GVariant *res;
gchar *uuid_str; gchar *uuid;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); if (!parse_args ("u", argc, argv, &uuid))
if (!uuid_is_valid (uuid_str)) return FALSE;
{
g_free (uuid_str);
return FALSE;
}
res = g_dbus_proxy_call_sync (obj->proxy, res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionErrors", "GetExtensionErrors",
g_variant_new ("(s)", uuid_str), g_variant_new ("(s)", uuid),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
&error); &error);
g_free (uuid_str);
if (!res) if (!res)
{ {
g_warning ("Failed to retrieve errors: %s", error->message); g_warning ("Failed to retrieve errors: %s", error->message);
@ -683,29 +763,25 @@ plugin_get_errors (PluginObject *obj,
} }
static gboolean static gboolean
plugin_launch_extension_prefs (PluginObject *obj, plugin_launch_extension_prefs (PluginObject *obj,
NPString uuid, uint32_t argc,
NPVariant *result) const NPVariant *argv,
NPVariant *result)
{ {
gchar *uuid_str; gchar *uuid;
uuid_str = g_strndup (uuid.UTF8Characters, uuid.UTF8Length); if (!parse_args ("u", argc, argv, &uuid))
if (!uuid_is_valid (uuid_str)) return FALSE;
{
g_free (uuid_str);
return FALSE;
}
g_dbus_proxy_call (obj->proxy, g_dbus_proxy_call (obj->proxy,
"LaunchExtensionPrefs", "LaunchExtensionPrefs",
g_variant_new ("(s)", uuid_str), g_variant_new ("(s)", uuid),
G_DBUS_CALL_FLAGS_NONE, G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */ -1, /* timeout */
NULL, /* cancellable */ NULL, /* cancellable */
NULL, /* callback */ NULL, /* callback */
NULL /* user_data */); NULL /* user_data */);
g_free (uuid_str);
return TRUE; return TRUE;
} }
@ -759,10 +835,40 @@ plugin_get_shell_version (PluginObject *obj,
return ret; return ret;
} }
#define METHODS \
METHOD (list_extensions) \
METHOD (get_info) \
METHOD (enable_extension) \
METHOD (install_extension) \
METHOD (uninstall_extension) \
METHOD (get_errors) \
METHOD (launch_extension_prefs) \
/* */
#define METHOD(x) \
static NPIdentifier x##_id;
METHODS
#undef METHOD
static NPIdentifier api_version_id;
static NPIdentifier shell_version_id;
static NPIdentifier onextension_changed_id;
static NPIdentifier onrestart_id;
static bool
plugin_object_has_method (NPObject *npobj,
NPIdentifier name)
{
#define METHOD(x) (name == (x##_id)) ||
/* expands to (name == list_extensions_id) || FALSE; */
return METHODS FALSE;
#undef METHOD
}
static bool static bool
plugin_object_invoke (NPObject *npobj, plugin_object_invoke (NPObject *npobj,
NPIdentifier name, NPIdentifier name,
const NPVariant *args, const NPVariant *argv,
uint32_t argc, uint32_t argc,
NPVariant *result) NPVariant *result)
{ {
@ -774,59 +880,13 @@ plugin_object_invoke (NPObject *npobj,
VOID_TO_NPVARIANT (*result); VOID_TO_NPVARIANT (*result);
if (!plugin_object_has_method (npobj, name)) #define METHOD(x) \
return FALSE; if (name == x##_id) \
return plugin_##x (obj, argc, argv, result);
METHODS
#undef METHOD
if (name == list_extensions_id) return FALSE;
return plugin_list_extensions (obj, result);
else if (name == get_info_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_get_info (obj, NPVARIANT_TO_STRING(args[0]), result);
}
else if (name == enable_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
if (!NPVARIANT_IS_BOOLEAN(args[1])) return FALSE;
return plugin_enable_extension (obj,
NPVARIANT_TO_STRING(args[0]),
NPVARIANT_TO_BOOLEAN(args[1]));
}
else if (name == install_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_install_extension (obj,
NPVARIANT_TO_STRING(args[0]));
}
else if (name == uninstall_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_uninstall_extension (obj,
NPVARIANT_TO_STRING(args[0]),
result);
}
else if (name == get_errors_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_get_errors (obj,
NPVARIANT_TO_STRING(args[0]),
result);
}
else if (name == launch_extension_prefs_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_launch_extension_prefs (obj,
NPVARIANT_TO_STRING(args[0]),
result);
}
return TRUE;
} }
static bool static bool

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.5.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.5.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
@ -44,15 +44,15 @@ AC_SUBST(PYTHON)
# We need at least this, since gst_plugin_register_static() was added # We need at least this, since gst_plugin_register_static() was added
# in 0.10.16, but nothing older than 0.10.21 has been tested. # in 0.10.16, but nothing older than 0.10.21 has been tested.
GSTREAMER_MIN_VERSION=0.10.16 GSTREAMER_MIN_VERSION=0.11.92
recorder_modules= recorder_modules=
build_recorder=false build_recorder=false
AC_MSG_CHECKING([for GStreamer (needed for recording functionality)]) AC_MSG_CHECKING([for GStreamer (needed for recording functionality)])
if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then if $PKG_CONFIG --exists gstreamer-1.0 '>=' $GSTREAMER_MIN_VERSION ; then
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
build_recorder=true build_recorder=true
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 x11" recorder_modules="gstreamer-1.0 gstreamer-base-1.0 x11"
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes gl) PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0 xfixes gl)
else else
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
@ -63,8 +63,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.9.16 CLUTTER_MIN_VERSION=1.9.16
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.33.2 GJS_MIN_VERSION=1.33.2
MUTTER_MIN_VERSION=3.5.3 MUTTER_MIN_VERSION=3.5.4
FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.3.9 GTK_MIN_VERSION=3.3.9
GIO_MIN_VERSION=2.31.6 GIO_MIN_VERSION=2.31.6
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
@ -78,27 +77,11 @@ GCR_MIN_VERSION=3.3.90
GNOME_DESKTOP_REQUIRED_VERSION=3.5.1 GNOME_DESKTOP_REQUIRED_VERSION=3.5.1
GNOME_MENUS_REQUIRED_VERSION=3.5.3 GNOME_MENUS_REQUIRED_VERSION=3.5.3
AC_ARG_WITH(folks,
AS_HELP_STRING([--with-folks],
[Enable folks support]),
[with_folks=$withval], [with_folks=yes])
if test x${with_folks} = xyes; then
FOLKS_REQUIREMENT="folks >= $FOLKS_MIN_VERSION"
AC_DEFINE([HAVE_FOLKS], [1], [folks support])
AC_SUBST([HAVE_FOLKS],[1])
else
FOLKS_REQUIREMENT=
AC_SUBST([HAVE_FOLKS],[0])
fi
AM_CONDITIONAL(BUILD_WITH_FOLKS, test x${with_folks} = xyes)
# Collect more than 20 libraries for a prize! # Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0 libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0 atk-bridge-2.0
$FOLKS_REQUIREMENT
libmutter >= $MUTTER_MIN_VERSION libmutter >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
@ -266,6 +249,7 @@ AC_CONFIG_FILES([
docs/reference/st/Makefile docs/reference/st/Makefile
docs/reference/st/st-docs.sgml docs/reference/st/st-docs.sgml
js/Makefile js/Makefile
src/calendar-server/evolution-calendar.desktop.in
src/Makefile src/Makefile
browser-plugin/Makefile browser-plugin/Makefile
tests/Makefile tests/Makefile

View File

@ -73,17 +73,11 @@ all-local: gschemas.compiled
convertdir = $(datadir)/GConf/gsettings convertdir = $(datadir)/GConf/gsettings
convert_DATA = gnome-shell-overrides.convert convert_DATA = gnome-shell-overrides.convert
shadersdir = $(pkgdatadir)/shaders
shaders_DATA = \
shaders/dim-window.glsl
EXTRA_DIST = \ EXTRA_DIST = \
gnome-shell.desktop.in.in \ gnome-shell.desktop.in.in \
gnome-shell-extension-prefs.desktop.in.in \ gnome-shell-extension-prefs.desktop.in.in \
$(introspection_DATA) \ $(introspection_DATA) \
$(menu_DATA) \ $(menu_DATA) \
$(shaders_DATA) \
$(convert_DATA) \ $(convert_DATA) \
org.gnome.shell.gschema.xml.in.in org.gnome.shell.gschema.xml.in.in

View File

@ -1,27 +0,0 @@
#version 110
uniform sampler2D tex;
uniform float fraction;
uniform float height;
const float c = -0.2;
const float border_max_height = 60.0;
mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
0.0, 1.0 + c, 0.0, 0.0,
0.0, 0.0, 1.0 + c, 0.0,
0.0, 0.0, 0.0, 1.0);
vec4 off = vec4(0.633, 0.633, 0.633, 0);
void main()
{
vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
float y = height * cogl_tex_coord_in[0].y;
// To reduce contrast, blend with a mid gray
cogl_color_out = color * contrast - off * c * color.a;
// We only fully dim at a distance of BORDER_MAX_HEIGHT from the top and
// when the fraction is 1.0. For other locations and fractions we linearly
// interpolate back to the original undimmed color, so the top of the window
// is at full color.
cogl_color_out = color + (cogl_color_out - color) * max(min(y / border_max_height, 1.0), 0.0);
cogl_color_out = color + (cogl_color_out - color) * fraction;
}

View File

@ -16,6 +16,14 @@
/* Login Dialog */ /* Login Dialog */
.login-dialog-banner {
font-size: 10pt;
font-weight: bold;
text-align: center;
color: #666666;
padding-bottom: 1em;
}
.login-dialog-title { .login-dialog-title {
font-size: 14pt; font-size: 14pt;
font-weight: bold; font-weight: bold;

View File

@ -803,58 +803,8 @@ StScrollBar StButton#vhandle:hover
transition-duration: 100; transition-duration: 100;
} }
/* Contacts */
.contact-grid {
spacing: 36px;
-shell-grid-horizontal-item-size: 272px; /* 2 * -shell-grid-horizontal-item-size + spacing */
-shell-grid-vertical-item-size: 118px;
}
.contact {
width: 272px; /* Same width as two normal results + spacing */
height: 118px; /* Aspect ratio = 1.75. Normal US business card ratio */
border-radius: 4px;
padding: 3px;
border: 1px rgba(0,0,0,0);
transition-duration: 100;
}
.contact-content {
border-radius: 7px;
padding: 8px;
width: 232px;
height: 84px;
background-color: rgba(0.0, 0.0, 0.0, 0.5);
color: white;
}
.contact-icon {
border-radius: 4px;
}
.contact-details {
padding: 0px 6px 22px 10px;
}
.contact-details-alias {
font-size: 18px;
padding-bottom: 8px;
}
.contact-details-status-icon {
padding-right: 4px;
}
.contact:hover {
background-color: rgba(255,255,255,0.1);
transition-duration: 100;
}
.contact:focus,
.app-well-app:focus > .overview-icon, .app-well-app:focus > .overview-icon,
.search-result-content:focus > .overview-icon, .search-result-content:focus > .overview-icon,
.contact:selected,
.app-well-app:selected > .overview-icon, .app-well-app:selected > .overview-icon,
.search-result-content:selected > .overview-icon { .search-result-content:selected > .overview-icon {
background-color: rgba(255,255,255,0.33); background-color: rgba(255,255,255,0.33);
@ -1066,6 +1016,7 @@ StScrollBar StButton#vhandle:hover
padding: .4em 1.75em; padding: .4em 1.75em;
color: #cccccc; color: #cccccc;
font-weight: bold; font-weight: bold;
text-align: center;
} }
.calendar-day-base { .calendar-day-base {
@ -1313,6 +1264,10 @@ StScrollBar StButton#vhandle:hover
padding: 8px; padding: 8px;
} }
.secondary-icon {
icon-size: 1.09em;
}
.hotplug-transient-box { .hotplug-transient-box {
spacing: 6px; spacing: 6px;
padding: 2px 72px 2px 12px; padding: 2px 72px 2px 12px;
@ -2051,3 +2006,17 @@ StScrollBar StButton#vhandle:hover
-arrow-rise: 10px; -arrow-rise: 10px;
-boxpointer-gap: 5px; -boxpointer-gap: 5px;
} }
/* IBus Candidate Popup */
.candidate-index {
padding: 0.5em 0.5em 0.5em 0.5em;
}
.candidate-label {
padding: 0.5em 0.5em 0.5em 0.5em;
}
.candidate-label:selected {
border-radius: 4px;
background-color: rgba(255,255,255,0.33);
}

View File

@ -68,6 +68,10 @@ IGNORE_HFILES= \
gactionobserver.h \ gactionobserver.h \
shell-recorder-src.h shell-recorder-src.h
if !BUILD_RECORDER
IGNORE_HFILES += shell-recorder.h
endif
# Images to copy into HTML directory. # Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES= HTML_IMAGES=

View File

@ -6,7 +6,6 @@ misc/config.js: misc/config.js.in Makefile
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \ [ -d $(@D) ] || $(mkdir_p) $(@D) ; \
sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \ sed -e "s|[@]PACKAGE_NAME@|$(PACKAGE_NAME)|g" \
-e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \ -e "s|[@]PACKAGE_VERSION@|$(PACKAGE_VERSION)|g" \
-e "s|[@]HAVE_FOLKS@|$(HAVE_FOLKS)|g" \
-e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \ -e "s|[@]HAVE_BLUETOOTH@|$(HAVE_BLUETOOTH)|g" \
-e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \ -e "s|[@]GETTEXT_PACKAGE@|$(GETTEXT_PACKAGE)|g" \
-e "s|[@]datadir@|$(datadir)|g" \ -e "s|[@]datadir@|$(datadir)|g" \
@ -43,7 +42,6 @@ nobase_dist_js_DATA = \
ui/boxpointer.js \ ui/boxpointer.js \
ui/calendar.js \ ui/calendar.js \
ui/checkBox.js \ ui/checkBox.js \
ui/contactDisplay.js \
ui/ctrlAltTab.js \ ui/ctrlAltTab.js \
ui/dash.js \ ui/dash.js \
ui/dateMenu.js \ ui/dateMenu.js \
@ -53,12 +51,12 @@ nobase_dist_js_DATA = \
ui/extensionSystem.js \ ui/extensionSystem.js \
ui/extensionDownloader.js \ ui/extensionDownloader.js \
ui/flashspot.js \ ui/flashspot.js \
ui/ibusCandidatePopup.js\
ui/iconGrid.js \ ui/iconGrid.js \
ui/keyboard.js \ ui/keyboard.js \
ui/keyringPrompt.js \ ui/keyringPrompt.js \
ui/layout.js \ ui/layout.js \
ui/lightbox.js \ ui/lightbox.js \
ui/link.js \
ui/lookingGlass.js \ ui/lookingGlass.js \
ui/magnifier.js \ ui/magnifier.js \
ui/magnifierDBus.js \ ui/magnifierDBus.js \

View File

@ -30,7 +30,7 @@ const Pango = imports.gi.Pango;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const GdmGreeter = imports.gi.GdmGreeter; const Gdm = imports.gi.Gdm;
const Batch = imports.gdm.batch; const Batch = imports.gdm.batch;
const Fprint = imports.gdm.fingerprint; const Fprint = imports.gdm.fingerprint;
@ -49,6 +49,8 @@ const _LOGO_ICON_NAME_SIZE = 48;
const _LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; const _LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
const _FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication'; const _FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
const _BANNER_MESSAGE_KEY = 'banner-message-enable';
const _BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
const _LOGO_KEY = 'logo'; const _LOGO_KEY = 'logo';
@ -701,7 +703,7 @@ const SessionList = new Lang.Class({
this._activeSessionId = null; this._activeSessionId = null;
this._items = {}; this._items = {};
let ids = GdmGreeter.get_session_ids(); let ids = Gdm.get_session_ids();
ids.sort(); ids.sort();
if (ids.length <= 1) { if (ids.length <= 1) {
@ -713,7 +715,7 @@ const SessionList = new Lang.Class({
} }
for (let i = 0; i < ids.length; i++) { for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription] = GdmGreeter.get_session_name_and_description(ids[i]); let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
let item = new SessionListItem(ids[i], sessionName); let item = new SessionListItem(ids[i], sessionName);
this._itemList.add_actor(item.actor, this._itemList.add_actor(item.actor,
@ -747,44 +749,38 @@ const LoginDialog = new Lang.Class({
Lang.bind(this, this._onOpened)); Lang.bind(this, this._onOpened));
this._userManager = AccountsService.UserManager.get_default() this._userManager = AccountsService.UserManager.get_default()
this._greeterClient = new GdmGreeter.Client(); this._greeterClient = new Gdm.Client();
this._greeterClient.open_connection(); this._greeter = this._greeterClient.get_greeter_sync(null);
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME); this._greeter.connect('default-session-name-changed',
Lang.bind(this, this._onDefaultSessionChanged));
this._greeterClient.connect('reset', this._greeter.connect('session-opened',
Lang.bind(this, this._onReset)); Lang.bind(this, this._onSessionOpened));
this._greeterClient.connect('default-session-changed', this._greeter.connect('timed-login-requested',
Lang.bind(this, this._onDefaultSessionChanged)); Lang.bind(this, this._onTimedLoginRequested));
this._greeterClient.connect('info',
Lang.bind(this, this._onInfo));
this._greeterClient.connect('problem',
Lang.bind(this, this._onProblem));
this._greeterClient.connect('info-query',
Lang.bind(this, this._onInfoQuery));
this._greeterClient.connect('secret-info-query',
Lang.bind(this, this._onSecretInfoQuery));
this._greeterClient.connect('session-opened',
Lang.bind(this, this._onSessionOpened));
this._greeterClient.connect('timed-login-requested',
Lang.bind(this, this._onTimedLoginRequested));
this._greeterClient.connect('authentication-failed',
Lang.bind(this, this._onAuthenticationFailed));
this._greeterClient.connect('conversation-stopped',
Lang.bind(this, this._onConversationStopped));
this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA }); this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA });
this._fprintManager = new Fprint.FprintManager(); this._fprintManager = new Fprint.FprintManager();
this._startFingerprintConversationIfNeeded(); this._checkForFingerprintReader();
this._settings.connect('changed::' + _LOGO_KEY, this._settings.connect('changed::' + _LOGO_KEY,
Lang.bind(this, this._updateLogo)); Lang.bind(this, this._updateLogo));
this._settings.connect('changed::' + _BANNER_MESSAGE_KEY,
Lang.bind(this, this._updateBanner));
this._settings.connect('changed::' + _BANNER_MESSAGE_TEXT_KEY,
Lang.bind(this, this._updateBanner));
this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' }); this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' });
this.contentLayout.add(this._logoBox); this.contentLayout.add(this._logoBox);
this._updateLogo(); this._updateLogo();
this._bannerLabel = new St.Label({ style_class: 'login-dialog-banner',
text: '' });
this.contentLayout.add(this._bannerLabel);
this._updateBanner();
this._titleLabel = new St.Label({ style_class: 'login-dialog-title', this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
text: C_("title", "Sign In") }); text: C_("title", "Sign In") });
@ -839,7 +835,7 @@ const LoginDialog = new Lang.Class({
this._sessionList = new SessionList(); this._sessionList = new SessionList();
this._sessionList.connect('session-activated', this._sessionList.connect('session-activated',
Lang.bind(this, function(list, sessionId) { Lang.bind(this, function(list, sessionId) {
this._greeterClient.call_select_session (sessionId); this._greeter.call_select_session_sync (sessionId, null);
})); }));
this._promptBox.add(this._sessionList.actor, this._promptBox.add(this._sessionList.actor,
@ -887,7 +883,7 @@ const LoginDialog = new Lang.Class({
}, },
_startFingerprintConversationIfNeeded: function() { _checkForFingerprintReader: function() {
this._haveFingerprintReader = false; this._haveFingerprintReader = false;
if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY)) if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
@ -897,9 +893,6 @@ const LoginDialog = new Lang.Class({
function(device, error) { function(device, error) {
if (!error && device) if (!error && device)
this._haveFingerprintReader = true; this._haveFingerprintReader = true;
if (this._haveFingerprintReader)
this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
})); }));
}, },
@ -917,9 +910,22 @@ const LoginDialog = new Lang.Class({
}, },
_updateBanner: function() {
let enabled = this._settings.get_boolean(_BANNER_MESSAGE_KEY);
let text = this._settings.get_string(_BANNER_MESSAGE_TEXT_KEY);
if (enabled && text) {
this._bannerLabel.set_text(text);
this._fadeInBanner();
} else {
this._fadeOutBanner();
}
},
_onReset: function(client, serviceName) { _onReset: function(client, serviceName) {
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME); this._userVerifier = null;
this._startFingerprintConversationIfNeeded();
this._checkForFingerprintReader();
let tasks = [this._hidePrompt, let tasks = [this._hidePrompt,
@ -977,7 +983,7 @@ const LoginDialog = new Lang.Class({
}, },
_onCancel: function(client) { _onCancel: function(client) {
this._greeterClient.call_cancel(); this._userVerifier.call_cancel_sync(null);
}, },
_fadeInPrompt: function() { _fadeInPrompt: function() {
@ -1084,7 +1090,7 @@ const LoginDialog = new Lang.Class({
let _text = this._promptEntry.get_text(); let _text = this._promptEntry.get_text();
this._promptEntry.reactive = false; this._promptEntry.reactive = false;
this._promptEntry.add_style_pseudo_class('insensitive'); this._promptEntry.add_style_pseudo_class('insensitive');
this._greeterClient.call_answer_query(serviceName, _text); this._userVerifier.call_answer_query_sync(serviceName, _text, null);
}]; }];
let batch = new Batch.ConsecutiveBatch(this, tasks); let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -1111,7 +1117,7 @@ const LoginDialog = new Lang.Class({
}, },
_onSessionOpened: function(client, serviceName) { _onSessionOpened: function(client, serviceName) {
this._greeterClient.call_start_session_when_ready(serviceName, true); this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
}, },
_waitForItemForUser: function(userName) { _waitForItemForUser: function(userName) {
@ -1193,7 +1199,7 @@ const LoginDialog = new Lang.Class({
function() { function() {
this._timedLoginBatch = null; this._timedLoginBatch = null;
this._greeterClient.call_begin_auto_login(userName); this._greeter.call_begin_auto_login_sync(userName, null);
}]; }];
this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks); this._timedLoginBatch = new Batch.ConsecutiveBatch(this, tasks);
@ -1236,16 +1242,12 @@ const LoginDialog = new Lang.Class({
})); }));
}, },
_onAuthenticationFailed: function(client) {
this._greeterClient.call_cancel();
},
_onConversationStopped: function(client, serviceName) { _onConversationStopped: function(client, serviceName) {
// if the password service fails, then cancel everything. // if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give // But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed // password authentication a chance to succeed
if (serviceName == _PASSWORD_SERVICE_NAME) { if (serviceName == _PASSWORD_SERVICE_NAME) {
this._greeterClient.call_cancel(); this._userVerifier.call_cancel_sync(null);
} else if (serviceName == _FINGERPRINT_SERVICE_NAME) { } else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
_fadeOutActor(this._promptFingerprintMessage); _fadeOutActor(this._promptFingerprintMessage);
} }
@ -1269,7 +1271,16 @@ const LoginDialog = new Lang.Class({
this._fadeOutLogo]), this._fadeOutLogo]),
function() { function() {
this._greeterClient.call_begin_verification(_PASSWORD_SERVICE_NAME); let hold = new Batch.Hold();
this._userVerifier.call_begin_verification(_PASSWORD_SERVICE_NAME,
null,
Lang.bind(this, function (userVerifier, result) {
this._userVerifier.call_begin_verification_finish (result);
hold.release();
}));
return hold;
}]; }];
let batch = new Batch.ConsecutiveBatch(this, tasks); let batch = new Batch.ConsecutiveBatch(this, tasks);
@ -1284,6 +1295,14 @@ const LoginDialog = new Lang.Class({
return _fadeOutActor(this._logoBox); return _fadeOutActor(this._logoBox);
}, },
_fadeInBanner: function() {
return _fadeInActor(this._bannerLabel);
},
_fadeOutBanner: function() {
return _fadeOutActor(this._bannerLabel);
},
_fadeInTitleLabel: function() { _fadeInTitleLabel: function() {
return _fadeInActor(this._titleLabel); return _fadeInActor(this._titleLabel);
}, },
@ -1300,7 +1319,101 @@ const LoginDialog = new Lang.Class({
return _fadeOutActor(this._notListedButton); return _fadeOutActor(this._notListedButton);
}, },
_getUserVerifier: function(userName) {
let hold = new Batch.Hold();
this._userVerifier = null;
// If possible, reauthenticate an already running session,
// so any session specific credentials get updated appropriately
this._greeterClient.open_reauthentication_channel(userName,
null,
Lang.bind(this, function(client, result) {
try {
this._userVerifier = this._greeterClient.open_reauthentication_channel_finish(result);
hold.release();
} catch (e) {
// If there's no session running, or it otherwise fails, then fall back
// to performing verification from this login session
this._greeterClient.get_user_verifier(null,
Lang.bind(this, function(client, result) {
this._userVerifier = this._greeterClient.get_user_verifier_finish(result);
hold.release();
}));
}
}));
hold.connect('release', Lang.bind(this, function() {
if (this._userVerifier) {
let ids = [];
let id;
id = this._userVerifier.connect('info',
Lang.bind(this, this._onInfo));
ids.push(id);
id = this._userVerifier.connect('problem',
Lang.bind(this, this._onProblem));
ids.push(id);
id = this._userVerifier.connect('info-query',
Lang.bind(this, this._onInfoQuery));
ids.push(id);
id = this._userVerifier.connect('secret-info-query',
Lang.bind(this, this._onSecretInfoQuery));
ids.push(id);
id = this._userVerifier.connect('conversation-stopped',
Lang.bind(this, this._onConversationStopped));
ids.push(id);
id = this._userVerifier.connect('reset',
Lang.bind(this, function() {
for (let i = 0; i < ids.length; i++)
this._userVerifier.disconnect(ids[i]);
this._onReset();
}));
ids.push(id);
}
}));
return hold;
},
_beginVerificationForUser: function(userName) {
let tasks = [function() {
let hold = new Batch.Hold();
this._userVerifier.call_begin_verification_for_user (_PASSWORD_SERVICE_NAME,
userName, null,
Lang.bind(this, function(userVerifier, result) {
this._userVerifier.call_begin_verification_for_user_finish (result);
hold.release();
}));
return hold;
},
function() {
let hold = new Batch.Hold();
if (this._haveFingerprintReader) {
this._userVerifier.call_begin_verification_for_user (_FINGERPRINT_SERVICE_NAME,
userName, null,
Lang.bind(this, function(userVerifier, result) {
this._userVerifier.call_begin_verification_for_user_finish (result);
hold.release();
}));
} else {
hold.release();
}
return hold;
}];
let batch = new Batch.ConsecutiveBatch(this, [this._getUserVerifier(userName),
new Batch.ConcurrentBatch(this, tasks)]);
return batch.run();
},
_onUserListActivated: function(activatedItem) { _onUserListActivated: function(activatedItem) {
let userName;
let tasks = [function() { let tasks = [function() {
this._userList.actor.reactive = false; this._userList.actor.reactive = false;
return this._userList.pinInPlace(); return this._userList.pinInPlace();
@ -1327,12 +1440,9 @@ const LoginDialog = new Lang.Class({
}, },
function() { function() {
let userName = activatedItem.user.get_user_name(); userName = activatedItem.user.get_user_name();
this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME,
userName);
if (this._haveFingerprintReader) return this._beginVerificationForUser(userName);
this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName);
}]; }];
this._user = activatedItem.user; this._user = activatedItem.user;

View File

@ -70,7 +70,7 @@ const PowerMenuButton = new Lang.Class({
this._systemdLoginManager.CanPowerOffRemote(Lang.bind(this, this._systemdLoginManager.CanPowerOffRemote(Lang.bind(this,
function(result, error) { function(result, error) {
if (!error) if (!error)
this._haveShutdown = result != 'no'; this._haveShutdown = result[0] != 'no';
else else
this._haveShutdown = false; this._haveShutdown = false;
@ -81,7 +81,7 @@ const PowerMenuButton = new Lang.Class({
this._consoleKitManager.CanStopRemote(Lang.bind(this, this._consoleKitManager.CanStopRemote(Lang.bind(this,
function(result, error) { function(result, error) {
if (!error) if (!error)
this._haveShutdown = result; this._haveShutdown = result[0];
else else
this._haveShutdown = false; this._haveShutdown = false;
@ -97,7 +97,7 @@ const PowerMenuButton = new Lang.Class({
this._systemdLoginManager.CanRebootRemote(Lang.bind(this, this._systemdLoginManager.CanRebootRemote(Lang.bind(this,
function(result, error) { function(result, error) {
if (!error) if (!error)
this._haveRestart = result != 'no'; this._haveRestart = result[0] != 'no';
else else
this._haveRestart = false; this._haveRestart = false;
@ -108,7 +108,7 @@ const PowerMenuButton = new Lang.Class({
this._consoleKitManager.CanRestartRemote(Lang.bind(this, this._consoleKitManager.CanRestartRemote(Lang.bind(this,
function(result, error) { function(result, error) {
if (!error) if (!error)
this._haveRestart = result; this._haveRestart = result[0];
else else
this._haveRestart = false; this._haveRestart = false;

View File

@ -6,8 +6,6 @@ const PACKAGE_NAME = '@PACKAGE_NAME@';
const PACKAGE_VERSION = '@PACKAGE_VERSION@'; const PACKAGE_VERSION = '@PACKAGE_VERSION@';
/* 1 if gnome-bluetooth is available, 0 otherwise */ /* 1 if gnome-bluetooth is available, 0 otherwise */
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@; const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
/* 1 if folks is available, 0 otherwise */
const HAVE_FOLKS = @HAVE_FOLKS@;
/* gettext package */ /* gettext package */
const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@'; const GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
/* locale dir */ /* locale dir */

View File

@ -177,7 +177,14 @@ const ExtensionFinder = new Lang.Class({
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path())); log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
continue; continue;
} }
let extension = createExtensionObject(uuid, extensionDir, type);
let extension;
try {
extension = createExtensionObject(uuid, extensionDir, type);
} catch(e) {
logError(e, 'Could not load extension %s'.format(uuid));
continue;
}
this.emit('extension-found', extension); this.emit('extension-found', extension);
} }
fileEnum.close(null); fileEnum.close(null);

View File

@ -28,7 +28,7 @@ function deleteGFile(file) {
return file['delete'](null); return file['delete'](null);
} }
function recursivelyDeleteDir(dir) { function recursivelyDeleteDir(dir, deleteParent) {
let children = dir.enumerate_children('standard::name,standard::type', let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null); Gio.FileQueryInfoFlags.NONE, null);
@ -39,8 +39,29 @@ function recursivelyDeleteDir(dir) {
if (type == Gio.FileType.REGULAR) if (type == Gio.FileType.REGULAR)
deleteGFile(child); deleteGFile(child);
else if (type == Gio.FileType.DIRECTORY) else if (type == Gio.FileType.DIRECTORY)
recursivelyDeleteDir(child); recursivelyDeleteDir(child, true);
} }
deleteGFile(dir); if (deleteParent)
deleteGFile(dir);
}
function recursivelyMoveDir(srcDir, destDir) {
let children = srcDir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
if (!destDir.query_exists(null))
destDir.make_directory_with_parents(null);
let info, child;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let srcChild = srcDir.get_child(info.get_name());
let destChild = destDir.get_child(info.get_name());
log([srcChild.get_path(), destChild.get_path()]);
if (type == Gio.FileType.REGULAR)
srcChild.move(destChild, Gio.FileCopyFlags.NONE, null, null);
else if (type == Gio.FileType.DIRECTORY)
recursivelyMoveDir(srcChild, destChild);
}
} }

View File

@ -50,9 +50,20 @@ const SessionManagerIface = <interface name="org.gnome.SessionManager">
<arg type="u" direction="in" /> <arg type="u" direction="in" />
</method> </method>
<method name="Shutdown" /> <method name="Shutdown" />
<method name="Reboot" />
<method name="CanShutdown"> <method name="CanShutdown">
<arg type="b" direction="out" /> <arg type="b" direction="out" />
</method> </method>
<method name="IsInhibited">
<arg type="u" direction="in" />
<arg type="b" direction="out" />
</method>
<signal name="InhibitorAdded">
<arg type="o" direction="out"/>
</signal>
<signal name="InhibitorRemoved">
<arg type="o" direction="out"/>
</signal>
</interface>; </interface>;
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface); var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);

View File

@ -1,5 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const System = imports.system;
const Main = imports.ui.main; const Main = imports.ui.main;
const Scripting = imports.ui.scripting; const Scripting = imports.ui.scripting;
@ -99,7 +101,7 @@ function run() {
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
global.gc(); System.gc();
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
Scripting.collectStatistics(); Scripting.collectStatistics();
Scripting.scriptEvent('afterShowHide'); Scripting.scriptEvent('afterShowHide');

View File

@ -10,6 +10,9 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const ShellMountOperation = imports.ui.shellMountOperation; const ShellMountOperation = imports.ui.shellMountOperation;
const ScreenSaver = imports.misc.screenSaver; const ScreenSaver = imports.misc.screenSaver;
const GnomeSession = imports.misc.gnomeSession;
const GNOME_SESSION_AUTOMOUNT_INHIBIT = 16;
// GSettings keys // GSettings keys
const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling'; const SETTINGS_SCHEMA = 'org.gnome.desktop.media-handling';
@ -79,6 +82,12 @@ const AutomountManager = new Lang.Class({
_init: function() { _init: function() {
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA }); this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = []; this._volumeQueue = [];
this._session = new GnomeSession.SessionManager();
this._session.connectSignal('InhibitorAdded',
Lang.bind(this, this._InhibitorsChanged));
this._session.connectSignal('InhibitorRemoved',
Lang.bind(this, this._InhibitorsChanged));
this._inhibited = false;
if (!haveSystemd()) if (!haveSystemd())
this.ckListener = new ConsoleKitManager(); this.ckListener = new ConsoleKitManager();
@ -108,6 +117,16 @@ const AutomountManager = new Lang.Class({
Mainloop.idle_add(Lang.bind(this, this._startupMountAll)); Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
}, },
_InhibitorsChanged: function(object, senderName, [inhibtor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
Lang.bind(this,
function(result, error) {
if (!error) {
this._inhibited = result[0];
}
}));
},
_screenSaverActiveChanged: function(object, senderName, [isActive]) { _screenSaverActiveChanged: function(object, senderName, [isActive]) {
if (!isActive) { if (!isActive) {
this._volumeQueue.forEach(Lang.bind(this, function(volume) { this._volumeQueue.forEach(Lang.bind(this, function(volume) {
@ -219,6 +238,9 @@ const AutomountManager = new Lang.Class({
} }
} }
if (this._inhibited)
return;
// Volume is already mounted, don't bother. // Volume is already mounted, don't bother.
if (volume.get_mount()) if (volume.get_mount())
return; return;

View File

@ -9,6 +9,13 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const PopupAnimation = {
NONE: 0,
SLIDE: 1 << 0,
FADE: 1 << 1,
FULL: ~0,
};
const POPUP_ANIMATION_TIME = 0.15; const POPUP_ANIMATION_TIME = 0.15;
/** /**
@ -18,7 +25,10 @@ const POPUP_ANIMATION_TIME = 0.15;
* *
* An actor which displays a triangle "arrow" pointing to a given * An actor which displays a triangle "arrow" pointing to a given
* side. The .bin property is a container in which content can be * side. The .bin property is a container in which content can be
* placed. The arrow position may be controlled via setArrowOrigin(). * placed. The arrow position may be controlled via
* setArrowOrigin(). The arrow side might be temporarily flipped
* depending on the box size and source position to keep the box
* totally inside the monitor if possible.
* *
*/ */
const BoxPointer = new Lang.Class({ const BoxPointer = new Lang.Class({
@ -26,6 +36,7 @@ const BoxPointer = new Lang.Class({
_init: function(arrowSide, binProperties) { _init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
this._userArrowSide = arrowSide;
this._arrowOrigin = 0; this._arrowOrigin = 0;
this.actor = new St.Bin({ x_fill: true, this.actor = new St.Bin({ x_fill: true,
y_fill: true }); y_fill: true });
@ -65,11 +76,16 @@ const BoxPointer = new Lang.Class({
show: function(animate, onComplete) { show: function(animate, onComplete) {
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate & PopupAnimation.FADE)
this.opacity = 0;
else
this.opacity = 255;
this.opacity = 0;
this.actor.show(); this.actor.show();
if (animate) { if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) { switch (this._arrowSide) {
case St.Side.TOP: case St.Side.TOP:
this.yOffset = -rise; this.yOffset = -rise;
@ -95,7 +111,7 @@ const BoxPointer = new Lang.Class({
if (onComplete) if (onComplete)
onComplete(); onComplete();
}), }),
time: POPUP_ANIMATION_TIME }); time: animationTime });
}, },
hide: function(animate, onComplete) { hide: function(animate, onComplete) {
@ -103,8 +119,10 @@ const BoxPointer = new Lang.Class({
let yOffset = 0; let yOffset = 0;
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
let rise = themeNode.get_length('-arrow-rise'); let rise = themeNode.get_length('-arrow-rise');
let fade = (animate & PopupAnimation.FADE);
let animationTime = (animate & PopupAnimation.FULL) ? POPUP_ANIMATION_TIME : 0;
if (animate) { if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) { switch (this._arrowSide) {
case St.Side.TOP: case St.Side.TOP:
yOffset = rise; yOffset = rise;
@ -123,13 +141,14 @@ const BoxPointer = new Lang.Class({
this._muteInput(); this._muteInput();
Tweener.addTween(this, { opacity: 0, Tweener.addTween(this, { opacity: fade ? 0 : 255,
xOffset: xOffset, xOffset: xOffset,
yOffset: yOffset, yOffset: yOffset,
transition: 'linear', transition: 'linear',
time: POPUP_ANIMATION_TIME, time: animationTime,
onComplete: Lang.bind(this, function () { onComplete: Lang.bind(this, function () {
this.actor.hide(); this.actor.hide();
this.opacity = 0;
this.xOffset = 0; this.xOffset = 0;
this.yOffset = 0; this.yOffset = 0;
if (onComplete) if (onComplete)
@ -199,8 +218,27 @@ const BoxPointer = new Lang.Class({
} }
this.bin.allocate(childBox, flags); this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) if (this._sourceActor && this._sourceActor.mapped) {
this._reposition(this._sourceActor, this._arrowAlignment); this._reposition(this._sourceActor, this._arrowAlignment);
if (this._shouldFlip()) {
switch (this._arrowSide) {
case St.Side.TOP:
this._arrowSide = St.Side.BOTTOM;
break;
case St.Side.BOTTOM:
this._arrowSide = St.Side.TOP;
break;
case St.Side.LEFT:
this._arrowSide = St.Side.RIGHT;
break;
case St.Side.RIGHT:
this._arrowSide = St.Side.LEFT;
break;
}
this._reposition(this._sourceActor, this._arrowAlignment);
}
}
}, },
_drawBorder: function(area) { _drawBorder: function(area) {
@ -327,6 +365,8 @@ const BoxPointer = new Lang.Class({
}, },
setPosition: function(sourceActor, alignment) { setPosition: function(sourceActor, alignment) {
this._arrowSide = this._userArrowSide;
// We need to show it now to force an allocation, // We need to show it now to force an allocation,
// so that we can query the correct size. // so that we can query the correct size.
this.actor.show(); this.actor.show();
@ -343,11 +383,7 @@ const BoxPointer = new Lang.Class({
if (!this._sourceActor) if (!this._sourceActor)
return; return;
// We need to show it now to force an allocation, this.setPosition(this._sourceActor, this._arrowAlignment);
// so that we can query the correct size.
this.actor.show();
this._reposition(this._sourceActor, this._arrowAlignment);
}, },
_reposition: function(sourceActor, alignment) { _reposition: function(sourceActor, alignment) {
@ -446,6 +482,39 @@ const BoxPointer = new Lang.Class({
-(this._yPosition + this._yOffset)); -(this._yPosition + this._yOffset));
}, },
_shouldFlip: function() {
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let boxAllocation = Shell.util_get_transformed_allocation(this.actor);
let boxWidth = boxAllocation.x2 - boxAllocation.x1;
let boxHeight = boxAllocation.y2 - boxAllocation.y1;
let monitor = Main.layoutManager.findMonitorForActor(this.actor);
switch (this._arrowSide) {
case St.Side.TOP:
if (boxAllocation.y2 > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - monitor.y)
return true;
break;
case St.Side.BOTTOM:
if (boxAllocation.y1 < monitor.y &&
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
return true;
break;
case St.Side.LEFT:
if (boxAllocation.x2 > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x)
return true;
break;
case St.Side.RIGHT:
if (boxAllocation.x1 < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return true;
break;
}
return false;
},
set xOffset(offset) { set xOffset(offset) {
this._xOffset = offset; this._xOffset = offset;
this._shiftActor(); this._shiftActor();

View File

@ -551,6 +551,7 @@ const Calendar = new Lang.Class({
let row = 2; let row = 2;
while (true) { while (true) {
let button = new St.Button({ label: iter.getDate().toString() }); let button = new St.Button({ label: iter.getDate().toString() });
let rtl = button.get_text_direction() == Clutter.TextDirection.RTL;
if (!this._eventSource) if (!this._eventSource)
button.reactive = false; button.reactive = false;
@ -571,7 +572,10 @@ const Calendar = new Lang.Class({
// Hack used in lieu of border-collapse - see gnome-shell.css // Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2) if (row == 2)
styleClass = 'calendar-day-top ' + styleClass; styleClass = 'calendar-day-top ' + styleClass;
if (iter.getDay() == this._weekStart)
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
if (leftMost)
styleClass = 'calendar-day-left ' + styleClass; styleClass = 'calendar-day-left ' + styleClass;
if (_sameDay(now, iter)) if (_sameDay(now, iter))

View File

@ -1,196 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Folks = imports.gi.Folks
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const Util = imports.misc.util;
const IconGrid = imports.ui.iconGrid;
const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const MAX_SEARCH_RESULTS_ROWS = 1;
const ICON_SIZE = 81;
function launchContact(id) {
Util.spawn(['gnome-contacts', '-i', id]);
}
/* This class represents a shown contact search result in the overview */
const Contact = new Lang.Class({
Name: 'Contact',
_init: function(id) {
this._contactSys = Shell.ContactSystem.get_default();
this.individual = this._contactSys.get_individual(id);
this.actor = new St.Bin({ style_class: 'contact',
reactive: true,
can_focus: true,
track_hover: true,
accessible_role: Atk.Role.PUSH_BUTTON });
let content = new St.BoxLayout( { style_class: 'contact-content',
vertical: false });
this.actor.set_child(content);
let icon = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
icon_size: ICON_SIZE,
style_class: 'contact-icon' });
if (this.individual.avatar != null)
icon.gicon = this.individual.avatar;
else
icon.icon_name = 'avatar-default';
content.add(icon, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let details = new St.BoxLayout({ style_class: 'contact-details',
vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let email = this._contactSys.get_email_for_display(this.individual);
let aliasText = this.individual.alias ||
this.individual.full_name ||
this.individual.nickname ||
email ||
C_("contact", "Unknown");
let aliasLabel = new St.Label({ text: aliasText,
style_class: 'contact-details-alias' });
details.add(aliasLabel, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.label_actor = aliasLabel;
let presence = this._createPresence(this.individual.presence_type);
details.add(presence, { x_fill: false,
y_fill: true,
x_align: St.Align.START,
y_align: St.Align.END });
},
_createPresence: function(presence) {
let text;
let iconName;
switch(presence) {
case Folks.PresenceType.AVAILABLE:
text = _("Available");
iconName = 'user-available';
break;
case Folks.PresenceType.AWAY:
case Folks.PresenceType.EXTENDED_AWAY:
text = _("Away");
iconName = 'user-away';
break;
case Folks.PresenceType.BUSY:
text = _("Busy");
iconName = 'user-busy';
break;
case Folks.PresenceType.OFFLINE:
text = _("Offline");
iconName = 'user-offline';
break;
default:
text = '';
iconName = null;
}
let box = new St.BoxLayout({ vertical: false,
style_class: 'contact-details-status' });
if (iconName) {
let icon = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.FULLCOLOR,
icon_size: 16,
style_class: 'contact-details-status-icon' });
box.add(icon, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
}
let label = new St.Label({ text: text });
box.add(label, { x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
return box;
},
createIcon: function(size) {
let tc = St.TextureCache.get_default();
let icon = this.individual.avatar;
if (icon != null) {
return tc.load_gicon(null, icon, size);
} else {
return tc.load_icon_name(null, 'avatar-default', St.IconType.FULLCOLOR, size);
}
},
});
/* Searches for and returns contacts */
const ContactSearchProvider = new Lang.Class({
Name: 'ContactSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
this.parent(_("CONTACTS"));
this._contactSys = Shell.ContactSystem.get_default();
},
getResultMetas: function(ids, callback) {
let metas = [];
for (let i = 0; i < ids.length; i++) {
let contact = new Contact(ids[i]);
metas.push({ 'id': ids[i],
'name': contact.alias,
'createIcon': function(size) {
return contact.createIcon(size);
}
});
}
callback(metas);
},
getInitialResultSet: function(terms) {
this.searchSystem.pushResults(this, this._contactSys.initial_search(terms));
},
getSubsearchResultSet: function(previousResults, terms) {
this.searchSystem.pushResults(this, this._contactSys.subsearch(previousResults, terms));
},
createResultActor: function(resultMeta, terms) {
let contact = new Contact(resultMeta.id);
return contact.actor;
},
createResultContainerActor: function() {
let grid = new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
grid.actor.style_class = 'contact-grid';
let actor = new SearchDisplay.GridSearchResults(this, grid);
return actor;
},
activateResult: function(id, params) {
launchContact(id);
}
});

View File

@ -133,7 +133,6 @@ const DashItemContainer = new Lang.Class({
}, },
hideLabel: function () { hideLabel: function () {
this.label.opacity = 255;
Tweener.addTween(this.label, Tweener.addTween(this.label,
{ opacity: 0, { opacity: 0,
time: DASH_ITEM_LABEL_HIDE_TIME, time: DASH_ITEM_LABEL_HIDE_TIME,
@ -459,6 +458,13 @@ const Dash = new Lang.Class({
Lang.bind(this, function() { Lang.bind(this, function() {
this._onHover(item, display) this._onHover(item, display)
})); }));
Main.overview.connect('hiding',
Lang.bind(this, function() {
this._labelShowing = false;
item.hideLabel();
}));
return item; return item;
}, },
@ -474,7 +480,7 @@ const Dash = new Lang.Class({
})); }));
if (this._resetHoverTimeoutId > 0) { if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId); Mainloop.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0; this._resetHoverTimeoutId = 0;
} }
} }
} else { } else {

View File

@ -155,15 +155,22 @@ const DateMenuButton = new Lang.Class({
_updateClockAndDate: function() { _updateClockAndDate: function() {
this._clockDisplay.set_text(this._clock.clock); this._clockDisplay.set_text(this._clock.clock);
/* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
*/
let dateFormat = _("%A %B %e, %Y");
let displayDate = new Date();
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
}, },
_onOpenCalendarActivate: function() { _onOpenCalendarActivate: function() {
this.menu.close(); this.menu.close();
let calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' }); let calendarSettings = new Gio.Settings({ schema: 'org.gnome.desktop.default-applications.office.calendar' });
let tool = calendarSettings.get_string('exec'); let tool = calendarSettings.get_string('exec');
if (tool.length == 0 || tool == 'evolution') { if (tool.length == 0 || tool.substr(0, 9) == 'evolution') {
// TODO: pass the selected day // TODO: pass the selected day
Util.spawn(['evolution', '-c', 'calendar']); let app = Shell.AppSystem.get_default().lookup_app('evolution-calendar.desktop');
app.activate();
} else { } else {
let needTerm = calendarSettings.get_boolean('needs-term'); let needTerm = calendarSettings.get_boolean('needs-term');
if (needTerm) { if (needTerm) {

View File

@ -7,6 +7,7 @@ const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Soup = imports.gi.Soup; const Soup = imports.gi.Soup;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Config = imports.misc.config; const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
@ -18,25 +19,39 @@ const _signals = ExtensionSystem._signals;
const REPOSITORY_URL_BASE = 'https://extensions.gnome.org'; const REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip'; const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
const REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/'; const REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
const REPOSITORY_URL_UPDATE = REPOSITORY_URL_BASE + '/update-info/';
let _httpSession; let _httpSession;
function installExtensionFromUUID(uuid) { function installExtension(uuid, invocation) {
let params = { uuid: uuid, let params = { uuid: uuid,
shell_version: Config.PACKAGE_VERSION }; shell_version: Config.PACKAGE_VERSION };
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params); let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
_httpSession.queue_message(message, _httpSession.queue_message(message, function(session, message) {
function(session, message) { if (message.status_code != Soup.KnownStatusCode.OK) {
let info = JSON.parse(message.response_body.data); ExtensionSystem.logExtensionError(uuid, 'downloading info: ' + message.status_code);
let dialog = new InstallExtensionDialog(uuid, info); invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
dialog.open(global.get_current_time()); return;
}); }
let info;
try {
info = JSON.parse(message.response_body.data);
} catch (e) {
ExtensionSystem.logExtensionError(uuid, 'parsing info: ' + e);
invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
return;
}
let dialog = new InstallExtensionDialog(uuid, info, invocation);
dialog.open(global.get_current_time());
});
} }
function uninstallExtensionFromUUID(uuid) { function uninstallExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid]; let extension = ExtensionUtils.extensions[uuid];
if (!extension) if (!extension)
return false; return false;
@ -48,22 +63,22 @@ function uninstallExtensionFromUUID(uuid) {
if (!ExtensionSystem.unloadExtension(uuid)) if (!ExtensionSystem.unloadExtension(uuid))
return false; return false;
FileUtils.recursivelyDeleteDir(extension.dir); FileUtils.recursivelyDeleteDir(extension.dir, true);
return true; return true;
} }
function gotExtensionZipFile(session, message, uuid) { function gotExtensionZipFile(session, message, uuid, dir, callback, errback) {
if (message.status_code != Soup.KnownStatusCode.OK) { if (message.status_code != Soup.KnownStatusCode.OK) {
logExtensionError(uuid, 'downloading extension: ' + message.status_code); errback('DownloadExtensionError', message.status_code);
return; return;
} }
let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
try { try {
if (!dir.query_exists(null)) if (!dir.query_exists(null))
dir.make_directory_with_parents(null); dir.make_directory_with_parents(null);
} catch (e) { } catch (e) {
logExtensionError('Could not create extension directory'); errback('CreateExtensionDirectoryError', e);
return;
} }
let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip'); let [file, stream] = Gio.File.new_tmp('XXXXXX.shell-extension.zip');
@ -77,21 +92,92 @@ function gotExtensionZipFile(session, message, uuid) {
null); null);
if (!success) { if (!success) {
logExtensionError(uuid, 'extract: could not extract'); errback('ExtractExtensionError');
return; return;
} }
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) { GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) {
GLib.spawn_close_pid(pid); GLib.spawn_close_pid(pid);
// Add extension to 'enabled-extensions' for the user, always... if (status != 0)
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY); errback('ExtractExtensionError');
if (enabledExtensions.indexOf(uuid) == -1) { else
enabledExtensions.push(uuid); callback();
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions); });
} }
ExtensionSystem.loadExtension(dir, ExtensionUtils.ExtensionType.PER_USER, true); function updateExtension(uuid) {
// This gets a bit tricky. We want the update to be seamless -
// if we have any error during downloading or extracting, we
// want to not unload the current version.
let oldExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension');
let newExtensionTmpDir = GLib.Dir.make_tmp('XXXXXX-shell-extension');
let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(uuid);
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, Lang.bind(this, function(session, message) {
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, function() {
let oldExtension = ExtensionUtils.extensions[uuid];
let extensionDir = oldExtension.dir;
if (!ExtensionSystem.unloadExtension(uuid))
return;
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
FileUtils.recursivelyMoveDir(newExtensionTmpDir, extensionDir);
let extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
try {
ExtensionSystem.loadExtension(extension);
} catch(e) {
ExtensionSystem.unloadExtension(uuid);
logError(e, 'Error loading extension %s'.format(uuid));
FileUtils.recursivelyDeleteDir(extensionDir, false);
FileUtils.recursivelyMoveDir(oldExtensionTmpDir, extensionDir);
// Restore what was there before. We can't do much if we
// fail here.
ExtensionSystem.loadExtension(oldExtension);
return;
}
FileUtils.recursivelyDeleteDir(oldExtensionTmpDir, true);
}, function(code, message) {
log('Error while updating extension %s: %s (%s)'.format(uuid, code, message ? message : ''));
});
}));
}
function checkForUpdates() {
let metadatas = {};
for (let uuid in ExtensionUtils.extensions) {
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
}
let params = { shell_version: Config.PACKAGE_VERSION,
installed: JSON.stringify(metadatas) };
let url = REPOSITORY_URL_UPDATE;
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, function(session, message) {
if (message.status_code != Soup.KnownStatusCode.OK)
return;
let operations = JSON.parse(message.response_body.data);
for (let uuid in operations) {
let operation = operations[uuid];
if (operation == 'blacklist')
uninstallExtension(uuid);
else if (operation == 'upgrade' || operation == 'downgrade')
updateExtension(uuid);
}
}); });
} }
@ -99,11 +185,12 @@ const InstallExtensionDialog = new Lang.Class({
Name: 'InstallExtensionDialog', Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog, Extends: ModalDialog.ModalDialog,
_init: function(uuid, info) { _init: function(uuid, info, invocation) {
this.parent({ styleClass: 'extension-dialog' }); this.parent({ styleClass: 'extension-dialog' });
this._uuid = uuid; this._uuid = uuid;
this._info = info; this._info = info;
this._invocation = invocation;
this.setButtons([{ label: _("Cancel"), this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this._onCancelButtonPressed), action: Lang.bind(this, this._onCancelButtonPressed),
@ -128,34 +215,46 @@ const InstallExtensionDialog = new Lang.Class({
_onCancelButtonPressed: function(button, event) { _onCancelButtonPressed: function(button, event) {
this.close(global.get_current_time()); this.close(global.get_current_time());
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
// Even though the extension is already "uninstalled", send through
// a state-changed signal for any users who want to know if the install
// went through correctly -- using proper async DBus would block more
// traditional clients like the plugin
let meta = { uuid: this._uuid,
state: ExtensionSystem.ExtensionState.UNINSTALLED,
error: '' };
_signals.emit('extension-state-changed', meta);
}, },
_onInstallButtonPressed: function(button, event) { _onInstallButtonPressed: function(button, event) {
let state = { uuid: this._uuid,
state: ExtensionSystem.ExtensionState.DOWNLOADING,
error: '' };
_signals.emit('extension-state-changed', state);
let params = { shell_version: Config.PACKAGE_VERSION }; let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid); let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
let message = Soup.form_request_new_from_hash('GET', url, params); let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message, let uuid = this._uuid;
Lang.bind(this, function(session, message) { let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
gotExtensionZipFile(session, message, this._uuid); let invocation = this._invocation;
})); function errback(code, message) {
invocation.return_dbus_error('org.gnome.Shell.' + code, message ? message.toString() : '');
}
function callback() {
// Add extension to 'enabled-extensions' for the user, always...
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
if (enabledExtensions.indexOf(uuid) == -1) {
enabledExtensions.push(uuid);
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
try {
ExtensionSystem.loadExtension(extension);
} catch(e) {
uninstallExtension(uuid);
errback('LoadExtensionError', e);
return;
}
invocation.return_value(GLib.Variant.new('(s)', 'successful'));
}
_httpSession.queue_message(message, Lang.bind(this, function(session, message) {
gotExtensionZipFile(session, message, uuid, dir, callback, errback);
}));
this.close(global.get_current_time()); this.close(global.get_current_time());
} }

View File

@ -63,7 +63,7 @@ function disableExtension(uuid) {
try { try {
ExtensionUtils.extensions[uuid].stateObj.disable(); ExtensionUtils.extensions[uuid].stateObj.disable();
} catch(e) { } catch(e) {
logExtensionError(uuid, e.toString()); logExtensionError(uuid, e);
} }
} }
@ -72,19 +72,14 @@ function disableExtension(uuid) {
theme.unload_stylesheet(extension.stylesheet.get_path()); theme.unload_stylesheet(extension.stylesheet.get_path());
} }
try { extension.stateObj.disable();
extension.stateObj.disable();
} catch(e) {
logExtensionError(uuid, e.toString());
return;
}
for (let i = 0; i < order.length; i++) { for (let i = 0; i < order.length; i++) {
let uuid = order[i]; let uuid = order[i];
try { try {
ExtensionUtils.extensions[uuid].stateObj.enable(); ExtensionUtils.extensions[uuid].stateObj.enable();
} catch(e) { } catch(e) {
logExtensionError(uuid, e.toString()); logExtensionError(uuid, e);
} }
} }
@ -107,42 +102,38 @@ function enableExtension(uuid) {
extensionOrder.push(uuid); extensionOrder.push(uuid);
try { extension.stateObj.enable();
extension.stateObj.enable();
} catch(e) {
logExtensionError(uuid, e.toString());
return;
}
let stylesheetFile = extension.dir.get_child('stylesheet.css'); let stylesheetFile = extension.dir.get_child('stylesheet.css');
if (stylesheetFile.query_exists(null)) { if (stylesheetFile.query_exists(null)) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
try { theme.load_stylesheet(stylesheetFile.get_path());
theme.load_stylesheet(stylesheetFile.get_path()); extension.stylesheet = stylesheetFile;
extension.stylesheet = stylesheetFile;
} catch (e) {
logExtensionError(uuid, 'Stylesheet parse error: ' + e);
}
} }
extension.state = ExtensionState.ENABLED; extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension); _signals.emit('extension-state-changed', extension);
} }
function logExtensionError(uuid, message, state) { function logExtensionError(uuid, error) {
let extension = ExtensionUtils.extensions[uuid]; let extension = ExtensionUtils.extensions[uuid];
if (!extension) if (!extension)
return; return;
let message = '' + error;
if (error.state)
extension.state = error.state;
else
extension.state = ExtensionState.ERROR;
if (!extension.errors) if (!extension.errors)
extension.errors = []; extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message)); log('Extension "%s" had error: %s'.format(uuid, message));
state = state || ExtensionState.ERROR;
_signals.emit('extension-state-changed', { uuid: uuid, _signals.emit('extension-state-changed', { uuid: uuid,
error: message, error: message,
state: state }); state: extension.state });
} }
function loadExtension(extension) { function loadExtension(extension) {
@ -150,9 +141,9 @@ function loadExtension(extension) {
extension.state = ExtensionState.ERROR; extension.state = ExtensionState.ERROR;
if (ExtensionUtils.isOutOfDate(extension)) { if (ExtensionUtils.isOutOfDate(extension)) {
logExtensionError(extension.uuid, 'extension is not compatible with current GNOME Shell and/or GJS version', ExtensionState.OUT_OF_DATE); let error = new Error('extension is not compatible with current GNOME Shell and/or GJS version');
extension.state = ExtensionState.OUT_OF_DATE; error.state = ExtensionState.OUT_OF_DATE;
return; throw error;
} }
let enabled = enabledExtensions.indexOf(extension.uuid) != -1; let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
@ -192,45 +183,24 @@ function initExtension(uuid) {
throw new Error("Extension was not properly created. Call loadExtension first"); throw new Error("Extension was not properly created. Call loadExtension first");
let extensionJs = dir.get_child('extension.js'); let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) { if (!extensionJs.query_exists(null))
logExtensionError(uuid, 'Missing extension.js'); throw new Error('Missing extension.js');
return;
}
let extensionModule; let extensionModule;
let extensionState = null; let extensionState = null;
try {
ExtensionUtils.installImporter(extension); ExtensionUtils.installImporter(extension);
extensionModule = extension.imports.extension; extensionModule = extension.imports.extension;
} catch (e) {
logExtensionError(uuid, '' + e);
return;
}
if (extensionModule.init) { if (extensionModule.init) {
try { extensionState = extensionModule.init(extension);
extensionState = extensionModule.init(extension);
} catch (e) {
logExtensionError(uuid, 'Failed to evaluate init function:' + e);
return;
}
} }
if (!extensionState) if (!extensionState)
extensionState = extensionModule; extensionState = extensionModule;
extension.stateObj = extensionState; extension.stateObj = extensionState;
if (!extensionState.enable) {
logExtensionError(uuid, 'missing \'enable\' function');
return;
}
if (!extensionState.disable) {
logExtensionError(uuid, 'missing \'disable\' function');
return;
}
extension.state = ExtensionState.DISABLED; extension.state = ExtensionState.DISABLED;
_signals.emit('extension-loaded', uuid); _signals.emit('extension-loaded', uuid);
} }
@ -242,7 +212,11 @@ function onEnabledExtensionsChanged() {
newEnabledExtensions.filter(function(uuid) { newEnabledExtensions.filter(function(uuid) {
return enabledExtensions.indexOf(uuid) == -1; return enabledExtensions.indexOf(uuid) == -1;
}).forEach(function(uuid) { }).forEach(function(uuid) {
enableExtension(uuid); try {
enableExtension(uuid);
} catch(e) {
logExtensionError(uuid, e);
}
}); });
// Find and disable all the newly disabled extensions: UUIDs found in the // Find and disable all the newly disabled extensions: UUIDs found in the
@ -250,7 +224,11 @@ function onEnabledExtensionsChanged() {
enabledExtensions.filter(function(item) { enabledExtensions.filter(function(item) {
return newEnabledExtensions.indexOf(item) == -1; return newEnabledExtensions.indexOf(item) == -1;
}).forEach(function(uuid) { }).forEach(function(uuid) {
disableExtension(uuid); try {
disableExtension(uuid);
} catch(e) {
logExtensionError(uuid, e);
}
}); });
enabledExtensions = newEnabledExtensions; enabledExtensions = newEnabledExtensions;
@ -262,7 +240,11 @@ function loadExtensions() {
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', function(signals, extension) { finder.connect('extension-found', function(signals, extension) {
loadExtension(extension); try {
loadExtension(extension);
} catch(e) {
logExtensionError(extension.uuid, e);
}
}); });
finder.scanExtensions(); finder.scanExtensions();
} }

228
js/ui/ibusCandidatePopup.js Normal file
View File

@ -0,0 +1,228 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const IBus = imports.gi.IBus;
const Lang = imports.lang;
const St = imports.gi.St;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
const MAX_CANDIDATES_PER_PAGE = 16;
const CandidateArea = new Lang.Class({
Name: 'CandidateArea',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function() {
this.parent({ reactive: false });
// St.Table exhibits some sizing problems so let's go with a
// clutter layout manager for now.
this._table = new Clutter.Actor();
this.addActor(this._table);
this._tableLayout = new Clutter.TableLayout();
this._table.set_layout_manager(this._tableLayout);
this._indexLabels = [];
this._candidateLabels = [];
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
this._indexLabels.push(new St.Label({ style_class: 'candidate-index' }));
this._candidateLabels.push(new St.Label({ style_class: 'candidate-label' }));
}
this._orientation = -1;
this._cursorPosition = 0;
},
_setOrientation: function(orientation) {
if (this._orientation == orientation)
return;
this._orientation = orientation;
this._table.remove_all_children();
if (this._orientation == IBus.Orientation.HORIZONTAL)
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
this._tableLayout.pack(this._indexLabels[i], i*2, 0);
this._tableLayout.pack(this._candidateLabels[i], i*2 + 1, 0);
}
else // VERTICAL || SYSTEM
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
this._tableLayout.pack(this._indexLabels[i], 0, i);
this._tableLayout.pack(this._candidateLabels[i], 1, i);
}
},
setCandidates: function(indexes, candidates, orientation, cursorPosition, cursorVisible) {
this._setOrientation(orientation);
for (let i = 0; i < MAX_CANDIDATES_PER_PAGE; ++i) {
let visible = i < candidates.length;
this._indexLabels[i].visible = visible;
this._candidateLabels[i].visible = visible;
if (!visible)
continue;
this._indexLabels[i].text = ((indexes && indexes[i]) ? indexes[i] : '%x.'.format(i + 1));
this._candidateLabels[i].text = candidates[i];
}
this._candidateLabels[this._cursorPosition].remove_style_pseudo_class('selected');
this._cursorPosition = cursorPosition;
if (cursorVisible)
this._candidateLabels[cursorPosition].add_style_pseudo_class('selected');
},
});
const CandidatePopup = new Lang.Class({
Name: 'CandidatePopup',
Extends: PopupMenu.PopupMenu,
_init: function() {
this._cursor = new St.Bin({ opacity: 0 });
Main.uiGroup.add_actor(this._cursor);
this.parent(this._cursor, 0, St.Side.TOP);
this.actor.hide();
Main.uiGroup.add_actor(this.actor);
this._preeditTextItem = new PopupMenu.PopupMenuItem('', { reactive: false });
this._preeditTextItem.actor.hide();
this.addMenuItem(this._preeditTextItem);
this._auxTextItem = new PopupMenu.PopupMenuItem('', { reactive: false });
this._auxTextItem.actor.hide();
this.addMenuItem(this._auxTextItem);
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._lookupTableItem = new CandidateArea();
this._lookupTableItem.actor.hide();
this.addMenuItem(this._lookupTableItem);
this._panelService = null;
},
setPanelService: function(panelService) {
this._panelService = panelService;
if (!panelService)
return;
panelService.connect('set-cursor-location',
Lang.bind(this, function(ps, x, y, w, h) {
this._cursor.set_position(x, y);
this._cursor.set_size(w, h);
}));
panelService.connect('update-preedit-text',
Lang.bind(this, function(ps, text, cursorPosition, visible) {
if (visible)
this._preeditTextItem.actor.show();
else
this._preeditTextItem.actor.hide();
this._updateVisibility();
this._preeditTextItem.actor.label_actor.text = text.get_text();
let attrs = text.get_attributes();
if (attrs)
this._setTextAttributes(this._preeditTextItem.actor.label_actor.clutter_text,
attrs);
}));
panelService.connect('show-preedit-text',
Lang.bind(this, function(ps) {
this._preeditTextItem.actor.show();
this._updateVisibility();
}));
panelService.connect('hide-preedit-text',
Lang.bind(this, function(ps) {
this._preeditTextItem.actor.hide();
this._updateVisibility();
}));
panelService.connect('update-auxiliary-text',
Lang.bind(this, function(ps, text, visible) {
if (visible)
this._auxTextItem.actor.show();
else
this._auxTextItem.actor.hide();
this._updateVisibility();
this._auxTextItem.actor.label_actor.text = text.get_text();
}));
panelService.connect('show-auxiliary-text',
Lang.bind(this, function(ps) {
this._auxTextItem.actor.show();
this._updateVisibility();
}));
panelService.connect('hide-auxiliary-text',
Lang.bind(this, function(ps) {
this._auxTextItem.actor.hide();
this._updateVisibility();
}));
panelService.connect('update-lookup-table',
Lang.bind(this, function(ps, lookupTable, visible) {
if (visible)
this._lookupTableItem.actor.show();
else
this._lookupTableItem.actor.hide();
this._updateVisibility();
let cursorPos = lookupTable.get_cursor_pos();
let pageSize = lookupTable.get_page_size();
let page = ((cursorPos == 0) ? 0 : Math.floor(cursorPos / pageSize));
let startIndex = page * pageSize;
let endIndex = Math.min((page + 1) * pageSize,
lookupTable.get_number_of_candidates());
let indexes = [];
let indexLabel;
for (let i = 0; indexLabel = lookupTable.get_label(i); ++i)
indexes.push(indexLabel.get_text());
let candidates = [];
for (let i = startIndex; i < endIndex; ++i)
candidates.push(lookupTable.get_candidate(i).get_text());
this._lookupTableItem.setCandidates(indexes,
candidates,
lookupTable.get_orientation(),
cursorPos % pageSize,
lookupTable.is_cursor_visible());
}));
panelService.connect('show-lookup-table',
Lang.bind(this, function(ps) {
this._lookupTableItem.actor.show();
this._updateVisibility();
}));
panelService.connect('hide-lookup-table',
Lang.bind(this, function(ps) {
this._lookupTableItem.actor.hide();
this._updateVisibility();
}));
panelService.connect('focus-out',
Lang.bind(this, function(ps) {
this.close(BoxPointer.PopupAnimation.NONE);
}));
},
_updateVisibility: function() {
let isVisible = (this._preeditTextItem.actor.visible ||
this._auxTextItem.actor.visible ||
this._lookupTableItem.actor.visible);
if (isVisible)
this.open(BoxPointer.PopupAnimation.NONE);
else
this.close(BoxPointer.PopupAnimation.NONE);
},
_setTextAttributes: function(clutterText, ibusAttrList) {
let attr;
for (let i = 0; attr = ibusAttrList.get(i); ++i)
if (attr.get_attr_type() == IBus.AttrType.BACKGROUND)
clutterText.set_selection(attr.get_start_index(), attr.get_end_index());
}
});

View File

@ -175,7 +175,7 @@ const Key = new Lang.Class({
this.actor.fake_release(); this.actor.fake_release();
this._boxPointer.actor.raise_top(); this._boxPointer.actor.raise_top();
this._boxPointer.setPosition(this.actor, 0.5); this._boxPointer.setPosition(this.actor, 0.5);
this._boxPointer.show(true); this._boxPointer.show(BoxPointer.PopupAnimation.FULL);
this.actor.set_hover(false); this.actor.set_hover(false);
if (!this._grabbed) { if (!this._grabbed) {
Main.pushModal(this.actor); Main.pushModal(this.actor);
@ -186,7 +186,7 @@ const Key = new Lang.Class({
} else { } else {
if (this._grabbed) if (this._grabbed)
this._ungrab(); this._ungrab();
this._boxPointer.hide(true); this._boxPointer.hide(BoxPointer.PopupAnimation.FULL);
} }
} }
}); });

View File

@ -1,21 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
const Link = new Lang.Class({
Name: 'Link',
_init : function(props) {
let realProps = { reactive: true,
track_hover: true,
style_class: 'shell-link' };
// The user can pass in reactive: false to override the above and get
// a non-reactive link (a link to the current page, perhaps)
Lang.copyProperties(props, realProps);
this.actor = new St.Button(realProps);
}
});
Signals.addSignalMethods(Link.prototype);

View File

@ -12,16 +12,18 @@ const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const System = imports.system;
const History = imports.misc.history; const History = imports.misc.history;
const ExtensionSystem = imports.ui.extensionSystem; const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const Link = imports.ui.link;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Main = imports.ui.main; const Main = imports.ui.main;
const JsParse = imports.misc.jsParse; const JsParse = imports.misc.jsParse;
const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */ /* Imports...feel free to add here as needed */
var commandHeader = 'const Clutter = imports.gi.Clutter; ' + var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
'const GLib = imports.gi.GLib; ' + 'const GLib = imports.gi.GLib; ' +
@ -261,9 +263,8 @@ function objectToString(o) {
const ObjLink = new Lang.Class({ const ObjLink = new Lang.Class({
Name: 'ObjLink', Name: 'ObjLink',
Extends: Link.Link,
_init: function(o, title) { _init: function(lookingGlass, o, title) {
let text; let text;
if (title) if (title)
text = title; text = title;
@ -272,24 +273,30 @@ const ObjLink = new Lang.Class({
text = GLib.markup_escape_text(text, -1); text = GLib.markup_escape_text(text, -1);
this._obj = o; this._obj = o;
this.parent({ label: text }); this.actor = new St.Button({ reactive: true,
track_hover: true,
style_class: 'shell-link',
label: text });
this.actor.get_child().single_line_mode = true; this.actor.get_child().single_line_mode = true;
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this._lookingGlass = lookingGlass;
}, },
_onClicked: function (link) { _onClicked: function (link) {
Main.lookingGlass.inspectObject(this._obj, this.actor); this._lookingGlass.inspectObject(this._obj, this.actor);
} }
}); });
const Result = new Lang.Class({ const Result = new Lang.Class({
Name: 'Result', Name: 'Result',
_init : function(command, o, index) { _init: function(lookingGlass, command, o, index) {
this.index = index; this.index = index;
this.o = o; this.o = o;
this.actor = new St.BoxLayout({ vertical: true }); this.actor = new St.BoxLayout({ vertical: true });
this._lookingGlass = lookingGlass;
let cmdTxt = new St.Label({ text: command }); let cmdTxt = new St.Label({ text: command });
cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END; cmdTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
@ -299,7 +306,7 @@ const Result = new Lang.Class({
let resultTxt = new St.Label({ text: 'r(' + index + ') = ' }); let resultTxt = new St.Label({ text: 'r(' + index + ') = ' });
resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END; resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
box.add(resultTxt); box.add(resultTxt);
let objLink = new ObjLink(o); let objLink = new ObjLink(this._lookingGlass, o);
box.add(objLink.actor); box.add(objLink.actor);
let line = new Clutter.Rectangle({ name: 'Separator' }); let line = new Clutter.Rectangle({ name: 'Separator' });
let padBin = new St.Bin({ name: 'Separator', x_fill: true, y_fill: true }); let padBin = new St.Bin({ name: 'Separator', x_fill: true, y_fill: true });
@ -311,12 +318,14 @@ const Result = new Lang.Class({
const WindowList = new Lang.Class({ const WindowList = new Lang.Class({
Name: 'WindowList', Name: 'WindowList',
_init : function () { _init: function(lookingGlass) {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' }); this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
this._updateId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._updateWindowList)); this._updateId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._updateWindowList));
global.display.connect('window-created', Lang.bind(this, this._updateWindowList)); global.display.connect('window-created', Lang.bind(this, this._updateWindowList));
tracker.connect('tracked-windows-changed', Lang.bind(this, this._updateWindowList)); tracker.connect('tracked-windows-changed', Lang.bind(this, this._updateWindowList));
this._lookingGlass = lookingGlass;
}, },
_updateWindowList: function() { _updateWindowList: function() {
@ -332,7 +341,7 @@ const WindowList = new Lang.Class({
} }
let box = new St.BoxLayout({ vertical: true }); let box = new St.BoxLayout({ vertical: true });
this.actor.add(box); this.actor.add(box);
let windowLink = new ObjLink(metaWindow, metaWindow.title); let windowLink = new ObjLink(this._lookingGlass, metaWindow, metaWindow.title);
box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false }); box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false });
let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' }); let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
box.add(propsBox); box.add(propsBox);
@ -343,7 +352,7 @@ const WindowList = new Lang.Class({
let propBox = new St.BoxLayout({ style: 'spacing: 6px; ' }); let propBox = new St.BoxLayout({ style: 'spacing: 6px; ' });
propsBox.add(propBox); propsBox.add(propBox);
propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false }); propBox.add(new St.Label({ text: 'app: ' }), { y_fill: false });
let appLink = new ObjLink(app, app.get_id()); let appLink = new ObjLink(this._lookingGlass, app, app.get_id());
propBox.add(appLink.actor, { y_fill: false }); propBox.add(appLink.actor, { y_fill: false });
propBox.add(icon, { y_fill: false }); propBox.add(icon, { y_fill: false });
} else { } else {
@ -357,7 +366,7 @@ Signals.addSignalMethods(WindowList.prototype);
const ObjInspector = new Lang.Class({ const ObjInspector = new Lang.Class({
Name: 'ObjInspector', Name: 'ObjInspector',
_init : function () { _init: function(lookingGlass) {
this._obj = null; this._obj = null;
this._previousObj = null; this._previousObj = null;
@ -369,6 +378,8 @@ const ObjInspector = new Lang.Class({
style_class: 'lg-dialog', style_class: 'lg-dialog',
vertical: true }); vertical: true });
this.actor.add_actor(this._container); this.actor.add_actor(this._container);
this._lookingGlass = lookingGlass;
}, },
selectObject: function(obj, skipPrevious) { selectObject: function(obj, skipPrevious) {
@ -412,7 +423,7 @@ const ObjInspector = new Lang.Class({
let link; let link;
try { try {
let prop = obj[propName]; let prop = obj[propName];
link = new ObjLink(prop).actor; link = new ObjLink(this._lookingGlass, prop).actor;
} catch (e) { } catch (e) {
link = new St.Label({ text: '<error>' }); link = new St.Label({ text: '<error>' });
} }
@ -457,7 +468,7 @@ const ObjInspector = new Lang.Class({
_onInsert: function() { _onInsert: function() {
let obj = this._obj; let obj = this._obj;
this.close(); this.close();
Main.lookingGlass.insertObject(obj); this._lookingGlass.insertObject(obj);
}, },
_onBack: function() { _onBack: function() {
@ -465,34 +476,36 @@ const ObjInspector = new Lang.Class({
} }
}); });
function addBorderPaintHook(actor) { const RedBorderEffect = new Lang.Class({
let signalId = actor.connect_after('paint', Name: 'RedBorderEffect',
function () { Extends: Clutter.Effect,
let color = new Cogl.Color();
color.init_from_4ub(0xff, 0, 0, 0xc4);
Cogl.set_source_color(color);
let geom = actor.get_allocation_geometry(); vfunc_paint: function() {
let width = 2; let actor = this.get_actor();
actor.continue_paint();
// clockwise order let color = new Cogl.Color();
Cogl.rectangle(0, 0, geom.width, width); color.init_from_4ub(0xff, 0, 0, 0xc4);
Cogl.rectangle(geom.width - width, width, Cogl.set_source_color(color);
geom.width, geom.height);
Cogl.rectangle(0, geom.height,
geom.width - width, geom.height - width);
Cogl.rectangle(0, geom.height - width,
width, width);
});
actor.queue_redraw(); let geom = actor.get_allocation_geometry();
return signalId; let width = 2;
}
// clockwise order
Cogl.rectangle(0, 0, geom.width, width);
Cogl.rectangle(geom.width - width, width,
geom.width, geom.height);
Cogl.rectangle(0, geom.height,
geom.width - width, geom.height - width);
Cogl.rectangle(0, geom.height - width,
width, width);
},
});
const Inspector = new Lang.Class({ const Inspector = new Lang.Class({
Name: 'Inspector', Name: 'Inspector',
_init: function() { _init: function(lookingGlass) {
let container = new Shell.GenericContainer({ width: 0, let container = new Shell.GenericContainer({ width: 0,
height: 0 }); height: 0 });
container.connect('allocate', Lang.bind(this, this._allocate)); container.connect('allocate', Lang.bind(this, this._allocate));
@ -506,9 +519,6 @@ const Inspector = new Lang.Class({
this._displayText = new St.Label(); this._displayText = new St.Label();
eventHandler.add(this._displayText, { expand: true }); eventHandler.add(this._displayText, { expand: true });
this._borderPaintTarget = null;
this._borderPaintId = null;
eventHandler.connect('destroy', Lang.bind(this, this._onDestroy));
eventHandler.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent)); eventHandler.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
eventHandler.connect('button-press-event', Lang.bind(this, this._onButtonPressEvent)); eventHandler.connect('button-press-event', Lang.bind(this, this._onButtonPressEvent));
eventHandler.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); eventHandler.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
@ -523,6 +533,8 @@ const Inspector = new Lang.Class({
// out, or move the pointer outside of _pointerTarget. // out, or move the pointer outside of _pointerTarget.
this._target = null; this._target = null;
this._pointerTarget = null; this._pointerTarget = null;
this._lookingGlass = lookingGlass;
}, },
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
@ -550,11 +562,6 @@ const Inspector = new Lang.Class({
this.emit('closed'); this.emit('closed');
}, },
_onDestroy: function() {
if (this._borderPaintTarget != null)
this._borderPaintTarget.disconnect(this._borderPaintId);
},
_onKeyPressEvent: function (actor, event) { _onKeyPressEvent: function (actor, event) {
if (event.get_key_symbol() == Clutter.Escape) if (event.get_key_symbol() == Clutter.Escape)
this._close(); this._close();
@ -623,12 +630,7 @@ const Inspector = new Lang.Class({
this._displayText.text = ''; this._displayText.text = '';
this._displayText.text = position + ' ' + this._target; this._displayText.text = position + ' ' + this._target;
if (this._borderPaintTarget != this._target) { this._lookingGlass.setBorderPaintTarget(this._target);
if (this._borderPaintTarget != null)
this._borderPaintTarget.disconnect(this._borderPaintId);
this._borderPaintTarget = this._target;
this._borderPaintId = addBorderPaintHook(this._target);
}
} }
}); });
@ -662,7 +664,7 @@ const Memory = new Lang.Class({
this._gcbutton = new St.Button({ label: 'Full GC', this._gcbutton = new St.Button({ label: 'Full GC',
style_class: 'lg-obj-inspector-button' }); style_class: 'lg-obj-inspector-button' });
this._gcbutton.connect('clicked', Lang.bind(this, function () { global.gc(); this._renderText(); })); this._gcbutton.connect('clicked', Lang.bind(this, function () { System.gc(); this._renderText(); }));
this.actor.add(this._gcbutton, { x_align: St.Align.START, this.actor.add(this._gcbutton, { x_align: St.Align.START,
x_fill: false }); x_fill: false });
@ -723,13 +725,13 @@ const Extensions = new Lang.Class({
let extension = actor._extension; let extension = actor._extension;
let uri = extension.dir.get_uri(); let uri = extension.dir.get_uri();
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context()); Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context());
Main.lookingGlass.close(); this._lookingGlass.close();
}, },
_onWebPage: function (actor) { _onWebPage: function (actor) {
let extension = actor._extension; let extension = actor._extension;
Gio.app_info_launch_default_for_uri(extension.metadata.url, global.create_app_launch_context()); Gio.app_info_launch_default_for_uri(extension.metadata.url, global.create_app_launch_context());
Main.lookingGlass.close(); this._lookingGlass.close();
}, },
_onViewErrors: function (actor) { _onViewErrors: function (actor) {
@ -793,24 +795,33 @@ const Extensions = new Lang.Class({
text: this._stateToString(extension.state) }); text: this._stateToString(extension.state) });
metaBox.add(state); metaBox.add(state);
let viewsource = new Link.Link({ label: _("View Source") }); let viewsource = new St.Button({ reactive: true,
viewsource.actor._extension = extension; track_hover: true,
viewsource.actor.connect('clicked', Lang.bind(this, this._onViewSource)); style_class: 'shell-link',
metaBox.add(viewsource.actor); label: _("View Source") });
viewsource._extension = extension;
viewsource.connect('clicked', Lang.bind(this, this._onViewSource));
metaBox.add(viewsource);
if (extension.metadata.url) { if (extension.metadata.url) {
let webpage = new Link.Link({ label: _("Web Page") }); let webpage = new St.Button({ reactive: true,
webpage.actor._extension = extension; track_hover: true,
webpage.actor.connect('clicked', Lang.bind(this, this._onWebPage)); style_class: 'shell-link',
metaBox.add(webpage.actor); label: _("Web Page") });
webpage._extension = extension;
webpage.connect('clicked', Lang.bind(this, this._onWebPage));
metaBox.add(webpage);
} }
let viewerrors = new Link.Link({ label: _("Show Errors") }); let viewerrors = new St.Button({ reactive: true,
viewerrors.actor._extension = extension; track_hover: true,
viewerrors.actor._parentBox = box; style_class: 'shell-link',
viewerrors.actor._isShowing = false; label: _("Show Errors") });
viewerrors.actor.connect('clicked', Lang.bind(this, this._onViewErrors)); viewerrors._extension = extension;
metaBox.add(viewerrors.actor); viewerrors._parentBox = box;
viewerrors._isShowing = false;
viewerrors.connect('clicked', Lang.bind(this, this._onViewErrors));
metaBox.add(viewerrors);
return box; return box;
} }
@ -821,8 +832,7 @@ const LookingGlass = new Lang.Class({
_init : function() { _init : function() {
this._borderPaintTarget = null; this._borderPaintTarget = null;
this._borderPaintId = 0; this._redBorderEffect = new RedBorderEffect();
this._borderDestroyId = 0;
this._open = false; this._open = false;
@ -852,7 +862,7 @@ const LookingGlass = new Lang.Class({
Main.layoutManager.keyboardBox.connect('allocation-changed', Main.layoutManager.keyboardBox.connect('allocation-changed',
Lang.bind(this, this._queueResize)); Lang.bind(this, this._queueResize));
this._objInspector = new ObjInspector(); this._objInspector = new ObjInspector(this);
Main.uiGroup.add_actor(this._objInspector.actor); Main.uiGroup.add_actor(this._objInspector.actor);
this._objInspector.actor.hide(); this._objInspector.actor.hide();
@ -864,7 +874,7 @@ const LookingGlass = new Lang.Class({
toolbar.add_actor(inspectIcon); toolbar.add_actor(inspectIcon);
inspectIcon.reactive = true; inspectIcon.reactive = true;
inspectIcon.connect('button-press-event', Lang.bind(this, function () { inspectIcon.connect('button-press-event', Lang.bind(this, function () {
let inspector = new Inspector(); let inspector = new Inspector(this);
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) { inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>', this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
target); target);
@ -894,18 +904,14 @@ const LookingGlass = new Lang.Class({
this._entryArea = new St.BoxLayout({ name: 'EntryArea' }); this._entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(this._entryArea); this._evalBox.add_actor(this._entryArea);
let label = new St.Label({ text: 'js>>> ' }); let label = new St.Label({ text: CHEVRON });
this._entryArea.add(label); this._entryArea.add(label);
this._entry = new St.Entry({ can_focus: true }); this._entry = new St.Entry({ can_focus: true });
ShellEntry.addContextMenu(this._entry); ShellEntry.addContextMenu(this._entry);
this._entryArea.add(this._entry, { expand: true }); this._entryArea.add(this._entry, { expand: true });
this._windowList = new WindowList(); this._windowList = new WindowList(this);
this._windowList.connect('selected', Lang.bind(this, function(list, window) {
notebook.selectIndex(0);
this._pushResult('<window selection>', window);
}));
notebook.appendPage('Windows', this._windowList.actor); notebook.appendPage('Windows', this._windowList.actor);
this._memory = new Memory(); this._memory = new Memory();
@ -959,23 +965,22 @@ const LookingGlass = new Lang.Class({
+ 'font-family: "' + fontDesc.get_family() + '";'; + 'font-family: "' + fontDesc.get_family() + '";';
}, },
setBorderPaintTarget: function(obj) {
if (this._borderPaintTarget != null)
this._borderPaintTarget.remove_effect(this._redBorderEffect);
this._borderPaintTarget = obj;
if (this._borderPaintTarget != null)
this._borderPaintTarget.add_effect(this._redBorderEffect);
},
_pushResult: function(command, obj) { _pushResult: function(command, obj) {
let index = this._results.length + this._offset; let index = this._results.length + this._offset;
let result = new Result('>>> ' + command, obj, index); let result = new Result(this, CHEVRON + command, obj, index);
this._results.push(result); this._results.push(result);
this._resultsArea.add(result.actor); this._resultsArea.add(result.actor);
if (this._borderPaintTarget != null) { if (obj instanceof Clutter.Actor)
this._borderPaintTarget.disconnect(this._borderPaintId); this.setBorderPaintTarget(obj);
this._borderPaintTarget = null;
}
if (obj instanceof Clutter.Actor) {
this._borderPaintTarget = obj;
this._borderPaintId = addBorderPaintHook(obj);
this._borderDestroyId = obj.connect('destroy', Lang.bind(this, function () {
this._borderDestroyId = 0;
this._borderPaintTarget = null;
}));
}
let children = this._resultsArea.get_children(); let children = this._resultsArea.get_children();
if (children.length > this._maxItems) { if (children.length > this._maxItems) {
this._results.shift(); this._results.shift();
@ -1156,11 +1161,7 @@ const LookingGlass = new Lang.Class({
this._open = false; this._open = false;
Tweener.removeTweens(this.actor); Tweener.removeTweens(this.actor);
if (this._borderPaintTarget != null) { this.setBorderPaintTarget(null);
this._borderPaintTarget.disconnect(this._borderPaintId);
this._borderPaintTarget.disconnect(this._borderDestroyId);
this._borderPaintTarget = null;
}
Main.popModal(this._entry); Main.popModal(this._entry);

View File

@ -26,6 +26,7 @@ const MAGNIFIER_SCHEMA = 'org.gnome.desktop.a11y.magnifier';
const SCREEN_POSITION_KEY = 'screen-position'; const SCREEN_POSITION_KEY = 'screen-position';
const MAG_FACTOR_KEY = 'mag-factor'; const MAG_FACTOR_KEY = 'mag-factor';
const INVERT_LIGHTNESS_KEY = 'invert-lightness'; const INVERT_LIGHTNESS_KEY = 'invert-lightness';
const COLOR_SATURATION_KEY = 'color-saturation';
const BRIGHT_RED_KEY = 'brightness-red'; const BRIGHT_RED_KEY = 'brightness-red';
const BRIGHT_GREEN_KEY = 'brightness-green'; const BRIGHT_GREEN_KEY = 'brightness-green';
const BRIGHT_BLUE_KEY = 'brightness-blue'; const BRIGHT_BLUE_KEY = 'brightness-blue';
@ -456,6 +457,10 @@ const Magnifier = new Lang.Class({
if (aPref) if (aPref)
zoomRegion.setInvertLightness(aPref); zoomRegion.setInvertLightness(aPref);
aPref = this._settings.get_double(COLOR_SATURATION_KEY);
if (aPref)
zoomRegion.setColorSaturation(aPref);
let bc = {}; let bc = {};
bc.r = this._settings.get_double(BRIGHT_RED_KEY); bc.r = this._settings.get_double(BRIGHT_RED_KEY);
bc.g = this._settings.get_double(BRIGHT_GREEN_KEY); bc.g = this._settings.get_double(BRIGHT_GREEN_KEY);
@ -490,6 +495,8 @@ const Magnifier = new Lang.Class({
this._settings.connect('changed::' + INVERT_LIGHTNESS_KEY, this._settings.connect('changed::' + INVERT_LIGHTNESS_KEY,
Lang.bind(this, this._updateInvertLightness)); Lang.bind(this, this._updateInvertLightness));
this._settings.connect('changed::' + COLOR_SATURATION_KEY,
Lang.bind(this, this._updateColorSaturation));
this._settings.connect('changed::' + BRIGHT_RED_KEY, this._settings.connect('changed::' + BRIGHT_RED_KEY,
Lang.bind(this, this._updateBrightness)); Lang.bind(this, this._updateBrightness));
@ -591,6 +598,15 @@ const Magnifier = new Lang.Class({
} }
}, },
_updateColorSaturation: function() {
// Applies only to the first zoom region.
if (this._zoomRegions.length) {
this._zoomRegions[0].setColorSaturation(
this._settings.get_boolean(COLOR_SATURATION_KEY)
);
}
},
_updateBrightness: function() { _updateBrightness: function() {
// Applies only to the first zoom region. // Applies only to the first zoom region.
if (this._zoomRegions.length) { if (this._zoomRegions.length) {
@ -626,6 +642,7 @@ const ZoomRegion = new Lang.Class({
this._lensMode = false; this._lensMode = false;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN; this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
this._invertLightness = false; this._invertLightness = false;
this._colorSaturation = 1.0;
this._brightness = { r: NO_CHANGE, g: NO_CHANGE, b: NO_CHANGE }; this._brightness = { r: NO_CHANGE, g: NO_CHANGE, b: NO_CHANGE };
this._contrast = { r: NO_CHANGE, g: NO_CHANGE, b: NO_CHANGE }; this._contrast = { r: NO_CHANGE, g: NO_CHANGE, b: NO_CHANGE };
@ -973,6 +990,27 @@ const ZoomRegion = new Lang.Class({
return this._invertLightness; return this._invertLightness;
}, },
/**
* setColorSaturation:
* Set the color saturation of the magnified view.
* @sauration A value from 0.0 to 1.0 that defines the color
* saturation, with 0.0 defining no color (grayscale),
* and 1.0 defining full color.
*/
setColorSaturation: function(saturation) {
this._colorSaturation = saturation;
if (this._magShaderEffects)
this._magShaderEffects.setColorSaturation(this._colorSaturation);
},
/**
* getColorSaturation:
* Retrieve the color saturation of the magnified view.
*/
getColorSaturation: function() {
return this._colorSaturation;
},
/** /**
* setBrightness: * setBrightness:
* Alter the brightness of the magnified view. * Alter the brightness of the magnified view.
@ -1074,6 +1112,7 @@ const ZoomRegion = new Lang.Class({
// Contrast and brightness effects. // Contrast and brightness effects.
this._magShaderEffects = new MagShaderEffects(this._uiGroupClone); this._magShaderEffects = new MagShaderEffects(this._uiGroupClone);
this._magShaderEffects.setColorSaturation(this._colorSaturation);
this._magShaderEffects.setInvertLightness(this._invertLightness); this._magShaderEffects.setInvertLightness(this._invertLightness);
this._magShaderEffects.setBrightness(this._brightness); this._magShaderEffects.setBrightness(this._brightness);
this._magShaderEffects.setContrast(this._contrast); this._magShaderEffects.setContrast(this._contrast);
@ -1602,12 +1641,14 @@ const MagShaderEffects = new Lang.Class({
_init: function(uiGroupClone) { _init: function(uiGroupClone) {
this._inverse = new Shell.InvertLightnessEffect(); this._inverse = new Shell.InvertLightnessEffect();
this._brightnessContrast = new Clutter.BrightnessContrastEffect(); this._brightnessContrast = new Clutter.BrightnessContrastEffect();
this._colorSaturation = new Clutter.DesaturateEffect();
this._inverse.set_enabled(false); this._inverse.set_enabled(false);
this._brightnessContrast.set_enabled(false); this._brightnessContrast.set_enabled(false);
this._magView = uiGroupClone; this._magView = uiGroupClone;
this._magView.add_effect(this._inverse); this._magView.add_effect(this._inverse);
this._magView.add_effect(this._brightnessContrast); this._magView.add_effect(this._brightnessContrast);
this._magView.add_effect(this._colorSaturation);
}, },
/** /**
@ -1618,6 +1659,7 @@ const MagShaderEffects = new Lang.Class({
*/ */
destroyEffects: function() { destroyEffects: function() {
this._magView.clear_effects(); this._magView.clear_effects();
this._colorSaturation = null;
this._brightnessContrast = null; this._brightnessContrast = null;
this._inverse = null; this._inverse = null;
this._magView = null; this._magView = null;
@ -1641,6 +1683,14 @@ const MagShaderEffects = new Lang.Class({
return this._inverse.get_enabled(); return this._inverse.get_enabled();
}, },
setColorSaturation: function(factor) {
this._colorSaturation.set_factor(factor);
},
getColorSaturation: function() {
return this._colorSaturation.get_factor();
},
/** /**
* setBrightness: * setBrightness:
* Set the brightness of the magnified view. * Set the brightness of the magnified view.

View File

@ -611,13 +611,13 @@ function _globalKeyPressHandler(actor, event) {
if (!sessionMode.hasWorkspaces) if (!sessionMode.hasWorkspaces)
return false; return false;
wm.actionMoveWorkspaceUp(); wm.actionMoveWorkspace(Meta.MotionDirection.UP);
return true; return true;
case Meta.KeyBindingAction.WORKSPACE_DOWN: case Meta.KeyBindingAction.WORKSPACE_DOWN:
if (!sessionMode.hasWorkspaces) if (!sessionMode.hasWorkspaces)
return false; return false;
wm.actionMoveWorkspaceDown(); wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
return true; return true;
case Meta.KeyBindingAction.PANEL_RUN_DIALOG: case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
case Meta.KeyBindingAction.COMMAND_2: case Meta.KeyBindingAction.COMMAND_2:

View File

@ -493,6 +493,7 @@ const Notification = new Lang.Class({
params = Params.parse(params, { customContent: false, params = Params.parse(params, { customContent: false,
body: null, body: null,
icon: null, icon: null,
secondaryIcon: null,
titleMarkup: false, titleMarkup: false,
bannerMarkup: false, bannerMarkup: false,
bodyMarkup: false, bodyMarkup: false,
@ -507,6 +508,11 @@ const Notification = new Lang.Class({
this._icon = null; this._icon = null;
} }
if (this._secondaryIcon && (params.secondaryIcon || params.clear)) {
this._secondaryIcon.destroy();
this._secondaryIcon = null;
}
// We always clear the content area if we don't have custom // We always clear the content area if we don't have custom
// content because it might contain the @banner that didn't // content because it might contain the @banner that didn't
// fit in the banner mode. // fit in the banner mode.
@ -542,6 +548,13 @@ const Notification = new Lang.Class({
y_align: St.Align.START }); y_align: St.Align.START });
} }
if (!this._secondaryIcon) {
this._secondaryIcon = params.secondaryIcon;
if (this._secondaryIcon)
this._bannerBox.add_actor(this._secondaryIcon);
}
this.title = title; this.title = title;
title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : ''; title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : '';
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>'); this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
@ -815,8 +828,15 @@ const Notification = new Lang.Class({
let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight); let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight);
let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight); let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight);
alloc.min_size = titleMin; if (this._secondaryIcon) {
alloc.natural_size = titleNat + this._spacing + bannerNat; let [secondaryIconMin, secondaryIconNat] = this._secondaryIcon.get_preferred_width(forHeight);
alloc.min_size = secondaryIconMin + this._spacing + titleMin;
alloc.natural_size = secondaryIconNat + this._spacing + titleNat + this._spacing + bannerNat;
} else {
alloc.min_size = titleMin;
alloc.natural_size = titleNat + this._spacing + bannerNat;
}
}, },
_bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) { _bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) {
@ -831,14 +851,42 @@ const Notification = new Lang.Class({
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth); let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth); let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
let rtl = (this._titleDirection == Clutter.TextDirection.RTL);
let x = rtl ? availWidth : 0;
if (this._secondaryIcon) {
let [iconMinW, iconNatW] = this._secondaryIcon.get_preferred_width(-1);
let [iconMinH, iconNatH] = this._secondaryIcon.get_preferred_height(availWidth);
let secondaryIconBox = new Clutter.ActorBox();
let secondaryIconBoxW = Math.min(iconNatW, availWidth);
// allocate secondary icon box
if (rtl) {
secondaryIconBox.x1 = x - secondaryIconBoxW;
secondaryIconBox.x2 = x;
x = x - (secondaryIconBoxW + this._spacing);
} else {
secondaryIconBox.x1 = x;
secondaryIconBox.x2 = x + secondaryIconBoxW;
x = x + secondaryIconBoxW + this._spacing;
}
secondaryIconBox.y1 = 0;
// Using titleNatH ensures that the secondary icon is centered vertically
secondaryIconBox.y2 = titleNatH;
availWidth = availWidth - (secondaryIconBoxW + this._spacing);
this._secondaryIcon.allocate(secondaryIconBox, flags);
}
let titleBox = new Clutter.ActorBox(); let titleBox = new Clutter.ActorBox();
let titleBoxW = Math.min(titleNatW, availWidth); let titleBoxW = Math.min(titleNatW, availWidth);
if (this._titleDirection == Clutter.TextDirection.RTL) { if (rtl) {
titleBox.x1 = availWidth - titleBoxW; titleBox.x1 = availWidth - titleBoxW;
titleBox.x2 = availWidth; titleBox.x2 = availWidth;
} else { } else {
titleBox.x1 = 0; titleBox.x1 = x;
titleBox.x2 = titleBoxW; titleBox.x2 = titleBox.x1 + titleBoxW;
} }
titleBox.y1 = 0; titleBox.y1 = 0;
titleBox.y2 = titleNatH; titleBox.y2 = titleNatH;
@ -852,7 +900,7 @@ const Notification = new Lang.Class({
} else { } else {
let bannerBox = new Clutter.ActorBox(); let bannerBox = new Clutter.ActorBox();
if (this._titleDirection == Clutter.TextDirection.RTL) { if (rtl) {
bannerBox.x1 = 0; bannerBox.x1 = 0;
bannerBox.x2 = titleBox.x1 - this._spacing; bannerBox.x2 = titleBox.x1 - this._spacing;
@ -1479,7 +1527,7 @@ const MessageTray = new Lang.Class({
Main.layoutManager.trackChrome(this._corner); Main.layoutManager.trackChrome(this._corner);
Main.layoutManager.trayBox.add_actor(this.actor); Main.layoutManager.trayBox.add_actor(this.actor);
this.actor.y = this.actor.height; this.actor.y = 0;
Main.layoutManager.trackChrome(this.actor); Main.layoutManager.trackChrome(this.actor);
Main.layoutManager.trackChrome(this._notificationBin); Main.layoutManager.trackChrome(this._notificationBin);
@ -1887,7 +1935,7 @@ const MessageTray = new Lang.Class({
_onTrayHoverChanged: function() { _onTrayHoverChanged: function() {
if (this.actor.hover) { if (this.actor.hover) {
// Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden. // Don't do anything if the one pixel area at the bottom is hovered over while the tray is hidden.
if (this._trayState == State.HIDDEN) if (this._trayState == State.HIDDEN && this._notificationState == State.HIDDEN)
return; return;
// Don't do anything if this._useLongerTrayLeftTimeout is true, meaning the notification originally // Don't do anything if this._useLongerTrayLeftTimeout is true, meaning the notification originally
@ -2022,7 +2070,7 @@ const MessageTray = new Lang.Class({
let notificationUrgent = this._notificationQueue.length > 0 && this._notificationQueue[0].urgency == Urgency.CRITICAL; let notificationUrgent = this._notificationQueue.length > 0 && this._notificationQueue[0].urgency == Urgency.CRITICAL;
let notificationsPending = this._notificationQueue.length > 0 && ((!this._busy && !this._inFullscreen) || notificationUrgent); let notificationsPending = this._notificationQueue.length > 0 && ((!this._busy && !this._inFullscreen) || notificationUrgent);
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved; let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
let notificationExpanded = this._notificationBin.y < 0; let notificationExpanded = this._notificationBin.y < - this.actor.height;
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked && !(this._pointerInKeyboard && notificationExpanded)) || this._notificationRemoved; let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked && !(this._pointerInKeyboard && notificationExpanded)) || this._notificationRemoved;
let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN; let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
@ -2102,8 +2150,7 @@ const MessageTray = new Lang.Class({
// Tray itself // Tray itself
let trayIsVisible = (this._trayState == State.SHOWING || let trayIsVisible = (this._trayState == State.SHOWING ||
this._trayState == State.SHOWN); this._trayState == State.SHOWN);
let trayShouldBeVisible = (!notificationsDone || let trayShouldBeVisible = (this._summaryState == State.SHOWING ||
this._summaryState == State.SHOWING ||
this._summaryState == State.SHOWN); this._summaryState == State.SHOWN);
if (!trayIsVisible && trayShouldBeVisible) if (!trayIsVisible && trayShouldBeVisible)
this._showTray(); this._showTray();
@ -2143,7 +2190,7 @@ const MessageTray = new Lang.Class({
_hideTray: function() { _hideTray: function() {
this._tween(this.actor, '_trayState', State.HIDDEN, this._tween(this.actor, '_trayState', State.HIDDEN,
{ y: this.actor.height, { y: 0,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
@ -2180,7 +2227,7 @@ const MessageTray = new Lang.Class({
this._notificationBin.child = this._notification.actor; this._notificationBin.child = this._notification.actor;
this._notificationBin.opacity = 0; this._notificationBin.opacity = 0;
this._notificationBin.y = this.actor.height; this._notificationBin.y = 0;
this._notificationBin.show(); this._notificationBin.show();
this._updateShowingNotification(); this._updateShowingNotification();
@ -2215,7 +2262,8 @@ const MessageTray = new Lang.Class({
// We tween all notifications to full opacity. This ensures that both new notifications and // We tween all notifications to full opacity. This ensures that both new notifications and
// notifications that might have been in the process of hiding get full opacity. // notifications that might have been in the process of hiding get full opacity.
// //
// We tween any notification showing in the banner mode to banner height (this._notificationBin.y = 0). // We tween any notification showing in the banner mode to banner height
// (this._notificationBin.y = -this.actor.height).
// This ensures that both new notifications and notifications in the banner mode that might // This ensures that both new notifications and notifications in the banner mode that might
// have been in the process of hiding are shown with the banner height. // have been in the process of hiding are shown with the banner height.
// //
@ -2232,7 +2280,7 @@ const MessageTray = new Lang.Class({
onCompleteScope: this onCompleteScope: this
}; };
if (!this._notification.expanded) if (!this._notification.expanded)
tweenParams.y = 0; tweenParams.y = - this.actor.height;
this._tween(this._notificationBin, '_notificationState', State.SHOWN, tweenParams); this._tween(this._notificationBin, '_notificationState', State.SHOWN, tweenParams);
}, },
@ -2321,7 +2369,7 @@ const MessageTray = new Lang.Class({
}, },
_onNotificationExpanded: function() { _onNotificationExpanded: function() {
let expandedY = this.actor.height - this._notificationBin.height; let expandedY = - this._notificationBin.height;
// Don't animate the notification to its new position if it has shrunk: // Don't animate the notification to its new position if it has shrunk:
// there will be a very visible "gap" that breaks the illusion. // there will be a very visible "gap" that breaks the illusion.
@ -2429,7 +2477,7 @@ const MessageTray = new Lang.Class({
this._summaryBoxPointerState = State.SHOWING; this._summaryBoxPointerState = State.SHOWING;
this._clickedSummaryItem.actor.add_style_pseudo_class('selected'); this._clickedSummaryItem.actor.add_style_pseudo_class('selected');
this._summaryBoxPointer.show(true, Lang.bind(this, function() { this._summaryBoxPointer.show(BoxPointer.PopupAnimation.FULL, Lang.bind(this, function() {
this._summaryBoxPointerState = State.SHOWN; this._summaryBoxPointerState = State.SHOWN;
})); }));
}, },
@ -2442,11 +2490,10 @@ const MessageTray = new Lang.Class({
}, },
_adjustSummaryBoxPointerPosition: function() { _adjustSummaryBoxPointerPosition: function() {
// The position of the arrow origin should be the same as center of this._clickedSummaryItem.actor
if (!this._clickedSummaryItem) if (!this._clickedSummaryItem)
return; return;
this._summaryBoxPointer.setPosition(this._clickedSummaryItem.actor, 0, 0.5); this._summaryBoxPointer.setPosition(this._clickedSummaryItem.actor, 0);
}, },
_unsetClickedSummaryItem: function() { _unsetClickedSummaryItem: function() {
@ -2484,7 +2531,7 @@ const MessageTray = new Lang.Class({
this._summaryBoxPointer.actor.hide(); this._summaryBoxPointer.actor.hide();
this._hideSummaryBoxPointerCompleted(); this._hideSummaryBoxPointerCompleted();
} else { } else {
this._summaryBoxPointer.hide(true, Lang.bind(this, this._hideSummaryBoxPointerCompleted)); this._summaryBoxPointer.hide(BoxPointer.PopupAnimation.FULL, Lang.bind(this, this._hideSummaryBoxPointerCompleted));
} }
}, },

View File

@ -683,7 +683,10 @@ const NetworkAgent = new Lang.Class({
try { try {
externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode'); externalUIMode = keyfile.get_boolean('GNOME', 'supports-external-ui-mode');
} catch(e) { } // ignore errors if key does not exist } catch(e) { } // ignore errors if key does not exist
let path = GLib.build_filenamev([Config.LIBEXECDIR, binary]); let path = binary;
if (!GLib.path_is_absolute(path)) {
path = GLib.build_filenamev([Config.LIBEXECDIR, path]);
}
if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE)) if (GLib.file_test(path, GLib.FileTest.IS_EXECUTABLE))
this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode }; this._vpnBinaries[service] = { fileName: path, externalUIMode: externalUIMode };

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Config = imports.misc.config;
const Gtk = imports.gi.Gtk; const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
@ -12,7 +11,6 @@ const Shell = imports.gi.Shell;
const Gdk = imports.gi.Gdk; const Gdk = imports.gi.Gdk;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const ContactDisplay = Config.HAVE_FOLKS ? imports.ui.contactDisplay : null;
const Dash = imports.ui.dash; const Dash = imports.ui.dash;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -208,8 +206,6 @@ const Overview = new Lang.Class({
this.addSearchProvider(new AppDisplay.AppSearchProvider()); this.addSearchProvider(new AppDisplay.AppSearchProvider());
this.addSearchProvider(new AppDisplay.SettingsSearchProvider()); this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider()); this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
if (ContactDisplay != null)
this.addSearchProvider(new ContactDisplay.ContactSearchProvider());
// Load remote search providers provided by applications // Load remote search providers provided by applications
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider)); RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));

View File

@ -346,6 +346,7 @@ const AppMenuButton = new Lang.Class({
return; return;
this._stop = true; this._stop = true;
this.actor.reactive = true;
Tweener.addTween(this._spinner.actor, Tweener.addTween(this._spinner.actor,
{ opacity: 0, { opacity: 0,
time: SPINNER_ANIMATION_TIME, time: SPINNER_ANIMATION_TIME,
@ -360,6 +361,7 @@ const AppMenuButton = new Lang.Class({
startAnimation: function() { startAnimation: function() {
this._stop = false; this._stop = false;
this.actor.reactive = false;
this._spinner.actor.show(); this._spinner.actor.show();
}, },
@ -1126,7 +1128,8 @@ const Panel = new Lang.Class({
if (!position) if (!position)
position = 0; position = 0;
this._insertStatusItem(indicator.actor, position); this._insertStatusItem(indicator.actor, position);
this._menus.addMenu(indicator.menu); if (indicator.menu)
this._menus.addMenu(indicator.menu);
this._statusArea[role] = indicator; this._statusArea[role] = indicator;
let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) { let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) {

View File

@ -269,7 +269,7 @@ const AuthenticationDialog = new Lang.Class({
_onSessionRequest: function(session, request, echo_on) { _onSessionRequest: function(session, request, echo_on) {
// Cheap localization trick // Cheap localization trick
if (request == 'Password:') if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:")); this._passwordLabel.set_text(_("Password:"));
else else
this._passwordLabel.set_text(request); this._passwordLabel.set_text(request);

View File

@ -942,7 +942,7 @@ const PopupMenuBase = new Lang.Class({
_connectSubMenuSignals: function(object, menu) { _connectSubMenuSignals: function(object, menu) {
object._subMenuActivateId = menu.connect('activate', Lang.bind(this, function() { object._subMenuActivateId = menu.connect('activate', Lang.bind(this, function() {
this.emit('activate'); this.emit('activate');
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
})); }));
object._subMenuActiveChangeId = menu.connect('active-changed', Lang.bind(this, function(submenu, submenuItem) { object._subMenuActiveChangeId = menu.connect('active-changed', Lang.bind(this, function(submenu, submenuItem) {
if (this._activeMenuItem && this._activeMenuItem != submenuItem) if (this._activeMenuItem && this._activeMenuItem != submenuItem)
@ -977,7 +977,7 @@ const PopupMenuBase = new Lang.Class({
})); }));
menuItem._activateId = menuItem.connect('activate', Lang.bind(this, function (menuItem, event) { menuItem._activateId = menuItem.connect('activate', Lang.bind(this, function (menuItem, event) {
this.emit('activate', menuItem); this.emit('activate', menuItem);
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
})); }));
// the weird name is to avoid a conflict with some random property // the weird name is to avoid a conflict with some random property
// the menuItem may have, called destroyId // the menuItem may have, called destroyId
@ -1050,7 +1050,7 @@ const PopupMenuBase = new Lang.Class({
menuItem._closingId = this.connect('open-state-changed', menuItem._closingId = this.connect('open-state-changed',
function(self, open) { function(self, open) {
if (!open) if (!open)
menuItem.close(false); menuItem.close(BoxPointer.PopupAnimation.FADE);
}); });
menuItem.connect('destroy', Lang.bind(this, function() { menuItem.connect('destroy', Lang.bind(this, function() {
menuItem.disconnect(menuItem._subMenuActivateId); menuItem.disconnect(menuItem._subMenuActivateId);
@ -1067,7 +1067,7 @@ const PopupMenuBase = new Lang.Class({
this._connectItemSignals(menuItem); this._connectItemSignals(menuItem);
menuItem._closingId = this.connect('open-state-changed', function(self, open) { menuItem._closingId = this.connect('open-state-changed', function(self, open) {
if (!open) if (!open)
menuItem.menu.close(false); menuItem.menu.close(BoxPointer.PopupAnimation.FADE);
}); });
} else if (menuItem instanceof PopupSeparatorMenuItem) { } else if (menuItem instanceof PopupSeparatorMenuItem) {
this._connectItemSignals(menuItem); this._connectItemSignals(menuItem);
@ -1154,9 +1154,9 @@ const PopupMenuBase = new Lang.Class({
toggle: function() { toggle: function() {
if (this.isOpen) if (this.isOpen)
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
else else
this.open(true); this.open(BoxPointer.PopupAnimation.FULL);
}, },
destroy: function() { destroy: function() {
@ -1217,7 +1217,7 @@ const PopupMenu = new Lang.Class({
_onKeyPressEvent: function(actor, event) { _onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) { if (event.get_key_symbol() == Clutter.Escape) {
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
return true; return true;
} }
@ -1419,7 +1419,7 @@ const PopupSubMenu = new Lang.Class({
// Move focus back to parent menu if the user types Left. // Move focus back to parent menu if the user types Left.
if (this.isOpen && event.get_key_symbol() == Clutter.KEY_Left) { if (this.isOpen && event.get_key_symbol() == Clutter.KEY_Left) {
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
this.sourceActor._delegate.setActive(true); this.sourceActor._delegate.setActive(true);
return true; return true;
} }
@ -1501,7 +1501,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Right) { if (symbol == Clutter.KEY_Right) {
this.menu.open(true); this.menu.open(BoxPointer.PopupAnimation.FULL);
this.menu.actor.navigate_focus(null, Gtk.DirectionType.DOWN, false); this.menu.actor.navigate_focus(null, Gtk.DirectionType.DOWN, false);
return true; return true;
} else if (symbol == Clutter.KEY_Left && this.menu.isOpen) { } else if (symbol == Clutter.KEY_Left && this.menu.isOpen) {
@ -1513,7 +1513,7 @@ const PopupSubMenuMenuItem = new Lang.Class({
}, },
activate: function(event) { activate: function(event) {
this.menu.open(true); this.menu.open(BoxPointer.PopupAnimation.FULL);
}, },
_onButtonReleaseEvent: function(actor) { _onButtonReleaseEvent: function(actor) {
@ -1540,7 +1540,7 @@ const PopupComboMenu = new Lang.Class({
_onKeyPressEvent: function(actor, event) { _onKeyPressEvent: function(actor, event) {
if (event.get_key_symbol() == Clutter.Escape) { if (event.get_key_symbol() == Clutter.Escape) {
this.close(true); this.close(BoxPointer.PopupAnimation.FULL);
return true; return true;
} }
@ -2194,11 +2194,11 @@ const PopupMenuManager = new Lang.Class({
let oldMenu = this._activeMenu; let oldMenu = this._activeMenu;
this._activeMenu = null; this._activeMenu = null;
for (let i = this._menuStack.length - 1; i >= 0; i--) for (let i = this._menuStack.length - 1; i >= 0; i--)
this._menuStack[i].close(false); this._menuStack[i].close(BoxPointer.PopupAnimation.FADE);
oldMenu.close(false); oldMenu.close(BoxPointer.PopupAnimation.FADE);
newMenu.open(false); newMenu.open(BoxPointer.PopupAnimation.FADE);
} else } else
newMenu.open(true); newMenu.open(BoxPointer.PopupAnimation.FULL);
}, },
_onMenuSourceEnter: function(menu) { _onMenuSourceEnter: function(menu) {
@ -2313,6 +2313,6 @@ const PopupMenuManager = new Lang.Class({
_closeMenu: function() { _closeMenu: function() {
if (this._activeMenu != null) if (this._activeMenu != null)
this._activeMenu.close(true); this._activeMenu.close(BoxPointer.PopupAnimation.FULL);
} }
}); });

View File

@ -141,19 +141,6 @@ const SearchProvider = new Lang.Class({
throw new Error('Not implemented'); throw new Error('Not implemented');
}, },
/**
* createResultContainer:
*
* Search providers may optionally override this to render their
* results in a custom fashion. The default implementation
* will create a vertical list.
*
* Returns: An instance of SearchResultDisplay.
*/
createResultContainerActor: function() {
return null;
},
/** /**
* createResultActor: * createResultActor:
* @resultMeta: Object with result metadata * @resultMeta: Object with result metadata

View File

@ -275,10 +275,7 @@ const SearchResults = new Lang.Class({
x_fill: true, x_fill: true,
y_fill: true }); y_fill: true });
providerBox.add(resultDisplayBin, { expand: true }); providerBox.add(resultDisplayBin, { expand: true });
let resultDisplay = provider.createResultContainerActor(); let resultDisplay = new GridSearchResults(provider);
if (resultDisplay == null) {
resultDisplay = new GridSearchResults(provider);
}
resultDisplayBin.set_child(resultDisplay.actor); resultDisplayBin.set_child(resultDisplay.actor);
this._providerMeta.push({ provider: provider, this._providerMeta.push({ provider: provider,

View File

@ -18,17 +18,6 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="b" direction="out" name="success" /> <arg type="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" /> <arg type="s" direction="out" name="result" />
</method> </method>
<method name="ListExtensions">
<arg type="a{sa{sv}}" direction="out" name="extensions" />
</method>
<method name="GetExtensionInfo">
<arg type="s" direction="in" name="extension" />
<arg type="a{sv}" direction="out" name="info" />
</method>
<method name="GetExtensionErrors">
<arg type="s" direction="in" name="extension" />
<arg type="as" direction="out" name="errors" />
</method>
<method name="ScreenshotArea"> <method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/> <arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/> <arg type="i" direction="in" name="y"/>
@ -57,27 +46,8 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
<arg type="i" direction="in" name="width"/> <arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/> <arg type="i" direction="in" name="height"/>
</method> </method>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="ReloadExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<property name="OverviewActive" type="b" access="readwrite" /> <property name="OverviewActive" type="b" access="readwrite" />
<property name="ApiVersion" type="i" access="read" />
<property name="ShellVersion" type="s" access="read" /> <property name="ShellVersion" type="s" access="read" />
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
</interface>; </interface>;
const GnomeShell = new Lang.Class({ const GnomeShell = new Lang.Class({
@ -86,8 +56,8 @@ const GnomeShell = new Lang.Class({
_init: function() { _init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell'); this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
ExtensionSystem.connect('extension-state-changed',
Lang.bind(this, this._extensionStateChanged)); this._extensionsSerivce = new GnomeShellExtensions();
}, },
/** /**
@ -199,6 +169,67 @@ const GnomeShell = new Lang.Class({
flashspot.fire(); flashspot.fire();
}, },
get OverviewActive() {
return Main.overview.visible;
},
set OverviewActive(visible) {
if (visible)
Main.overview.show();
else
Main.overview.hide();
},
ShellVersion: Config.PACKAGE_VERSION
});
const GnomeShellExtensionsIface = <interface name="org.gnome.Shell.Extensions">
<method name="ListExtensions">
<arg type="a{sa{sv}}" direction="out" name="extensions" />
</method>
<method name="GetExtensionInfo">
<arg type="s" direction="in" name="extension" />
<arg type="a{sv}" direction="out" name="info" />
</method>
<method name="GetExtensionErrors">
<arg type="s" direction="in" name="extension" />
<arg type="as" direction="out" name="errors" />
</method>
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="out" name="result"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="LaunchExtensionPrefs">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="ReloadExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="CheckForUpdates">
</method>
<property name="ShellVersion" type="s" access="read" />
</interface>;
const GnomeShellExtensions = new Lang.Class({
Name: 'GnomeShellExtensionsDBus',
_init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellExtensionsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
ExtensionSystem.connect('extension-state-changed',
Lang.bind(this, this._extensionStateChanged));
},
ListExtensions: function() { ListExtensions: function() {
let out = {}; let out = {};
for (let uuid in ExtensionUtils.extensions) { for (let uuid in ExtensionUtils.extensions) {
@ -257,12 +288,12 @@ const GnomeShell = new Lang.Class({
return extension.errors; return extension.errors;
}, },
InstallRemoteExtension: function(uuid) { InstallRemoteExtensionAsync: function([uuid], invocation) {
ExtensionDownloader.installExtensionFromUUID(uuid); return ExtensionDownloader.installExtension(uuid, invocation);
}, },
UninstallExtension: function(uuid) { UninstallExtension: function(uuid) {
return ExtensionDownloader.uninstallExtensionFromUUID(uuid); return ExtensionDownloader.uninstallExtension(uuid);
}, },
LaunchExtensionPrefs: function(uuid) { LaunchExtensionPrefs: function(uuid) {
@ -277,15 +308,8 @@ const GnomeShell = new Lang.Class({
ExtensionSystem.loadExtension(uuid); ExtensionSystem.loadExtension(uuid);
}, },
get OverviewActive() { CheckForUpdates: function() {
return Main.overview.visible; ExtensionDownloader.checkForUpdates();
},
set OverviewActive(visible) {
if (visible)
Main.overview.show();
else
Main.overview.hide();
}, },
ShellVersion: Config.PACKAGE_VERSION, ShellVersion: Config.PACKAGE_VERSION,

View File

@ -117,6 +117,8 @@ const ShellMountOperation = new Lang.Class({
Lang.bind(this, this._onShowProcesses2)); Lang.bind(this, this._onShowProcesses2));
this.mountOp.connect('aborted', this.mountOp.connect('aborted',
Lang.bind(this, this.close)); Lang.bind(this, this.close));
this.mountOp.connect('show-unmount-progress',
Lang.bind(this, this._onShowUnmountProgress));
this._gicon = source.get_icon(); this._gicon = source.get_icon();
}, },
@ -178,6 +180,11 @@ const ShellMountOperation = new Lang.Class({
this._dialog.close(); this._dialog.close();
this._dialog = null; this._dialog = null;
} }
if (this._notifier) {
this._notifier.done();
this._notifier = null;
}
}, },
_onShowProcesses2: function(op) { _onShowProcesses2: function(op) {
@ -208,6 +215,16 @@ const ShellMountOperation = new Lang.Class({
this._processesDialog.update(message, processes, choices); this._processesDialog.update(message, processes, choices);
}, },
_onShowUnmountProgress: function(op, message, timeLeft, bytesLeft) {
if (!this._notifier)
this._notifier = new ShellUnmountNotifier();
if (bytesLeft == 0)
this._notifier.done(message);
else
this._notifier.show(message);
},
borrowDialog: function() { borrowDialog: function() {
if (this._dialogId != 0) { if (this._dialogId != 0) {
this._dialog.disconnect(this._dialogId); this._dialog.disconnect(this._dialogId);
@ -218,6 +235,46 @@ const ShellMountOperation = new Lang.Class({
} }
}); });
const ShellUnmountNotifier = new Lang.Class({
Name: 'ShellUnmountNotifier',
Extends: MessageTray.Source,
_init: function() {
this.parent('', 'media-removable', St.IconType.FULLCOLOR);
this._notification = null;
Main.messageTray.add(this);
},
show: function(message) {
let [header, text] = message.split('\n', 2);
if (!this._notification) {
this._notification = new MessageTray.Notification(this, header, text);
this._notification.setTransient(true);
this._notification.setUrgency(MessageTray.Urgency.CRITICAL);
} else {
this._notification.update(header, text);
}
this.notify(this._notification);
},
done: function(message) {
if (this._notification) {
this._notification.destroy();
this._notification = null;
}
if (message) {
let notification = new MessageTray.Notification(this, message, null);
notification.setTransient(true);
this.notify(notification);
}
}
});
const ShellMountQuestionDialog = new Lang.Class({ const ShellMountQuestionDialog = new Lang.Class({
Name: 'ShellMountQuestionDialog', Name: 'ShellMountQuestionDialog',
Extends: ModalDialog.ModalDialog, Extends: ModalDialog.ModalDialog,

View File

@ -6,9 +6,20 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const GnomeDesktop = imports.gi.GnomeDesktop; const GnomeDesktop = imports.gi.GnomeDesktop;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
try {
var IBus = imports.gi.IBus;
if (!('new_async' in IBus.Bus))
throw "IBus version is too old";
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
} catch (e) {
var IBus = null;
log(e);
}
const Main = imports.ui.main; const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
@ -19,6 +30,102 @@ const KEY_CURRENT_INPUT_SOURCE = 'current';
const KEY_INPUT_SOURCES = 'sources'; const KEY_INPUT_SOURCES = 'sources';
const INPUT_SOURCE_TYPE_XKB = 'xkb'; const INPUT_SOURCE_TYPE_XKB = 'xkb';
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
const IBusManager = new Lang.Class({
Name: 'IBusManager',
_init: function(readyCallback) {
if (!IBus)
return;
IBus.init();
this._readyCallback = readyCallback;
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._ibus = null;
this._panelService = null;
this._engines = {};
this._ready = false;
this._nameWatcherId = Gio.DBus.session.watch_name(IBus.SERVICE_IBUS,
Gio.BusNameWatcherFlags.NONE,
Lang.bind(this, this._onNameAppeared),
Lang.bind(this, this._clear));
},
_clear: function() {
if (this._panelService)
this._panelService.destroy();
if (this._ibus)
this._ibus.destroy();
this._ibus = null;
this._panelService = null;
this._candidatePopup.setPanelService(null);
this._engines = {};
this._ready = false;
},
_onNameAppeared: function() {
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
},
_onConnected: function() {
this._ibus.list_engines_async(-1, null, Lang.bind(this, this._initEngines));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
Lang.bind(this, this._initPanelService));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
},
_initEngines: function(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines[name] = enginesList[i];
}
} else {
this._clear();
return;
}
this._updateReadiness();
},
_initPanelService: function(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
this._candidatePopup.setPanelService(this._panelService);
} else {
this._clear();
return;
}
this._updateReadiness();
},
_updateReadiness: function() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
if (this._ready && this._readyCallback)
this._readyCallback();
},
getEngineDesc: function(id) {
if (!IBus || !this._ready)
return null;
return this._engines[id];
}
});
const LayoutMenuItem = new Lang.Class({ const LayoutMenuItem = new Lang.Class({
Name: 'LayoutMenuItem', Name: 'LayoutMenuItem',
@ -58,6 +165,8 @@ const InputSourceIndicator = new Lang.Class({
this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE); this._currentSourceIndex = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
this._xkbInfo = new GnomeDesktop.XkbInfo(); this._xkbInfo = new GnomeDesktop.XkbInfo();
this._ibusManager = new IBusManager(Lang.bind(this, this._inputSourcesChanged));
this._inputSourcesChanged(); this._inputSourcesChanged();
// re-using "allowSettings" for the keyboard layout is a bit shady, // re-using "allowSettings" for the keyboard layout is a bit shady,
@ -120,13 +229,20 @@ const InputSourceIndicator = new Lang.Class({
let infosByShortName = {}; let infosByShortName = {};
for (let i = 0; i < nSources; i++) { for (let i = 0; i < nSources; i++) {
let info = { exists: false };
let [type, id] = sources.get_child_value(i).deep_unpack(); let [type, id] = sources.get_child_value(i).deep_unpack();
if (type != INPUT_SOURCE_TYPE_XKB)
continue;
let info = {}; if (type == INPUT_SOURCE_TYPE_XKB) {
[info.exists, info.displayName, info.shortName, , ] = [info.exists, info.displayName, info.shortName, , ] =
this._xkbInfo.get_layout_info(id); this._xkbInfo.get_layout_info(id);
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
let engineDesc = this._ibusManager.getEngineDesc(id);
if (engineDesc) {
info.exists = true;
info.displayName = engineDesc.get_longname();
info.shortName = engineDesc.get_symbol();
}
}
if (!info.exists) if (!info.exists)
continue; continue;
@ -175,8 +291,19 @@ const InputSourceIndicator = new Lang.Class({
let sources = this._settings.get_value(KEY_INPUT_SOURCES); let sources = this._settings.get_value(KEY_INPUT_SOURCES);
let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE); let current = this._settings.get_uint(KEY_CURRENT_INPUT_SOURCE);
let id = sources.get_child_value(current).deep_unpack()[1]; let [type, id] = sources.get_child_value(current).deep_unpack();
let [, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id); let xkbLayout = '';
let xkbVariant = '';
if (type == INPUT_SOURCE_TYPE_XKB) {
[, , , xkbLayout, xkbVariant] = this._xkbInfo.get_layout_info(id);
} else if (type == INPUT_SOURCE_TYPE_IBUS) {
let engineDesc = this._ibusManager.getEngineDesc(id);
if (engineDesc) {
xkbLayout = engineDesc.get_layout();
xkbVariant = '';
}
}
if (!xkbLayout || xkbLayout.length == 0) if (!xkbLayout || xkbLayout.length == 0)
return; return;

View File

@ -20,7 +20,7 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'kbd-scrolllock': 'keyboard', 'kbd-scrolllock': 'keyboard',
'kbd-numlock': 'keyboard', 'kbd-numlock': 'keyboard',
'kbd-capslock': 'keyboard', 'kbd-capslock': 'keyboard',
'ibus-ui-gtk': 'input-method' 'ibus-ui-gtk': 'keyboard'
}; };
const StatusIconDispatcher = new Lang.Class({ const StatusIconDispatcher = new Lang.Class({

View File

@ -500,6 +500,37 @@ const ChatSource = new Lang.Class({
return this._iconBox; return this._iconBox;
}, },
createSecondaryIcon: function() {
let iconBox = new St.Bin();
iconBox.child = new St.Icon({ style_class: 'secondary-icon',
icon_type: St.IconType.FULLCOLOR });
let presenceType = this._contact.get_presence_type();
switch (presenceType) {
case Tp.ConnectionPresenceType.AVAILABLE:
iconBox.child.icon_name = 'user-available';
break;
case Tp.ConnectionPresenceType.BUSY:
iconBox.child.icon_name = 'user-busy';
break;
case Tp.ConnectionPresenceType.OFFLINE:
iconBox.child.icon_name = 'user-offline';
break;
case Tp.ConnectionPresenceType.HIDDEN:
iconBox.child.icon_name = 'user-invisible';
break;
case Tp.ConnectionPresenceType.AWAY:
iconBox.child.icon_name = 'user-away';
break;
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
iconBox.child.icon_name = 'user-idle';
break;
default:
iconBox.child.icon_name = 'user-offline';
}
return iconBox;
},
_updateAvatarIcon: function() { _updateAvatarIcon: function() {
this._setSummaryIcon(this.createNotificationIcon()); this._setSummaryIcon(this.createNotificationIcon());
this._notification.update(this._notification.title, null, { customContent: true, icon: this.createNotificationIcon() }); this._notification.update(this._notification.title, null, { customContent: true, icon: this.createNotificationIcon() });
@ -664,38 +695,14 @@ const ChatSource = new Lang.Class({
}, },
_presenceChanged: function (contact, presence, status, message) { _presenceChanged: function (contact, presence, status, message) {
let msg, shouldNotify, title; let msg, title;
if (this._presence == presence)
return;
title = GLib.markup_escape_text(this.title, -1); title = GLib.markup_escape_text(this.title, -1);
if (presence == Tp.ConnectionPresenceType.AVAILABLE) { this._notification.update(this._notification.title, null, { customContent: true, secondaryIcon: this.createSecondaryIcon() });
msg = _("%s is online.").format(title);
shouldNotify = (this._presence == Tp.ConnectionPresenceType.OFFLINE);
} else if (presence == Tp.ConnectionPresenceType.OFFLINE) {
presence = Tp.ConnectionPresenceType.OFFLINE;
msg = _("%s is offline.").format(title);
shouldNotify = (this._presence != Tp.ConnectionPresenceType.OFFLINE);
} else if (presence == Tp.ConnectionPresenceType.AWAY ||
presence == Tp.ConnectionPresenceType.EXTENDED_AWAY) {
msg = _("%s is away.").format(title);
shouldNotify = false;
} else if (presence == Tp.ConnectionPresenceType.BUSY) {
msg = _("%s is busy.").format(title);
shouldNotify = false;
} else
return;
this._presence = presence;
if (message) if (message)
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>'; msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
this._notification.appendPresence(msg, shouldNotify);
if (shouldNotify)
this.notify();
}, },
_pendingRemoved: function(channel, message) { _pendingRemoved: function(channel, message) {
@ -722,7 +729,7 @@ const ChatNotification = new Lang.Class({
Extends: MessageTray.Notification, Extends: MessageTray.Notification,
_init: function(source) { _init: function(source) {
this.parent(source, source.title, null, { customContent: true }); this.parent(source, source.title, null, { customContent: true, secondaryIcon: source.createSecondaryIcon() });
this.setResident(true); this.setResident(true);
this._responseEntry = new St.Entry({ style_class: 'chat-response', this._responseEntry = new St.Entry({ style_class: 'chat-response',
@ -932,19 +939,6 @@ const ChatNotification = new Lang.Class({
return false; return false;
}, },
appendPresence: function(text, asTitle) {
if (asTitle)
this.update(text, null, { customContent: true, titleMarkup: true });
else
this.update(this.source.title, null, { customContent: true });
let label = this._append({ body: text,
group: 'meta',
styles: ['chat-meta-message'] });
this._filterMessages();
},
appendAliasChange: function(oldAlias, newAlias) { appendAliasChange: function(oldAlias, newAlias) {
oldAlias = GLib.markup_escape_text(oldAlias, -1); oldAlias = GLib.markup_escape_text(oldAlias, -1);
newAlias = GLib.markup_escape_text(newAlias, -1); newAlias = GLib.markup_escape_text(newAlias, -1);

View File

@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService; const AccountsService = imports.gi.AccountsService;
const GdmGreeter = imports.gi.GdmGreeter; const Gdm = imports.gi.Gdm;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Lang = imports.lang; const Lang = imports.lang;
@ -481,10 +481,8 @@ const UserMenuButton = new Lang.Class({
Lang.bind(this, this._updatePresenceIcon)); Lang.bind(this, this._updatePresenceIcon));
this._accountMgr.connect('account-enabled', this._accountMgr.connect('account-enabled',
Lang.bind(this, this._onAccountEnabled)); Lang.bind(this, this._onAccountEnabled));
this._accountMgr.connect('account-disabled',
Lang.bind(this, this._onAccountDisabled));
this._accountMgr.connect('account-removed', this._accountMgr.connect('account-removed',
Lang.bind(this, this._onAccountDisabled)); Lang.bind(this, this._onAccountRemoved));
this._accountMgr.prepare_async(null, Lang.bind(this, this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) { function(mgr) {
let [presence, s, msg] = mgr.get_most_available_presence(); let [presence, s, msg] = mgr.get_most_available_presence();
@ -525,6 +523,10 @@ const UserMenuButton = new Lang.Class({
this._updateLogout(); this._updateLogout();
this._updateLockScreen(); this._updateLockScreen();
this._updatesFile = Gio.File.new_for_path('/var/lib/PackageKit/prepared-update');
this._updatesMonitor = this._updatesFile.monitor(Gio.FileMonitorFlags.NONE, null);
this._updatesMonitor.connect('changed', Lang.bind(this, this._updateInstallUpdates));
// Whether shutdown is available or not depends on both lockdown // Whether shutdown is available or not depends on both lockdown
// settings (disable-log-out) and Polkit policy - the latter doesn't // settings (disable-log-out) and Polkit policy - the latter doesn't
// notify, so we update the menu item each time the menu opens or // notify, so we update the menu item each time the menu opens or
@ -560,7 +562,7 @@ const UserMenuButton = new Lang.Class({
_updateSwitchUser: function() { _updateSwitchUser: function() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY); let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
let multiUser = this._userManager.can_switch() && this._userManager.has_multiple_users; let multiUser = this._userManager.can_switch() && this._userManager.has_multiple_users;
let multiSession = GdmGreeter.get_session_ids().length > 1; let multiSession = Gdm.get_session_ids().length > 1;
this._loginScreenItem.label.set_text(multiUser ? _("Switch User") this._loginScreenItem.label.set_text(multiUser ? _("Switch User")
: _("Switch Session")); : _("Switch Session"));
@ -570,7 +572,7 @@ const UserMenuButton = new Lang.Class({
_updateLogout: function() { _updateLogout: function() {
let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY); let allowLogout = !this._lockdownSettings.get_boolean(DISABLE_LOG_OUT_KEY);
let multiUser = this._userManager.has_multiple_users; let multiUser = this._userManager.has_multiple_users;
let multiSession = GdmGreeter.get_session_ids().length > 1; let multiSession = Gdm.get_session_ids().length > 1;
this._logoutItem.actor.visible = allowLogout && (multiUser || multiSession); this._logoutItem.actor.visible = allowLogout && (multiUser || multiSession);
}, },
@ -580,11 +582,17 @@ const UserMenuButton = new Lang.Class({
this._lockScreenItem.actor.visible = allowLockScreen; this._lockScreenItem.actor.visible = allowLockScreen;
}, },
_updateInstallUpdates: function() {
let haveUpdates = this._updatesFile.query_exists(null);
this._installUpdatesItem.actor.visible = haveUpdates && this._haveShutdown;
},
_updateHaveShutdown: function() { _updateHaveShutdown: function() {
this._session.CanShutdownRemote(Lang.bind(this, this._session.CanShutdownRemote(Lang.bind(this,
function(result, error) { function(result, error) {
if (!error) { if (!error) {
this._haveShutdown = result; this._haveShutdown = result[0];
this._updateInstallUpdates();
this._updateSuspendOrPowerOff(); this._updateSuspendOrPowerOff();
} }
})); }));
@ -645,7 +653,7 @@ const UserMenuButton = new Lang.Class({
this._updateChangingPresence(); this._updateChangingPresence();
}, },
_onAccountDisabled: function(accountMgr, account) { _onAccountRemoved: function(accountMgr, account) {
account.disconnect(account._changingId); account.disconnect(account._changingId);
account._changingId = 0; account._changingId = 0;
this._updateChangingPresence(); this._updateChangingPresence();
@ -692,13 +700,6 @@ const UserMenuButton = new Lang.Class({
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
} }
item = new PopupMenu.PopupAlternatingMenuItem(_("Power Off"),
_("Suspend"));
this.menu.addMenuItem(item);
item.connect('activate', Lang.bind(this, this._onSuspendOrPowerOffActivate));
this._suspendOrPowerOffItem = item;
this._updateSuspendOrPowerOff();
item = new PopupMenu.PopupSeparatorMenuItem(); item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
@ -712,13 +713,25 @@ const UserMenuButton = new Lang.Class({
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
this._logoutItem = item; this._logoutItem = item;
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
item = new PopupMenu.PopupMenuItem(_("Lock")); item = new PopupMenu.PopupMenuItem(_("Lock"));
item.connect('activate', Lang.bind(this, this._onLockScreenActivate)); item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
this._lockScreenItem = item; this._lockScreenItem = item;
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
item = new PopupMenu.PopupAlternatingMenuItem(_("Power Off"),
_("Suspend"));
this.menu.addMenuItem(item);
item.connect('activate', Lang.bind(this, this._onSuspendOrPowerOffActivate));
this._suspendOrPowerOffItem = item;
this._updateSuspendOrPowerOff();
item = new PopupMenu.PopupMenuItem(_("Install Updates & Restart"));
item.connect('activate', Lang.bind(this, this._onInstallUpdatesActivate));
this.menu.addMenuItem(item);
this._installUpdatesItem = item;
}, },
_updatePresenceStatus: function(item, event) { _updatePresenceStatus: function(item, event) {
@ -771,6 +784,13 @@ const UserMenuButton = new Lang.Class({
this._session.LogoutRemote(0); this._session.LogoutRemote(0);
}, },
_onInstallUpdatesActivate: function() {
Main.overview.hide();
Util.spawn(['pkexec', '/usr/libexec/pk-trigger-offline-update']);
this._session.RebootRemote();
},
_onSuspendOrPowerOffActivate: function() { _onSuspendOrPowerOffActivate: function() {
Main.overview.hide(); Main.overview.hide();

View File

@ -15,65 +15,38 @@ const Tweener = imports.ui.tweener;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
const WINDOW_ANIMATION_TIME = 0.25; const WINDOW_ANIMATION_TIME = 0.25;
const DIM_DESATURATION = 0.6;
const DIM_BRIGHTNESS = -0.1;
const DIM_TIME = 0.500; const DIM_TIME = 0.500;
const UNDIM_TIME = 0.250; const UNDIM_TIME = 0.250;
var dimShader = undefined;
function getDimShaderSource() {
if (!dimShader)
dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
return dimShader;
}
function getTopInvisibleBorder(metaWindow) {
let outerRect = metaWindow.get_outer_rect();
let inputRect = metaWindow.get_input_rect();
return outerRect.y - inputRect.y;
}
const WindowDimmer = new Lang.Class({ const WindowDimmer = new Lang.Class({
Name: 'WindowDimmer', Name: 'WindowDimmer',
_init: function(actor) { _init: function(actor) {
if (Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL)) { this._desaturateEffect = new Clutter.DesaturateEffect();
this._effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER }); this._brightnessEffect = new Clutter.BrightnessContrastEffect();
this._effect.set_shader_source(getDimShaderSource()); actor.add_effect(this._desaturateEffect);
} else { actor.add_effect(this._brightnessEffect);
this._effect = null;
}
this.actor = actor; this.actor = actor;
this._dimFactor = 0.0;
}, },
set dimFraction(fraction) { setEnabled: function(enabled) {
this._dimFraction = fraction; this._desaturateEffect.enabled = enabled;
this._brightnessEffect.enabled = enabled;
if (this._effect == null)
return;
if (!Meta.prefs_get_attach_modal_dialogs()) {
this._effect.enabled = false;
return;
}
if (fraction > 0.01) {
Shell.shader_effect_set_double_uniform(this._effect, 'height', this.actor.get_height());
Shell.shader_effect_set_double_uniform(this._effect, 'fraction', fraction);
if (!this._effect.actor)
this.actor.add_effect(this._effect);
} else {
if (this._effect.actor)
this.actor.remove_effect(this._effect);
}
}, },
get dimFraction() { set dimFactor(factor) {
return this._dimFraction; this._dimFactor = factor;
this._desaturateEffect.set_factor(factor * DIM_DESATURATION);
this._brightnessEffect.set_brightness(factor * DIM_BRIGHTNESS);
}, },
_dimFraction: 0.0 get dimFactor() {
return this._dimFactor;
}
}); });
function getWindowDimmer(actor) { function getWindowDimmer(actor) {
@ -94,6 +67,7 @@ const WindowManager = new Lang.Class({
this._unmaximizing = []; this._unmaximizing = [];
this._mapping = []; this._mapping = [];
this._destroying = []; this._destroying = [];
this._movingWindow = null;
this._dimmedWindows = []; this._dimmedWindows = [];
@ -125,6 +99,14 @@ const WindowManager = new Lang.Class({
Lang.bind(this, this._showWorkspaceSwitcher)); Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-down', Meta.keybindings_set_custom_handler('switch-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher)); Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-left',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-right',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-up',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('move-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-windows', Meta.keybindings_set_custom_handler('switch-windows',
Lang.bind(this, this._startAppSwitcher)); Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group', Meta.keybindings_set_custom_handler('switch-group',
@ -142,11 +124,11 @@ const WindowManager = new Lang.Class({
Main.overview.connect('showing', Lang.bind(this, function() { Main.overview.connect('showing', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++) for (let i = 0; i < this._dimmedWindows.length; i++)
this._undimWindow(this._dimmedWindows[i], true); this._undimWindow(this._dimmedWindows[i]);
})); }));
Main.overview.connect('hiding', Lang.bind(this, function() { Main.overview.connect('hiding', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++) for (let i = 0; i < this._dimmedWindows.length; i++)
this._dimWindow(this._dimmedWindows[i], true); this._dimWindow(this._dimmedWindows[i]);
})); }));
}, },
@ -158,12 +140,14 @@ const WindowManager = new Lang.Class({
this._animationBlockCount = Math.max(0, this._animationBlockCount - 1); this._animationBlockCount = Math.max(0, this._animationBlockCount - 1);
}, },
_shouldAnimate : function(actor) { _shouldAnimate: function() {
if (Main.overview.visible || this._animationBlockCount > 0) return !(Main.overview.visible || this._animationBlockCount > 0);
},
_shouldAnimateActor: function(actor) {
if (!this._shouldAnimate())
return false; return false;
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL)) return actor.meta_window.get_window_type() == Meta.WindowType.NORMAL;
return false;
return true;
}, },
_removeEffect : function(list, actor) { _removeEffect : function(list, actor) {
@ -176,7 +160,7 @@ const WindowManager = new Lang.Class({
}, },
_minimizeWindow : function(shellwm, actor) { _minimizeWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) { if (!this._shouldAnimateActor(actor)) {
shellwm.completed_minimize(actor); shellwm.completed_minimize(actor);
return; return;
} }
@ -260,43 +244,47 @@ const WindowManager = new Lang.Class({
window._dimmed = true; window._dimmed = true;
this._dimmedWindows.push(window); this._dimmedWindows.push(window);
if (!Main.overview.visible) if (!Main.overview.visible)
this._dimWindow(window, true); this._dimWindow(window);
} else if (!shouldDim && window._dimmed) { } else if (!shouldDim && window._dimmed) {
window._dimmed = false; window._dimmed = false;
this._dimmedWindows = this._dimmedWindows.filter(function(win) { this._dimmedWindows = this._dimmedWindows.filter(function(win) {
return win != window; return win != window;
}); });
if (!Main.overview.visible) if (!Main.overview.visible)
this._undimWindow(window, true); this._undimWindow(window);
} }
}, },
_dimWindow: function(window, animate) { _dimWindow: function(window) {
let actor = window.get_compositor_private(); let actor = window.get_compositor_private();
if (!actor) if (!actor)
return; return;
if (animate) let dimmer = getWindowDimmer(actor);
Tweener.addTween(getWindowDimmer(actor), let enabled = Meta.prefs_get_attach_modal_dialogs();
{ dimFraction: 1.0, dimmer.setEnabled(enabled);
time: DIM_TIME, if (!enabled)
transition: 'linear' return;
}); Tweener.addTween(dimmer,
else { dimFactor: 1.0,
getWindowDimmer(actor).dimFraction = 1.0; time: DIM_TIME,
transition: 'linear'
});
}, },
_undimWindow: function(window, animate) { _undimWindow: function(window) {
let actor = window.get_compositor_private(); let actor = window.get_compositor_private();
if (!actor) if (!actor)
return; return;
if (animate) let dimmer = getWindowDimmer(actor);
Tweener.addTween(getWindowDimmer(actor), let enabled = Meta.prefs_get_attach_modal_dialogs();
{ dimFraction: 0.0, dimmer.setEnabled(enabled);
time: UNDIM_TIME, if (!enabled)
transition: 'linear' return;
}); Tweener.addTween(dimmer,
else { dimFactor: 0.0,
getWindowDimmer(actor).dimFraction = 0.0; time: UNDIM_TIME,
transition: 'linear'
});
}, },
_mapWindow : function(shellwm, actor) { _mapWindow : function(shellwm, actor) {
@ -316,28 +304,12 @@ const WindowManager = new Lang.Class({
})); }));
if (actor.meta_window.is_attached_dialog()) { if (actor.meta_window.is_attached_dialog()) {
this._checkDimming(actor.get_meta_window().get_transient_for()); this._checkDimming(actor.get_meta_window().get_transient_for());
if (this._shouldAnimate()) {
actor.set_scale(1.0, 0.0);
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor, if (!this._shouldAnimate()) {
{ scale_y: 1, shellwm.completed_map(actor);
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
return; return;
} }
shellwm.completed_map(actor); } else if (!this._shouldAnimateActor(actor)) {
return;
}
if (!this._shouldAnimate(actor)) {
shellwm.completed_map(actor); shellwm.completed_map(actor);
return; return;
} }
@ -393,7 +365,7 @@ const WindowManager = new Lang.Class({
return; return;
} }
actor.set_scale(1.0, 1.0); actor.opacity = 255;
actor.show(); actor.show();
this._destroying.push(actor); this._destroying.push(actor);
@ -403,7 +375,7 @@ const WindowManager = new Lang.Class({
})); }));
Tweener.addTween(actor, Tweener.addTween(actor,
{ scale_y: 0, { opacity: 0,
time: WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad", transition: "easeOutQuad",
onComplete: this._destroyWindowDone, onComplete: this._destroyWindowDone,
@ -465,11 +437,13 @@ const WindowManager = new Lang.Class({
this._switchData = switchData; this._switchData = switchData;
switchData.inGroup = new Clutter.Group(); switchData.inGroup = new Clutter.Group();
switchData.outGroup = new Clutter.Group(); switchData.outGroup = new Clutter.Group();
switchData.movingWindowBin = new Clutter.Group();
switchData.windows = []; switchData.windows = [];
let wgroup = global.window_group; let wgroup = global.window_group;
wgroup.add_actor(switchData.inGroup); wgroup.add_actor(switchData.inGroup);
wgroup.add_actor(switchData.outGroup); wgroup.add_actor(switchData.outGroup);
wgroup.add_actor(switchData.movingWindowBin);
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let window = windows[i]; let window = windows[i];
@ -477,7 +451,12 @@ const WindowManager = new Lang.Class({
if (!window.meta_window.showing_on_its_workspace()) if (!window.meta_window.showing_on_its_workspace())
continue; continue;
if (window.get_workspace() == from) { if (this._movingWindow && window.meta_window == this._movingWindow) {
switchData.movingWindow = { window: window,
parent: window.get_parent() };
switchData.windows.push(switchData.movingWindow);
window.reparent(switchData.movingWindowBin);
} else if (window.get_workspace() == from) {
switchData.windows.push({ window: window, switchData.windows.push({ window: window,
parent: window.get_parent() }); parent: window.get_parent() });
window.reparent(switchData.outGroup); window.reparent(switchData.outGroup);
@ -492,6 +471,8 @@ const WindowManager = new Lang.Class({
switchData.inGroup.set_position(-xDest, -yDest); switchData.inGroup.set_position(-xDest, -yDest);
switchData.inGroup.raise_top(); switchData.inGroup.raise_top();
switchData.movingWindowBin.raise_top();
Tweener.addTween(switchData.outGroup, Tweener.addTween(switchData.outGroup,
{ x: xDest, { x: xDest,
y: yDest, y: yDest,
@ -529,6 +510,10 @@ const WindowManager = new Lang.Class({
Tweener.removeTweens(switchData.outGroup); Tweener.removeTweens(switchData.outGroup);
switchData.inGroup.destroy(); switchData.inGroup.destroy();
switchData.outGroup.destroy(); switchData.outGroup.destroy();
switchData.movingWindowBin.destroy();
if (this._movingWindow)
this._movingWindow = null;
shellwm.completed_switch_workspace(); shellwm.completed_switch_workspace();
}, },
@ -536,7 +521,7 @@ const WindowManager = new Lang.Class({
_startAppSwitcher : function(display, screen, window, binding) { _startAppSwitcher : function(display, screen, window, binding) {
/* prevent a corner case where both popups show up at once */ /* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null) if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide(); this._workspaceSwitcherPopup.destroy();
let tabPopup = new AltTab.AltTabPopup(); let tabPopup = new AltTab.AltTabPopup();
@ -560,76 +545,56 @@ const WindowManager = new Lang.Class({
if (screen.n_workspaces == 1) if (screen.n_workspaces == 1)
return; return;
if (this._workspaceSwitcherPopup == null) let [action,,,direction] = binding.get_name().split('-');
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); let direction = Meta.MotionDirection[direction.toUpperCase()];
let newWs;
if (binding.get_name() == 'switch-to-workspace-up')
this.actionMoveWorkspaceUp(); if (direction != Meta.MotionDirection.UP &&
else if (binding.get_name() == 'switch-to-workspace-down') direction != Meta.MotionDirection.DOWN)
this.actionMoveWorkspaceDown(); return;
// left/right would effectively act as synonyms for up/down if we enabled them;
// but that could be considered confusing. if (action == 'switch')
// else if (binding.get_name() == 'switch-to-workspace-left') newWs = this.actionMoveWorkspace(direction);
// this.actionMoveWorkspaceLeft(); else
// else if (binding.get_name() == 'switch-to-workspace-right') newWs = this.actionMoveWindow(window, direction);
// this.actionMoveWorkspaceRight();
if (!Main.overview.visible) {
if (this._workspaceSwitcherPopup == null) {
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
this._workspaceSwitcherPopup.connect('destroy', Lang.bind(this, function() {
this._workspaceSwitcherPopup = null;
}));
}
this._workspaceSwitcherPopup.display(direction, newWs.index());
}
}, },
actionMoveWorkspaceLeft: function() { actionMoveWorkspace: function(direction) {
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); let activeWorkspace = global.screen.get_active_workspace();
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let toActivate = activeWorkspace.get_neighbor(direction);
let indexToActivate = activeWorkspaceIndex;
if (rtl && activeWorkspaceIndex < global.screen.n_workspaces - 1)
indexToActivate++;
else if (!rtl && activeWorkspaceIndex > 0)
indexToActivate--;
if (indexToActivate != activeWorkspaceIndex) if (activeWorkspace != toActivate)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time()); toActivate.activate(global.get_current_time());
if (!Main.overview.visible) return toActivate;
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.UP, indexToActivate);
}, },
actionMoveWorkspaceRight: function() { actionMoveWindow: function(window, direction) {
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL); let activeWorkspace = global.screen.get_active_workspace();
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let toActivate = activeWorkspace.get_neighbor(direction);
let indexToActivate = activeWorkspaceIndex;
if (rtl && activeWorkspaceIndex > 0)
indexToActivate--;
else if (!rtl && activeWorkspaceIndex < global.screen.n_workspaces - 1)
indexToActivate++;
if (indexToActivate != activeWorkspaceIndex) if (activeWorkspace != toActivate) {
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time()); // This won't have any effect for "always sticky" windows
// (like desktop windows or docks)
if (!Main.overview.visible) this._movingWindow = window;
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate); window.change_workspace(toActivate);
global.display.clear_mouse_mode();
toActivate.activate_with_focus (window, global.get_current_time());
}
return toActivate;
}, },
actionMoveWorkspaceUp: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let indexToActivate = activeWorkspaceIndex;
if (activeWorkspaceIndex > 0)
indexToActivate--;
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.UP, indexToActivate);
},
actionMoveWorkspaceDown: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let indexToActivate = activeWorkspaceIndex;
if (activeWorkspaceIndex < global.screen.n_workspaces - 1)
indexToActivate++;
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
}
}); });

View File

@ -3,18 +3,17 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St; const St = imports.gi.St;
const Main = imports.ui.main;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const ANIMATION_TIME = 0.1; const ANIMATION_TIME = 0.1;
const DISPLAY_TIMEOUT = 600; const DISPLAY_TIMEOUT = 600;
const UP = -1;
const DOWN = 1;
const WorkspaceSwitcherPopup = new Lang.Class({ const WorkspaceSwitcherPopup = new Lang.Class({
Name: 'WorkspaceSwitcherPopup', Name: 'WorkspaceSwitcherPopup',
@ -43,12 +42,14 @@ const WorkspaceSwitcherPopup = new Lang.Class({
this.actor.add_actor(this._container); this.actor.add_actor(this._container);
this._redraw(); this._redisplay();
this._position();
this.actor.hide(); this.actor.hide();
this._globalSignals = [];
this._globalSignals.push(global.screen.connect('workspace-added', Lang.bind(this, this._redisplay)));
this._globalSignals.push(global.screen.connect('workspace-removed', Lang.bind(this, this._redisplay)));
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
}, },
@ -104,15 +105,15 @@ const WorkspaceSwitcherPopup = new Lang.Class({
} }
}, },
_redraw : function(direction, activeWorkspaceIndex) { _redisplay: function() {
this._list.destroy_all_children(); this._list.destroy_all_children();
for (let i = 0; i < global.screen.n_workspaces; i++) { for (let i = 0; i < global.screen.n_workspaces; i++) {
let indicator = null; let indicator = null;
if (i == activeWorkspaceIndex && direction == UP) if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP)
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-up' });
else if(i == activeWorkspaceIndex && direction == DOWN) else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN)
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-down' });
else else
indicator = new St.Bin({ style_class: 'ws-switcher-box' }); indicator = new St.Bin({ style_class: 'ws-switcher-box' });
@ -120,13 +121,13 @@ const WorkspaceSwitcherPopup = new Lang.Class({
this._list.add_actor(indicator); this._list.add_actor(indicator);
} }
},
_position: function() {
let primary = Main.layoutManager.primaryMonitor; let primary = Main.layoutManager.primaryMonitor;
this._container.x = primary.x + Math.floor((primary.width - this._container.width) / 2); let [containerMinHeight, containerNatHeight] = this._container.get_preferred_height(global.screen_width);
let [containerMinWidth, containerNatWidth] = this._container.get_preferred_width(containerNatHeight);
this._container.x = primary.x + Math.floor((primary.width - containerNatWidth) / 2);
this._container.y = primary.y + Main.panel.actor.height + this._container.y = primary.y + Main.panel.actor.height +
Math.floor(((primary.height - Main.panel.actor.height) - this._container.height) / 2); Math.floor(((primary.height - Main.panel.actor.height) - containerNatHeight) / 2);
}, },
_show : function() { _show : function() {
@ -134,12 +135,14 @@ const WorkspaceSwitcherPopup = new Lang.Class({
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
this._position();
this.actor.show(); this.actor.show();
}, },
display : function(direction, activeWorkspaceIndex) { display : function(direction, activeWorkspaceIndex) {
this._redraw(direction, activeWorkspaceIndex); this._direction = direction;
this._activeWorkspaceIndex = activeWorkspaceIndex;
this._redisplay();
if (this._timeoutId != 0) if (this._timeoutId != 0)
Mainloop.source_remove(this._timeoutId); Mainloop.source_remove(this._timeoutId);
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout)); this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
@ -152,8 +155,22 @@ const WorkspaceSwitcherPopup = new Lang.Class({
Tweener.addTween(this._container, { opacity: 0.0, Tweener.addTween(this._container, { opacity: 0.0,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: function() { this.actor.hide(); }, onComplete: function() { this.destroy(); },
onCompleteScope: this onCompleteScope: this
}); });
},
destroy: function() {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
for (let i = 0; i < this._globalSignals.length; i++)
global.screen.disconnect(this._globalSignals[i]);
this.actor.destroy();
this.emit('destroy');
} }
}); });
Signals.addSignalMethods(WorkspaceSwitcherPopup.prototype);

View File

@ -1048,10 +1048,10 @@ const WorkspacesDisplay = new Lang.Class({
_onScrollEvent: function (actor, event) { _onScrollEvent: function (actor, event) {
switch ( event.get_scroll_direction() ) { switch ( event.get_scroll_direction() ) {
case Clutter.ScrollDirection.UP: case Clutter.ScrollDirection.UP:
Main.wm.actionMoveWorkspaceUp(); Main.wm.actionMoveWorkspace(Meta.MotionDirection.UP);
break; break;
case Clutter.ScrollDirection.DOWN: case Clutter.ScrollDirection.DOWN:
Main.wm.actionMoveWorkspaceDown(); Main.wm.actionMoveWorkspace(Meta.MotionDirection.DOWN);
break; break;
} }
} }

View File

@ -9,7 +9,6 @@ js/ui/appDisplay.js
js/ui/appFavorites.js js/ui/appFavorites.js
js/ui/autorunManager.js js/ui/autorunManager.js
js/ui/calendar.js js/ui/calendar.js
js/ui/contactDisplay.js
js/ui/dash.js js/ui/dash.js
js/ui/dateMenu.js js/ui/dateMenu.js
js/ui/endSessionDialog.js js/ui/endSessionDialog.js
@ -42,6 +41,7 @@ js/ui/userMenu.js
js/ui/viewSelector.js js/ui/viewSelector.js
js/ui/wanda.js js/ui/wanda.js
js/ui/windowAttentionHandler.js js/ui/windowAttentionHandler.js
src/calendar-server/evolution-calendar.desktop.in.in
src/gvc/gvc-mixer-control.c src/gvc/gvc-mixer-control.c
src/main.c src/main.c
src/shell-app.c src/shell-app.c

View File

@ -1,3 +1,4 @@
data/gnome-shell.desktop.in data/gnome-shell.desktop.in
data/gnome-shell-extension-prefs.desktop.in data/gnome-shell-extension-prefs.desktop.in
data/org.gnome.shell.evolution.calendar.gschema.xml.in data/org.gnome.shell.evolution.calendar.gschema.xml.in
src/calendar-server/evolution-calendar.desktop.in

542
po/ar.po

File diff suppressed because it is too large Load Diff

872
po/as.po

File diff suppressed because it is too large Load Diff

692
po/be.po

File diff suppressed because it is too large Load Diff

678
po/bg.po

File diff suppressed because it is too large Load Diff

424
po/es.po
View File

@ -10,14 +10,15 @@ msgstr ""
"Project-Id-Version: gnome-shell.master\n" "Project-Id-Version: gnome-shell.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n" "shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-06-21 04:16+0000\n" "POT-Creation-Date: 2012-07-07 16:23+0000\n"
"PO-Revision-Date: 2012-06-21 12:18+0200\n" "PO-Revision-Date: 2012-07-16 16:08+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n" "Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: Español <gnome-es-list@gnome.org>\n" "Language-Team: Español <gnome-es-list@gnome.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Gtranslator 2.91.4\n" "X-Generator: Gtranslator 2.91.4\n"
#: ../data/gnome-shell.desktop.in.in.h:1 #: ../data/gnome-shell.desktop.in.in.h:1
@ -158,26 +159,10 @@ msgid "The type of keyboard to use."
msgstr "El tipo de teclado que usar." msgstr "El tipo de teclado que usar."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "Show time with seconds"
msgstr "Mostrar la hora con segundos"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "If true, display seconds in time."
msgstr "Si es cierta, muestra los segundos en la hora."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "Show date in clock"
msgstr "Mostrar la fecha en el reloj"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "If true, display date in the clock, in addition to time."
msgstr "Si es cierta, muestra la fecha en el reloj, además de la hora."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "Tasa de fotogramas usada para grabar «screencast»." msgstr "Tasa de fotogramas usada para grabar «screencast»."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@ -185,11 +170,11 @@ msgstr ""
"La tasa de fotogramas de la grabación resultante grabada por el grabador de " "La tasa de fotogramas de la grabación resultante grabada por el grabador de "
"«screencast» de GNOME Shell, en fotogramas por segundo." "«screencast» de GNOME Shell, en fotogramas por segundo."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28 #: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "La tubería de gstreamer usada para codificar el «screencast»" msgstr "La tubería de gstreamer usada para codificar el «screencast»"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30 #: ../data/org.gnome.shell.gschema.xml.in.in.h:26
#, no-c-format #, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
@ -215,11 +200,11 @@ msgstr ""
"usando el códec VP8. Se usa %T como marcador de posición para el número de " "usando el códec VP8. Se usa %T como marcador de posición para el número de "
"hilos óptimos en el sistema." "hilos óptimos en el sistema."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31 #: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "Extensión de archivo que usar para almacenar los «screencast»" msgstr "Extensión de archivo que usar para almacenar los «screencast»"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32 #: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@ -243,46 +228,46 @@ msgid "Select an extension to configure using the combobox above."
msgstr "" msgstr ""
"Seleccione una extensión que configurar usando la caja combinada de arriba." "Seleccione una extensión que configurar usando la caja combinada de arriba."
#: ../js/gdm/loginDialog.js:627 #: ../js/gdm/loginDialog.js:629
msgid "Session..." msgid "Session..."
msgstr "Sesión…" msgstr "Sesión…"
#: ../js/gdm/loginDialog.js:789 #: ../js/gdm/loginDialog.js:800
msgctxt "title" msgctxt "title"
msgid "Sign In" msgid "Sign In"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:834 #: ../js/gdm/loginDialog.js:845
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(o pase el dedo)" msgstr "(o pase el dedo)"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: ../js/gdm/loginDialog.js:855 #: ../js/gdm/loginDialog.js:866
msgid "Not listed?" msgid "Not listed?"
msgstr "¿No está en la lista?" msgstr "¿No está en la lista?"
#: ../js/gdm/loginDialog.js:1023 ../js/ui/endSessionDialog.js:410 #: ../js/gdm/loginDialog.js:1046 ../js/ui/endSessionDialog.js:410
#: ../js/ui/extensionDownloader.js:108 ../js/ui/networkAgent.js:153 #: ../js/ui/extensionDownloader.js:138 ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:176 #: ../js/ui/polkitAuthenticationAgent.js:176
#: ../js/ui/shellMountOperation.js:334 ../js/ui/status/bluetooth.js:431 #: ../js/ui/shellMountOperation.js:339 ../js/ui/status/bluetooth.js:431
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: ../js/gdm/loginDialog.js:1028 #: ../js/gdm/loginDialog.js:1051
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: ../js/gdm/loginDialog.js:1380 #: ../js/gdm/loginDialog.js:1411
msgid "Login Window" msgid "Login Window"
msgstr "Ventana de inicio de sesión" msgstr "Ventana de inicio de sesión"
#: ../js/gdm/powerMenu.js:130 ../js/ui/userMenu.js:604 #: ../js/gdm/powerMenu.js:130 ../js/ui/userMenu.js:612
#: ../js/ui/userMenu.js:608 ../js/ui/userMenu.js:696 #: ../js/ui/userMenu.js:616 ../js/ui/userMenu.js:730
msgid "Suspend" msgid "Suspend"
msgstr "Suspender" msgstr "Suspender"
@ -290,48 +275,48 @@ msgstr "Suspender"
msgid "Restart" msgid "Restart"
msgstr "Reiniciar" msgstr "Reiniciar"
#: ../js/gdm/powerMenu.js:140 ../js/ui/userMenu.js:606 #: ../js/gdm/powerMenu.js:140 ../js/ui/userMenu.js:614
#: ../js/ui/userMenu.js:608 ../js/ui/userMenu.js:695 #: ../js/ui/userMenu.js:616 ../js/ui/userMenu.js:729
msgid "Power Off" msgid "Power Off"
msgstr "Apagar" msgstr "Apagar"
#: ../js/misc/util.js:93 #: ../js/misc/util.js:95
msgid "Command not found" msgid "Command not found"
msgstr "Comando no encontrado" msgstr "Comando no encontrado"
#. Replace "Error invoking GLib.shell_parse_argv: " with #. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer #. something nicer
#: ../js/misc/util.js:124 #: ../js/misc/util.js:128
msgid "Could not parse command:" msgid "Could not parse command:"
msgstr "No se pudo analizar el comando:" msgstr "No se pudo analizar el comando:"
#: ../js/misc/util.js:132 #: ../js/misc/util.js:136
#, c-format #, c-format
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "Falló la ejecución de «%s»:" msgstr "Falló la ejecución de «%s»:"
#. Translators: Filter to display all applications #. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:251 #: ../js/ui/appDisplay.js:252
msgid "All" msgid "All"
msgstr "Todas" msgstr "Todas"
#: ../js/ui/appDisplay.js:309 #: ../js/ui/appDisplay.js:310
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "APLICACIONES" msgstr "APLICACIONES"
#: ../js/ui/appDisplay.js:369 #: ../js/ui/appDisplay.js:370
msgid "SETTINGS" msgid "SETTINGS"
msgstr "CONFIGURACIÓN" msgstr "CONFIGURACIÓN"
#: ../js/ui/appDisplay.js:674 #: ../js/ui/appDisplay.js:675
msgid "New Window" msgid "New Window"
msgstr "Ventana nueva" msgstr "Ventana nueva"
#: ../js/ui/appDisplay.js:677 #: ../js/ui/appDisplay.js:678
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Quitar de los favoritos" msgstr "Quitar de los favoritos"
#: ../js/ui/appDisplay.js:678 #: ../js/ui/appDisplay.js:679
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Añadir a los favoritos" msgstr "Añadir a los favoritos"
@ -504,87 +489,22 @@ msgstr "Esta semana"
msgid "Next week" msgid "Next week"
msgstr "La semana que viene" msgstr "La semana que viene"
#: ../js/ui/contactDisplay.js:66 #: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1287
msgctxt "contact"
msgid "Unknown"
msgstr "Desconocido"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:130
msgid "Available"
msgstr "Disponible"
#: ../js/ui/contactDisplay.js:94 ../js/ui/userMenu.js:139
msgid "Away"
msgstr "Ausente"
#: ../js/ui/contactDisplay.js:98 ../js/ui/userMenu.js:133
msgid "Busy"
msgstr "Ocupado"
#: ../js/ui/contactDisplay.js:102
msgid "Offline"
msgstr "Desconectado"
#: ../js/ui/contactDisplay.js:153
msgid "CONTACTS"
msgstr "CONTACTOS"
#: ../js/ui/dash.js:239 ../js/ui/messageTray.js:1239
msgid "Remove" msgid "Remove"
msgstr "Quitar" msgstr "Quitar"
#: ../js/ui/dateMenu.js:101 #: ../js/ui/dateMenu.js:94
msgid "Date and Time Settings" msgid "Date and Time Settings"
msgstr "Ajustes de hora y fecha" msgstr "Ajustes de hora y fecha"
#: ../js/ui/dateMenu.js:127 #: ../js/ui/dateMenu.js:120
msgid "Open Calendar" msgid "Open Calendar"
msgstr "Abrir calendario" msgstr "Abrir calendario"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:185
msgid "%a %b %e, %R:%S"
msgstr "%a %e de %b, %R:%S"
#: ../js/ui/dateMenu.js:186
msgid "%a %b %e, %R"
msgstr "%a %e de %b, %R"
#. Translators: This is the time format without date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:190
msgid "%a %R:%S"
msgstr "%a %R:%S"
#: ../js/ui/dateMenu.js:191
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format with date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:198
msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %e de %b, %l:%M:%S %p"
#: ../js/ui/dateMenu.js:199
msgid "%a %b %e, %l:%M %p"
msgstr "%a %e de %b, %l:%M %p"
#. Translators: This is a time format without date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:203
msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p"
#: ../js/ui/dateMenu.js:204
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#. Translators: This is the date format to use when the calendar popup is #. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM"). #. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. #.
#: ../js/ui/dateMenu.js:215 #: ../js/ui/dateMenu.js:161
msgid "%A %B %e, %Y" msgid "%A %B %e, %Y"
msgstr "%A, %e de %B de %Y" msgstr "%A, %e de %B de %Y"
@ -679,11 +599,11 @@ msgstr[1] "El sistema se reiniciará automáticamente en %d segundos."
msgid "Restarting the system." msgid "Restarting the system."
msgstr "Reiniciando el sistema." msgstr "Reiniciando el sistema."
#: ../js/ui/extensionDownloader.js:112 #: ../js/ui/extensionDownloader.js:142
msgid "Install" msgid "Install"
msgstr "Instalar" msgstr "Instalar"
#: ../js/ui/extensionDownloader.js:116 #: ../js/ui/extensionDownloader.js:146
#, c-format #, c-format
msgid "Download and install '%s' from extensions.gnome.org?" msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "¿Descargar e instalar «%s» desde extensions.gnome.org?" msgstr "¿Descargar e instalar «%s» desde extensions.gnome.org?"
@ -705,73 +625,73 @@ msgstr "Contraseña:"
msgid "Type again:" msgid "Type again:"
msgstr "Escriba de nuevo:" msgstr "Escriba de nuevo:"
#: ../js/ui/lookingGlass.js:693 #: ../js/ui/lookingGlass.js:696
msgid "No extensions installed" msgid "No extensions installed"
msgstr "No hay extensiones instaladas" msgstr "No hay extensiones instaladas"
#. Translators: argument is an extension UUID. #. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:747 #: ../js/ui/lookingGlass.js:750
#, c-format #, c-format
msgid "%s has not emitted any errors." msgid "%s has not emitted any errors."
msgstr "%s no ha generado ningún error." msgstr "%s no ha generado ningún error."
#: ../js/ui/lookingGlass.js:753 #: ../js/ui/lookingGlass.js:756
msgid "Hide Errors" msgid "Hide Errors"
msgstr "Ocultar errores" msgstr "Ocultar errores"
#: ../js/ui/lookingGlass.js:757 ../js/ui/lookingGlass.js:808 #: ../js/ui/lookingGlass.js:760 ../js/ui/lookingGlass.js:811
msgid "Show Errors" msgid "Show Errors"
msgstr "Mostrar errores" msgstr "Mostrar errores"
#: ../js/ui/lookingGlass.js:766 #: ../js/ui/lookingGlass.js:769
msgid "Enabled" msgid "Enabled"
msgstr "Activado" msgstr "Activado"
#. translators: #. translators:
#. * The device has been disabled #. * The device has been disabled
#: ../js/ui/lookingGlass.js:769 ../src/gvc/gvc-mixer-control.c:1082 #: ../js/ui/lookingGlass.js:772 ../src/gvc/gvc-mixer-control.c:1082
msgid "Disabled" msgid "Disabled"
msgstr "Desactivado" msgstr "Desactivado"
#: ../js/ui/lookingGlass.js:771 #: ../js/ui/lookingGlass.js:774
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
#: ../js/ui/lookingGlass.js:773 #: ../js/ui/lookingGlass.js:776
msgid "Out of date" msgid "Out of date"
msgstr "Caducado" msgstr "Caducado"
#: ../js/ui/lookingGlass.js:775 #: ../js/ui/lookingGlass.js:778
msgid "Downloading" msgid "Downloading"
msgstr "Descargando" msgstr "Descargando"
#: ../js/ui/lookingGlass.js:796 #: ../js/ui/lookingGlass.js:799
msgid "View Source" msgid "View Source"
msgstr "Ver fuente" msgstr "Ver fuente"
#: ../js/ui/lookingGlass.js:802 #: ../js/ui/lookingGlass.js:805
msgid "Web Page" msgid "Web Page"
msgstr "Página web" msgstr "Página web"
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:127 #: ../js/ui/main.js:129
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Screencast desde %d %t" msgstr "Screencast desde %d %t"
#: ../js/ui/messageTray.js:1232 #: ../js/ui/messageTray.js:1280
msgid "Open" msgid "Open"
msgstr "Abrir" msgstr "Abrir"
#: ../js/ui/messageTray.js:1249 #: ../js/ui/messageTray.js:1297
msgid "Unmute" msgid "Unmute"
msgstr "Dar voz" msgstr "Dar voz"
#: ../js/ui/messageTray.js:1249 #: ../js/ui/messageTray.js:1297
msgid "Mute" msgid "Mute"
msgstr "Silenciar" msgstr "Silenciar"
#: ../js/ui/messageTray.js:2528 #: ../js/ui/messageTray.js:2575
msgid "System Information" msgid "System Information"
msgstr "Información del sistema" msgstr "Información del sistema"
@ -861,25 +781,25 @@ msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Desconocido" msgstr "Desconocido"
#: ../js/ui/overview.js:90 #: ../js/ui/overview.js:88
msgid "Undo" msgid "Undo"
msgstr "Deshacer" msgstr "Deshacer"
#: ../js/ui/overview.js:130 #: ../js/ui/overview.js:128
msgid "Overview" msgid "Overview"
msgstr "Vista general" msgstr "Vista general"
#: ../js/ui/overview.js:200 #: ../js/ui/overview.js:198
msgid "Windows" msgid "Windows"
msgstr "Ventanas" msgstr "Ventanas"
#: ../js/ui/overview.js:203 #: ../js/ui/overview.js:201
msgid "Applications" msgid "Applications"
msgstr "Aplicaciones" msgstr "Aplicaciones"
#. Translators: this is the name of the dock/favorites area on #. Translators: this is the name of the dock/favorites area on
#. the left of the overview #. the left of the overview
#: ../js/ui/overview.js:230 #: ../js/ui/overview.js:226
msgid "Dash" msgid "Dash"
msgstr "Tablero" msgstr "Tablero"
@ -931,7 +851,7 @@ msgstr "Autenticar"
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/polkitAuthenticationAgent.js:261 #: ../js/ui/polkitAuthenticationAgent.js:261
#: ../js/ui/shellMountOperation.js:323 #: ../js/ui/shellMountOperation.js:324
msgid "Sorry, that didn't work. Please try again." msgid "Sorry, that didn't work. Please try again."
msgstr "Inténtelo de nuevo," msgstr "Inténtelo de nuevo,"
@ -948,11 +868,11 @@ msgstr "toggle-switch-intl"
msgid "Please enter a command:" msgid "Please enter a command:"
msgstr "Introduzca un comando:" msgstr "Introduzca un comando:"
#: ../js/ui/searchDisplay.js:323 #: ../js/ui/searchDisplay.js:320
msgid "Searching..." msgid "Searching..."
msgstr "Buscando…" msgstr "Buscando…"
#: ../js/ui/searchDisplay.js:376 #: ../js/ui/searchDisplay.js:373
msgid "No matching results." msgid "No matching results."
msgstr "No se encontró ningún resultado coincidente." msgstr "No se encontró ningún resultado coincidente."
@ -972,16 +892,15 @@ msgstr "Mostrar texto"
msgid "Hide Text" msgid "Hide Text"
msgstr "Ocultar texto" msgstr "Ocultar texto"
#: ../js/ui/shellMountOperation.js:310 #: ../js/ui/shellMountOperation.js:311
msgid "Passphrase" msgid "Passphrase"
msgstr "Contraseña" msgstr "Contraseña"
#: ../js/ui/shellMountOperation.js:330 #: ../js/ui/shellMountOperation.js:332
msgid "Remember Passphrase" msgid "Remember Passphrase"
msgstr "Recordar contraseña" msgstr "Recordar contraseña"
#: ../js/ui/shellMountOperation.js:338 #: ../js/ui/shellMountOperation.js:343
#| msgid "Undo"
msgid "Unlock" msgid "Unlock"
msgstr "Desbloquear" msgstr "Desbloquear"
@ -994,7 +913,6 @@ msgid "Zoom"
msgstr "Ampliación" msgstr "Ampliación"
#: ../js/ui/status/accessibility.js:59 #: ../js/ui/status/accessibility.js:59
#| msgid "Screen Keyboard"
msgid "Screen Reader" msgid "Screen Reader"
msgstr "Lector de pantalla" msgstr "Lector de pantalla"
@ -1122,7 +1040,7 @@ msgstr "Conceder acceso siempre"
msgid "Grant this time only" msgid "Grant this time only"
msgstr "Conceder sólo esta vez" msgstr "Conceder sólo esta vez"
#: ../js/ui/status/bluetooth.js:350 ../js/ui/telepathyClient.js:1103 #: ../js/ui/status/bluetooth.js:350 ../js/ui/telepathyClient.js:1097
msgid "Reject" msgid "Reject"
msgstr "Rechazar" msgstr "Rechazar"
@ -1417,58 +1335,38 @@ msgstr "Solicitud de suscripción"
msgid "Connection error" msgid "Connection error"
msgstr "Error de conexión" msgstr "Error de conexión"
#: ../js/ui/telepathyClient.js:675
#, c-format
msgid "%s is online."
msgstr "%s está conectado/a."
#: ../js/ui/telepathyClient.js:679
#, c-format
msgid "%s is offline."
msgstr "%s está desconectado/a."
#: ../js/ui/telepathyClient.js:683
#, c-format
msgid "%s is away."
msgstr "%s está ausente."
#: ../js/ui/telepathyClient.js:686
#, c-format
msgid "%s is busy."
msgstr "%s está ocupado/a."
#. Translators: this is a time format string followed by a date. #. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your #. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds. #. locale, without seconds.
#: ../js/ui/telepathyClient.js:901 #: ../js/ui/telepathyClient.js:908
#, no-c-format #, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>" msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviado el <b>%A</b> a las <b>%H:%M</b>" msgstr "Enviado el <b>%A</b> a las <b>%H:%M</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25", #. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year. #. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:907 #: ../js/ui/telepathyClient.js:914
#, no-c-format #, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>" msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviado el <b>%A</b>, <b>%d de %B</b>" msgstr "Enviado el <b>%A</b>, <b>%d de %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012", #. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year. #. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:912 #: ../js/ui/telepathyClient.js:919
#, no-c-format #, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y" msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviado el <b>%A</b>, <b>%d de %B</b> de %Y" msgstr "Enviado el <b>%A</b>, <b>%d de %B</b> de %Y"
#. Translators: this is the other person changing their old IM name to their new #. Translators: this is the other person changing their old IM name to their new
#. IM name. #. IM name.
#: ../js/ui/telepathyClient.js:954 #: ../js/ui/telepathyClient.js:948
#, c-format #, c-format
msgid "%s is now known as %s" msgid "%s is now known as %s"
msgstr "Ahora %s se llama %s" msgstr "Ahora %s se llama %s"
#. translators: argument is a room name like #. translators: argument is a room name like
#. * room@jabber.org for example. #. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1054 #: ../js/ui/telepathyClient.js:1048
#, c-format #, c-format
msgid "Invitation to %s" msgid "Invitation to %s"
msgstr "Invitación a %s" msgstr "Invitación a %s"
@ -1476,35 +1374,35 @@ msgstr "Invitación a %s"
#. translators: first argument is the name of a contact and the second #. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org #. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example. #. * for example.
#: ../js/ui/telepathyClient.js:1062 #: ../js/ui/telepathyClient.js:1056
#, c-format #, c-format
msgid "%s is inviting you to join %s" msgid "%s is inviting you to join %s"
msgstr "%s le está invitando a unirse a %s" msgstr "%s le está invitando a unirse a %s"
#: ../js/ui/telepathyClient.js:1064 ../js/ui/telepathyClient.js:1143 #: ../js/ui/telepathyClient.js:1058 ../js/ui/telepathyClient.js:1137
#: ../js/ui/telepathyClient.js:1207 #: ../js/ui/telepathyClient.js:1201
msgid "Decline" msgid "Decline"
msgstr "Rechazar" msgstr "Rechazar"
#: ../js/ui/telepathyClient.js:1065 ../js/ui/telepathyClient.js:1144 #: ../js/ui/telepathyClient.js:1059 ../js/ui/telepathyClient.js:1138
#: ../js/ui/telepathyClient.js:1208 #: ../js/ui/telepathyClient.js:1202
msgid "Accept" msgid "Accept"
msgstr "Aceptar" msgstr "Aceptar"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1095 #: ../js/ui/telepathyClient.js:1089
#, c-format #, c-format
msgid "Video call from %s" msgid "Video call from %s"
msgstr "Videollamada de %s" msgstr "Videollamada de %s"
#. translators: argument is a contact name like Alice for example. #. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1098 #: ../js/ui/telepathyClient.js:1092
#, c-format #, c-format
msgid "Call from %s" msgid "Call from %s"
msgstr "Llamada de %s" msgstr "Llamada de %s"
#. translators: this is a button label (verb), not a noun #. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1105 #: ../js/ui/telepathyClient.js:1099
msgid "Answer" msgid "Answer"
msgstr "Responder" msgstr "Responder"
@ -1513,112 +1411,112 @@ msgstr "Responder"
#. * file name. The string will be something #. * file name. The string will be something
#. * like: "Alice is sending you test.ogg" #. * like: "Alice is sending you test.ogg"
#. #.
#: ../js/ui/telepathyClient.js:1137 #: ../js/ui/telepathyClient.js:1131
#, c-format #, c-format
msgid "%s is sending you %s" msgid "%s is sending you %s"
msgstr "%s le está enviando %s" msgstr "%s le está enviando %s"
#. To translators: The parameter is the contact's alias #. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1172 #: ../js/ui/telepathyClient.js:1166
#, c-format #, c-format
msgid "%s would like permission to see when you are online" msgid "%s would like permission to see when you are online"
msgstr "%s solicita permiso para ver cuándo está en línea" msgstr "%s solicita permiso para ver cuándo está en línea"
#: ../js/ui/telepathyClient.js:1265 #: ../js/ui/telepathyClient.js:1259
msgid "Network error" msgid "Network error"
msgstr "Error de la red" msgstr "Error de la red"
#: ../js/ui/telepathyClient.js:1267 #: ../js/ui/telepathyClient.js:1261
msgid "Authentication failed" msgid "Authentication failed"
msgstr "Falló la autenticación" msgstr "Falló la autenticación"
#: ../js/ui/telepathyClient.js:1269 #: ../js/ui/telepathyClient.js:1263
msgid "Encryption error" msgid "Encryption error"
msgstr "Error de cifrado" msgstr "Error de cifrado"
#: ../js/ui/telepathyClient.js:1271 #: ../js/ui/telepathyClient.js:1265
msgid "Certificate not provided" msgid "Certificate not provided"
msgstr "Certificado no proporcionado" msgstr "Certificado no proporcionado"
#: ../js/ui/telepathyClient.js:1273 #: ../js/ui/telepathyClient.js:1267
msgid "Certificate untrusted" msgid "Certificate untrusted"
msgstr "No se confía en el certificado" msgstr "No se confía en el certificado"
#: ../js/ui/telepathyClient.js:1275 #: ../js/ui/telepathyClient.js:1269
msgid "Certificate expired" msgid "Certificate expired"
msgstr "Certificado caducado" msgstr "Certificado caducado"
#: ../js/ui/telepathyClient.js:1277 #: ../js/ui/telepathyClient.js:1271
msgid "Certificate not activated" msgid "Certificate not activated"
msgstr "Certificado no activado" msgstr "Certificado no activado"
#: ../js/ui/telepathyClient.js:1279 #: ../js/ui/telepathyClient.js:1273
msgid "Certificate hostname mismatch" msgid "Certificate hostname mismatch"
msgstr "El nombre del servidor dle certificado no coincide" msgstr "El nombre del servidor dle certificado no coincide"
#: ../js/ui/telepathyClient.js:1281 #: ../js/ui/telepathyClient.js:1275
msgid "Certificate fingerprint mismatch" msgid "Certificate fingerprint mismatch"
msgstr "La huella del certificado no coincide" msgstr "La huella del certificado no coincide"
#: ../js/ui/telepathyClient.js:1283 #: ../js/ui/telepathyClient.js:1277
msgid "Certificate self-signed" msgid "Certificate self-signed"
msgstr "Certificado autofirmado" msgstr "Certificado autofirmado"
#: ../js/ui/telepathyClient.js:1285 #: ../js/ui/telepathyClient.js:1279
msgid "Status is set to offline" msgid "Status is set to offline"
msgstr "El estado está establecido a «desconectado»" msgstr "El estado está establecido a «desconectado»"
#: ../js/ui/telepathyClient.js:1287 #: ../js/ui/telepathyClient.js:1281
msgid "Encryption is not available" msgid "Encryption is not available"
msgstr "El cifrado no está disponible" msgstr "El cifrado no está disponible"
#: ../js/ui/telepathyClient.js:1289 #: ../js/ui/telepathyClient.js:1283
msgid "Certificate is invalid" msgid "Certificate is invalid"
msgstr "El certificado no es válido" msgstr "El certificado no es válido"
#: ../js/ui/telepathyClient.js:1291 #: ../js/ui/telepathyClient.js:1285
msgid "Connection has been refused" msgid "Connection has been refused"
msgstr "Se ha rechazado la conexión" msgstr "Se ha rechazado la conexión"
#: ../js/ui/telepathyClient.js:1293 #: ../js/ui/telepathyClient.js:1287
msgid "Connection can't be established" msgid "Connection can't be established"
msgstr "No se puede establecer la conexión" msgstr "No se puede establecer la conexión"
#: ../js/ui/telepathyClient.js:1295 #: ../js/ui/telepathyClient.js:1289
msgid "Connection has been lost" msgid "Connection has been lost"
msgstr "Se ha perdido la conexión" msgstr "Se ha perdido la conexión"
#: ../js/ui/telepathyClient.js:1297 #: ../js/ui/telepathyClient.js:1291
msgid "This account is already connected to the server" msgid "This account is already connected to the server"
msgstr "Esta cuenta ya está conectada al servidor" msgstr "Esta cuenta ya está conectada al servidor"
#: ../js/ui/telepathyClient.js:1299 #: ../js/ui/telepathyClient.js:1293
msgid "" msgid ""
"Connection has been replaced by a new connection using the same resource" "Connection has been replaced by a new connection using the same resource"
msgstr "" msgstr ""
"Se ha sustituido la conexión por una nueva conexión usando el mismo recurso" "Se ha sustituido la conexión por una nueva conexión usando el mismo recurso"
#: ../js/ui/telepathyClient.js:1301 #: ../js/ui/telepathyClient.js:1295
msgid "The account already exists on the server" msgid "The account already exists on the server"
msgstr "La cuenta ya existe en el servidor" msgstr "La cuenta ya existe en el servidor"
#: ../js/ui/telepathyClient.js:1303 #: ../js/ui/telepathyClient.js:1297
msgid "Server is currently too busy to handle the connection" msgid "Server is currently too busy to handle the connection"
msgstr "" msgstr ""
"Actualmente el servidor está muy ocupado intentando gestionar la conexión" "Actualmente el servidor está muy ocupado intentando gestionar la conexión"
#: ../js/ui/telepathyClient.js:1305 #: ../js/ui/telepathyClient.js:1299
msgid "Certificate has been revoked" msgid "Certificate has been revoked"
msgstr "Se ha revocado el certificado" msgstr "Se ha revocado el certificado"
#: ../js/ui/telepathyClient.js:1307 #: ../js/ui/telepathyClient.js:1301
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "" msgstr ""
"El certificado usa un algoritmo de cifrado inseguro o es criptográficamente " "El certificado usa un algoritmo de cifrado inseguro o es criptográficamente "
"débil" "débil"
#: ../js/ui/telepathyClient.js:1309 #: ../js/ui/telepathyClient.js:1303
msgid "" msgid ""
"The length of the server certificate, or the depth of the server certificate " "The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library" "chain, exceed the limits imposed by the cryptography library"
@ -1627,32 +1525,44 @@ msgstr ""
"certificado del servidor exceden los límites impuestos por la biblioteca de " "certificado del servidor exceden los límites impuestos por la biblioteca de "
"criptografía" "criptografía"
#: ../js/ui/telepathyClient.js:1311 #: ../js/ui/telepathyClient.js:1305
msgid "Internal error" msgid "Internal error"
msgstr "Error interno" msgstr "Error interno"
#. translators: argument is the account name, like #. translators: argument is the account name, like
#. * name@jabber.org for example. #. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1321 #: ../js/ui/telepathyClient.js:1315
#, c-format #, c-format
msgid "Connection to %s failed" msgid "Connection to %s failed"
msgstr "Falló la conexión a %s" msgstr "Falló la conexión a %s"
#: ../js/ui/telepathyClient.js:1330 #: ../js/ui/telepathyClient.js:1324
msgid "Reconnect" msgid "Reconnect"
msgstr "Reconectar" msgstr "Reconectar"
#: ../js/ui/telepathyClient.js:1331 #: ../js/ui/telepathyClient.js:1325
msgid "Edit account" msgid "Edit account"
msgstr "Editar cuenta" msgstr "Editar cuenta"
#: ../js/ui/telepathyClient.js:1377 #: ../js/ui/telepathyClient.js:1371
msgid "Unknown reason" msgid "Unknown reason"
msgstr "Razón desconocida" msgstr "Razón desconocida"
#: ../js/ui/userMenu.js:130
msgid "Available"
msgstr "Disponible"
#: ../js/ui/userMenu.js:133
msgid "Busy"
msgstr "Ocupado"
#: ../js/ui/userMenu.js:136 #: ../js/ui/userMenu.js:136
msgid "Hidden" msgid "Invisible"
msgstr "Oculto" msgstr "Invisible"
#: ../js/ui/userMenu.js:139
msgid "Away"
msgstr "Ausente"
#: ../js/ui/userMenu.js:142 #: ../js/ui/userMenu.js:142
msgid "Idle" msgid "Idle"
@ -1662,35 +1572,39 @@ msgstr "Inactivo"
msgid "Unavailable" msgid "Unavailable"
msgstr "No disponible" msgstr "No disponible"
#: ../js/ui/userMenu.js:565 ../js/ui/userMenu.js:705 #: ../js/ui/userMenu.js:567 ../js/ui/userMenu.js:706
msgid "Switch User" msgid "Switch User"
msgstr "Cambiar de usuario" msgstr "Cambiar de usuario"
#: ../js/ui/userMenu.js:566 #: ../js/ui/userMenu.js:568
msgid "Switch Session" msgid "Switch Session"
msgstr "Cambiar de sesión" msgstr "Cambiar de sesión"
#: ../js/ui/userMenu.js:681 #: ../js/ui/userMenu.js:689
msgid "Notifications" msgid "Notifications"
msgstr "Notificaciones" msgstr "Notificaciones"
#: ../js/ui/userMenu.js:690 #: ../js/ui/userMenu.js:698
msgid "System Settings" msgid "System Settings"
msgstr "Configuración del sistema" msgstr "Configuración del sistema"
#: ../js/ui/userMenu.js:710 #: ../js/ui/userMenu.js:711
msgid "Log Out" msgid "Log Out"
msgstr "Cerrar la sesión" msgstr "Cerrar la sesión"
#: ../js/ui/userMenu.js:718 #: ../js/ui/userMenu.js:716
msgid "Lock" msgid "Lock"
msgstr "Bloquear" msgstr "Bloquear"
#: ../js/ui/userMenu.js:736 #: ../js/ui/userMenu.js:724
msgid "Install Updates & Restart"
msgstr "Instalar actualizaciones y reiniciar"
#: ../js/ui/userMenu.js:749
msgid "Your chat status will be set to busy" msgid "Your chat status will be set to busy"
msgstr "Su estado del chat se establecerá a «ocupado»" msgstr "Su estado del chat se establecerá a «ocupado»"
#: ../js/ui/userMenu.js:737 #: ../js/ui/userMenu.js:750
msgid "" msgid ""
"Notifications are now disabled, including chat messages. Your online status " "Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages." "has been adjusted to let others know that you might not see their messages."
@ -1734,6 +1648,10 @@ msgstr "Su mensaje oculto favorito"
msgid "'%s' is ready" msgid "'%s' is ready"
msgstr "«%s» está preparado" msgstr "«%s» está preparado"
#: ../src/calendar-server/evolution-calendar.desktop.in.in.h:1
msgid "Evolution Calendar"
msgstr "Calendario de Evolution"
#. translators: #. translators:
#. * The number of sound outputs on a particular device #. * The number of sound outputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1089 #: ../src/gvc/gvc-mixer-control.c:1089
@ -1795,7 +1713,7 @@ msgstr "Reino Unido"
msgid "Default" msgid "Default"
msgstr "Predeterminada" msgstr "Predeterminada"
#: ../src/shell-polkit-authentication-agent.c:339 #: ../src/shell-polkit-authentication-agent.c:340
msgid "Authentication dialog was dismissed by the user" msgid "Authentication dialog was dismissed by the user"
msgstr "El usuario rechazó el diálogo de autenticación" msgstr "El usuario rechazó el diálogo de autenticación"
@ -1821,6 +1739,67 @@ msgstr "Sistema de archivos"
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s" msgstr "%1$s: %2$s"
#~ msgid "Show time with seconds"
#~ msgstr "Mostrar la hora con segundos"
#~ msgid "If true, display seconds in time."
#~ msgstr "Si es cierta, muestra los segundos en la hora."
#~ msgid "Show date in clock"
#~ msgstr "Mostrar la fecha en el reloj"
#~ msgid "If true, display date in the clock, in addition to time."
#~ msgstr "Si es cierta, muestra la fecha en el reloj, además de la hora."
#~ msgctxt "contact"
#~ msgid "Unknown"
#~ msgstr "Desconocido"
#~ msgid "Offline"
#~ msgstr "Desconectado"
#~ msgid "CONTACTS"
#~ msgstr "CONTACTOS"
#~ msgid "%a %b %e, %R:%S"
#~ msgstr "%a %e de %b, %R:%S"
#~ msgid "%a %b %e, %R"
#~ msgstr "%a %e de %b, %R"
#~ msgid "%a %R:%S"
#~ msgstr "%a %R:%S"
#~ msgid "%a %R"
#~ msgstr "%a %R"
#~ msgid "%a %b %e, %l:%M:%S %p"
#~ msgstr "%a %e de %b, %l:%M:%S %p"
#~ msgid "%a %b %e, %l:%M %p"
#~ msgstr "%a %e de %b, %l:%M %p"
#~ msgid "%a %l:%M:%S %p"
#~ msgstr "%a %l:%M:%S %p"
#~ msgid "%a %l:%M %p"
#~ msgstr "%a %l:%M %p"
#~ msgid "%s is online."
#~ msgstr "%s está conectado/a."
#~ msgid "%s is offline."
#~ msgstr "%s está desconectado/a."
#~ msgid "%s is away."
#~ msgstr "%s está ausente."
#~ msgid "%s is busy."
#~ msgstr "%s está ocupado/a."
#~ msgid "Hidden"
#~ msgstr "Oculto"
#~ msgid "Wrong password, please try again" #~ msgid "Wrong password, please try again"
#~ msgstr "Contraseña incorrecta; inténtelo de nuevo" #~ msgstr "Contraseña incorrecta; inténtelo de nuevo"
@ -2182,9 +2161,6 @@ msgstr "%1$s: %2$s"
#~ msgid "Find" #~ msgid "Find"
#~ msgstr "Buscar" #~ msgstr "Buscar"
#~ msgid "Invisible"
#~ msgstr "Invisible"
#~ msgid "ON" #~ msgid "ON"
#~ msgstr "ENCENDIDO" #~ msgstr "ENCENDIDO"

647
po/he.po

File diff suppressed because it is too large Load Diff

464
po/nb.po

File diff suppressed because it is too large Load Diff

1391
po/nn.po

File diff suppressed because it is too large Load Diff

141
po/sl.po
View File

@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-06-21 20:04+0000\n" "POT-Creation-Date: 2012-06-25 22:10+0000\n"
"PO-Revision-Date: 2012-06-22 09:36+0100\n" "PO-Revision-Date: 2012-06-26 09:17+0100\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n" "Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n" "Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: Slovenian\n" "Language: Slovenian\n"
@ -123,43 +123,27 @@ msgid "The type of keyboard to use."
msgstr "Vrsta tipkovnice za uporabo." msgstr "Vrsta tipkovnice za uporabo."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid "Show time with seconds"
msgstr "Pokaži čas s sekundami"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "If true, display seconds in time."
msgstr "Izbrana možnost določi prikaz sekund v času."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "Show date in clock"
msgstr "Pokaži datum v uri"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "If true, display date in the clock, in addition to time."
msgstr "Izbrana možnost določi, da je ob času prikazan tudi datum."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "Hitrost sličic uporabljena za snemanje zaslonskega posnetka." msgstr "Hitrost sličic uporabljena za snemanje zaslonskega posnetka."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "The framerate of the resulting screencast recordered by GNOME Shell's screencast recorder in frames-per-second." msgid "The framerate of the resulting screencast recordered by GNOME Shell's screencast recorder in frames-per-second."
msgstr "Hitrost sličic shranjenega končnega zaslonskega posnetka v sličicah na sekundo." msgstr "Hitrost sličic shranjenega končnega zaslonskega posnetka v sličicah na sekundo."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28 #: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "Uporabljen GStreamer cevovod za kodiranje zaslonskega posnetka." msgstr "Uporabljen GStreamer cevovod za kodiranje zaslonskega posnetka."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30 #: ../data/org.gnome.shell.gschema.xml.in.in.h:26
#, no-c-format #, no-c-format
msgid "Sets the GStreamer pipeline used to encode recordings. It follows the syntax used for gst-launch. The pipeline should have an unconnected sink pad where the recorded video is recorded. It will normally have a unconnected source pad; output from that pad will be written into the output file. However the pipeline can also take care of its own output - this might be used to send the output to an icecast server via shout2send or similar. When unset or set to an empty value, the default pipeline will be used. This is currently 'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is used as a placeholder for a guess at the optimal thread count on the system." msgid "Sets the GStreamer pipeline used to encode recordings. It follows the syntax used for gst-launch. The pipeline should have an unconnected sink pad where the recorded video is recorded. It will normally have a unconnected source pad; output from that pad will be written into the output file. However the pipeline can also take care of its own output - this might be used to send the output to an icecast server via shout2send or similar. When unset or set to an empty value, the default pipeline will be used. This is currently 'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux' and records to WEBM using the VP8 codec. %T is used as a placeholder for a guess at the optimal thread count on the system."
msgstr "Določa cevovod programa GStreamer, ki se uporablja za kodiranje posnetkov. Ta sledi skladnji, ki se uporablja za gst-launch. Cevovod mora imeti nepovezano korito, kamor se posnetek snema. Običajno je za to namenjen nepovezan izvorni pomnilnik, katerega odvod se zapiše v odvodno datoteko. Vendar pa lahko cevovod ta korak naredi v lastni odvod - možnost se lahko uporabi pri pošiljanju odvoda na strežnik icecast preko shout2send ali podobno. Nedoločena ali prazna možnost se odrazi kot privzeti cevovod. Trenutno je to 'videorate ! vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux' in omogoča snemanje v zapis WEBM z uporabo kodeka VP8. Vrednost %T se uporablja kot ročnik za ugibanje optimalnega števila niti na sistemu." msgstr "Določa cevovod programa GStreamer, ki se uporablja za kodiranje posnetkov. Ta sledi skladnji, ki se uporablja za gst-launch. Cevovod mora imeti nepovezano korito, kamor se posnetek snema. Običajno je za to namenjen nepovezan izvorni pomnilnik, katerega odvod se zapiše v odvodno datoteko. Vendar pa lahko cevovod ta korak naredi v lastni odvod - možnost se lahko uporabi pri pošiljanju odvoda na strežnik icecast preko shout2send ali podobno. Nedoločena ali prazna možnost se odrazi kot privzeti cevovod. Trenutno je to 'videorate ! vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux' in omogoča snemanje v zapis WEBM z uporabo kodeka VP8. Vrednost %T se uporablja kot ročnik za ugibanje optimalnega števila niti na sistemu."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31 #: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "Pripona datoteke uporabljene za shranjevanje zaslonskih posnetkov" msgstr "Pripona datoteke uporabljene za shranjevanje zaslonskih posnetkov"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32 #: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "The filename for recorded screencasts will be a unique filename based on the current date, and use this extension. It should be changed when recording to a different container format." msgid "The filename for recorded screencasts will be a unique filename based on the current date, and use this extension. It should be changed when recording to a different container format."
msgstr "Ime datoteke zaslonskega posnetka bo enoznačno ime, kateremu bo dodan datum in določena pripona. Pripona mora ustrezati zapisu zabojnika." msgstr "Ime datoteke zaslonskega posnetka bo enoznačno ime, kateremu bo dodan datum in določena pripona. Pripona mora ustrezati zapisu zabojnika."
@ -203,7 +187,7 @@ msgstr "Ali je ni na seznamu?"
#: ../js/ui/extensionDownloader.js:108 #: ../js/ui/extensionDownloader.js:108
#: ../js/ui/networkAgent.js:153 #: ../js/ui/networkAgent.js:153
#: ../js/ui/polkitAuthenticationAgent.js:176 #: ../js/ui/polkitAuthenticationAgent.js:176
#: ../js/ui/shellMountOperation.js:334 #: ../js/ui/shellMountOperation.js:339
#: ../js/ui/status/bluetooth.js:431 #: ../js/ui/status/bluetooth.js:431
msgid "Cancel" msgid "Cancel"
msgstr "Prekliči" msgstr "Prekliči"
@ -477,61 +461,14 @@ msgstr "Stiki"
msgid "Remove" msgid "Remove"
msgstr "Odstrani" msgstr "Odstrani"
#: ../js/ui/dateMenu.js:101 #: ../js/ui/dateMenu.js:94
msgid "Date and Time Settings" msgid "Date and Time Settings"
msgstr "Nastavitve časa in datuma" msgstr "Nastavitve časa in datuma"
#: ../js/ui/dateMenu.js:127 #: ../js/ui/dateMenu.js:120
msgid "Open Calendar" msgid "Open Calendar"
msgstr "Odpri koledar" msgstr "Odpri koledar"
#. Translators: This is the time format with date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:185
msgid "%a %b %e, %R:%S"
msgstr "%a. %e. %b., %R:%S"
#: ../js/ui/dateMenu.js:186
msgid "%a %b %e, %R"
msgstr "%a, %e. %b., %R"
#. Translators: This is the time format without date used
#. in 24-hour mode.
#: ../js/ui/dateMenu.js:190
msgid "%a %R:%S"
msgstr "%a. %R:%S"
#: ../js/ui/dateMenu.js:191
msgid "%a %R"
msgstr "%a. %R"
#. Translators: This is a time format with date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:198
msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %b %e, %l:%M:%S %p"
#: ../js/ui/dateMenu.js:199
msgid "%a %b %e, %l:%M %p"
msgstr "%a %b %e, %l:%M %p"
#. Translators: This is a time format without date used
#. for AM/PM.
#: ../js/ui/dateMenu.js:203
msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p"
#: ../js/ui/dateMenu.js:204
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#.
#: ../js/ui/dateMenu.js:215
msgid "%A %B %e, %Y"
msgstr "%a, %e. %b., %R"
#: ../js/ui/endSessionDialog.js:60 #: ../js/ui/endSessionDialog.js:60
#, c-format #, c-format
msgctxt "title" msgctxt "title"
@ -708,7 +645,7 @@ msgid "Web Page"
msgstr "Spletna stran" msgstr "Spletna stran"
#. Translators: this is a filename used for screencast recording #. Translators: this is a filename used for screencast recording
#: ../js/ui/main.js:127 #: ../js/ui/main.js:129
#, no-c-format #, no-c-format
msgid "Screencast from %d %t" msgid "Screencast from %d %t"
msgstr "Screencast z %d %t" msgstr "Screencast z %d %t"
@ -885,7 +822,7 @@ msgstr "Overi"
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: ../js/ui/polkitAuthenticationAgent.js:261 #: ../js/ui/polkitAuthenticationAgent.js:261
#: ../js/ui/shellMountOperation.js:323 #: ../js/ui/shellMountOperation.js:324
msgid "Sorry, that didn't work. Please try again." msgid "Sorry, that didn't work. Please try again."
msgstr "Dejanje je spodletelo. Poskusite znova." msgstr "Dejanje je spodletelo. Poskusite znova."
@ -926,15 +863,15 @@ msgstr "Pokaži besedilo"
msgid "Hide Text" msgid "Hide Text"
msgstr "Skrij besedilo" msgstr "Skrij besedilo"
#: ../js/ui/shellMountOperation.js:310 #: ../js/ui/shellMountOperation.js:311
msgid "Passphrase" msgid "Passphrase"
msgstr "Šifrirno geslo" msgstr "Šifrirno geslo"
#: ../js/ui/shellMountOperation.js:330 #: ../js/ui/shellMountOperation.js:332
msgid "Remember Passphrase" msgid "Remember Passphrase"
msgstr "Zapomni si šifrirno geslo" msgstr "Zapomni si šifrirno geslo"
#: ../js/ui/shellMountOperation.js:338 #: ../js/ui/shellMountOperation.js:343
msgid "Unlock" msgid "Unlock"
msgstr "Odkleni" msgstr "Odkleni"
@ -1619,8 +1556,8 @@ msgid "Unknown reason"
msgstr "Neznan vzrok" msgstr "Neznan vzrok"
#: ../js/ui/userMenu.js:136 #: ../js/ui/userMenu.js:136
msgid "Hidden" msgid "Invisible"
msgstr "Skrito" msgstr "Nevidno"
#: ../js/ui/userMenu.js:142 #: ../js/ui/userMenu.js:142
msgid "Idle" msgid "Idle"
@ -1762,7 +1699,7 @@ msgstr "Velika Britanija"
msgid "Default" msgid "Default"
msgstr "Privzeto" msgstr "Privzeto"
#: ../src/shell-polkit-authentication-agent.c:339 #: ../src/shell-polkit-authentication-agent.c:340
msgid "Authentication dialog was dismissed by the user" msgid "Authentication dialog was dismissed by the user"
msgstr "Uporabnik je zavrnil pogovorno okno overitve" msgstr "Uporabnik je zavrnil pogovorno okno overitve"
@ -1788,6 +1725,48 @@ msgstr "Datotečni sistem"
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s" msgstr "%1$s: %2$s"
#~ msgid "Show time with seconds"
#~ msgstr "Pokaži čas s sekundami"
#~ msgid "If true, display seconds in time."
#~ msgstr "Izbrana možnost določi prikaz sekund v času."
#~ msgid "Show date in clock"
#~ msgstr "Pokaži datum v uri"
#~ msgid "If true, display date in the clock, in addition to time."
#~ msgstr "Izbrana možnost določi, da je ob času prikazan tudi datum."
#~ msgid "%a %b %e, %R:%S"
#~ msgstr "%a. %e. %b., %R:%S"
#~ msgid "%a %b %e, %R"
#~ msgstr "%a, %e. %b., %R"
#~ msgid "%a %R:%S"
#~ msgstr "%a. %R:%S"
#~ msgid "%a %R"
#~ msgstr "%a. %R"
#~ msgid "%a %b %e, %l:%M:%S %p"
#~ msgstr "%a %b %e, %l:%M:%S %p"
#~ msgid "%a %b %e, %l:%M %p"
#~ msgstr "%a %b %e, %l:%M %p"
#~ msgid "%a %l:%M:%S %p"
#~ msgstr "%a %l:%M:%S %p"
#~ msgid "%a %l:%M %p"
#~ msgstr "%a %l:%M %p"
#~ msgid "%A %B %e, %Y"
#~ msgstr "%a, %e. %b., %R"
#~ msgid "Hidden"
#~ msgstr "Skrito"
#~ msgid "Wrong password, please try again" #~ msgid "Wrong password, please try again"
#~ msgstr "Napačno geslo; poskusite znova." #~ msgstr "Napačno geslo; poskusite znova."

812
po/te.po

File diff suppressed because it is too large Load Diff

747
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,12 @@ gnome_shell_calendar_server_SOURCES = \
calendar-server/gnome-shell-calendar-server.c \ calendar-server/gnome-shell-calendar-server.c \
$(NULL) $(NULL)
desktopdir=$(datadir)/applications
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
desktop_in_files = calendar-server/evolution-calendar.desktop.in
@INTLTOOL_DESKTOP_RULE@
gnome_shell_calendar_server_CFLAGS = \ gnome_shell_calendar_server_CFLAGS = \
-I$(top_srcdir)/src \ -I$(top_srcdir)/src \
-DPREFIX=\""$(prefix)"\" \ -DPREFIX=\""$(prefix)"\" \
@ -26,3 +32,6 @@ EXTRA_DIST += \
calendar-server/README \ calendar-server/README \
calendar-server/org.gnome.Shell.CalendarServer.service.in \ calendar-server/org.gnome.Shell.CalendarServer.service.in \
$(NULL) $(NULL)
CLEANFILES = \
$(desktop_DATA)

View File

@ -131,10 +131,6 @@ shell_public_headers_h = \
shell-wm.h \ shell-wm.h \
shell-xfixes-cursor.h shell-xfixes-cursor.h
if BUILD_WITH_FOLKS
shell_public_headers_h += shell-contact-system.h
endif
shell_private_sources = \ shell_private_sources = \
gactionmuxer.h \ gactionmuxer.h \
gactionmuxer.c \ gactionmuxer.c \
@ -187,10 +183,6 @@ libgnome_shell_la_SOURCES = \
shell-xfixes-cursor.c \ shell-xfixes-cursor.c \
$(NULL) $(NULL)
if BUILD_WITH_FOLKS
libgnome_shell_la_SOURCES += shell-contact-system.c
endif
libgnome_shell_la_gir_sources = \ libgnome_shell_la_gir_sources = \
$(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_la_SOURCES)) $(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_la_SOURCES))
@ -200,8 +192,6 @@ gnome_shell_real_CPPFLAGS = $(gnome_shell_cflags)
gnome_shell_real_LDADD = libgnome-shell.la libgnome-shell-js.la $(libgnome_shell_la_LIBADD) gnome_shell_real_LDADD = libgnome-shell.la libgnome-shell-js.la $(libgnome_shell_la_LIBADD)
gnome_shell_real_DEPENDENCIES = libgnome-shell.la gnome_shell_real_DEPENDENCIES = libgnome-shell.la
EXTRA_DIST += test-gapplication.js
######################################## ########################################
libgnome_shell_js_la_SOURCES = \ libgnome_shell_js_la_SOURCES = \
@ -307,9 +297,6 @@ libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
Shell-0.1.gir: libgnome-shell.la St-1.0.gir Shell-0.1.gir: libgnome-shell.la St-1.0.gir
Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0 Shell_0_1_gir_INCLUDES = Clutter-1.0 ClutterX11-1.0 Meta-3.0 TelepathyGLib-0.12 TelepathyLogger-0.2 Soup-2.4 GMenu-3.0 NetworkManager-1.0 NMClient-1.0
if BUILD_WITH_FOLKS
Shell_0_1_gir_INCLUDES += Folks-0.6
endif
Shell_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir) Shell_0_1_gir_CFLAGS = $(libgnome_shell_la_CPPFLAGS) -I $(srcdir)
Shell_0_1_gir_LIBS = libgnome-shell.la Shell_0_1_gir_LIBS = libgnome-shell.la
Shell_0_1_gir_FILES = $(libgnome_shell_la_gir_sources) Shell_0_1_gir_FILES = $(libgnome_shell_la_gir_sources)

View File

@ -0,0 +1,7 @@
[Desktop Entry]
_Name=Evolution Calendar
Exec=evolution -c calendar
Icon=evolution
NoDisplay=true
Type=Application
StartupNotify=true

View File

@ -1,4 +1,4 @@
#!/bin/bash #!/bin/sh
if [ -n "$GI_TYPELIB_PATH" ]; then if [ -n "$GI_TYPELIB_PATH" ]; then
export GI_TYPELIB_PATH=@pkglibdir@ export GI_TYPELIB_PATH=@pkglibdir@

View File

@ -1,490 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* This implements a complete suite for caching and searching contacts in the
* Shell. We retrieve contacts from libfolks asynchronously and we search
* these for display to the user. */
#include "shell-contact-system.h"
#include <glib.h>
#include <glib/gprintf.h>
#include <gee.h>
#include <clutter/clutter.h>
#include <folks/folks.h>
#include "shell-global.h"
#include "shell-util.h"
#include "st.h"
G_DEFINE_TYPE (ShellContactSystem, shell_contact_system, G_TYPE_OBJECT);
#define NAME_PREFIX_MATCH_WEIGHT 100
#define NAME_SUBSTRING_MATCH_WEIGHT 90
#define ADDR_PREFIX_MATCH_WEIGHT 10
#define ADDR_SUBSTRING_MATCH_WEIGHT 5
/* Callbacks */
static void
prepare_individual_aggregator_cb (GObject *obj,
GAsyncResult *res,
gpointer user_data)
{
FolksIndividualAggregator *aggregator = FOLKS_INDIVIDUAL_AGGREGATOR (obj);
folks_individual_aggregator_prepare_finish (aggregator, res, NULL);
}
/* Internal stuff */
typedef struct {
gchar *key;
guint weight;
} ContactSearchResult;
struct _ShellContactSystemPrivate {
FolksIndividualAggregator *aggregator;
};
static void
shell_contact_system_constructed (GObject *obj)
{
ShellContactSystem *self = SHELL_CONTACT_SYSTEM (obj);
G_OBJECT_CLASS (shell_contact_system_parent_class)->constructed (obj);
/* We intentionally do not care about the "individuals-changed" signal, as
* we don't intend to update searches after they've been performed.
* Therefore, we will simply retrieve the "individuals" property which
* represents a snapshot of the individuals in the aggregator.
*/
self->priv->aggregator = folks_individual_aggregator_new ();
folks_individual_aggregator_prepare (self->priv->aggregator, prepare_individual_aggregator_cb, NULL);
}
static void
shell_contact_system_finalize (GObject *obj)
{
ShellContactSystem *self = SHELL_CONTACT_SYSTEM (obj);
g_object_unref (self->priv->aggregator);
G_OBJECT_CLASS (shell_contact_system_parent_class)->finalize (obj);
}
static void
shell_contact_system_init (ShellContactSystem *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_CONTACT_SYSTEM, ShellContactSystemPrivate);
}
static void
shell_contact_system_class_init (ShellContactSystemClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = shell_contact_system_constructed;
object_class->finalize = shell_contact_system_finalize;
g_type_class_add_private (object_class, sizeof (ShellContactSystemPrivate));
}
/*
* normalize_terms:
* @terms: (element-type utf8): Input search terms
*
* Returns: (element-type utf8) (transfer full): Unicode-normalized and lowercased terms
*/
static GSList *
normalize_terms (GSList *terms)
{
GSList *normalized_terms = NULL;
GSList *iter;
for (iter = terms; iter; iter = iter->next)
{
const char *term = iter->data;
normalized_terms = g_slist_prepend (normalized_terms, shell_util_normalize_and_casefold (term));
}
return normalized_terms;
}
static guint
do_match (ShellContactSystem *self,
FolksIndividual *individual,
GSList *terms)
{
GSList *term_iter;
guint weight = 0;
char *alias = shell_util_normalize_and_casefold (folks_alias_details_get_alias (FOLKS_ALIAS_DETAILS (individual)));
char *name = shell_util_normalize_and_casefold (folks_name_details_get_full_name (FOLKS_NAME_DETAILS (individual)));
char *nick = shell_util_normalize_and_casefold (folks_name_details_get_nickname (FOLKS_NAME_DETAILS (individual)));
GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual));
GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map);
GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual));
GeeIterator *addrs_iter;
gboolean have_name_prefix = FALSE;
gboolean have_name_substring = FALSE;
gboolean have_addr_prefix = FALSE;
gboolean have_addr_substring = FALSE;
for (term_iter = terms; term_iter; term_iter = term_iter->next)
{
const char *term = term_iter->data;
const char *p;
gboolean matched;
matched = FALSE;
/* Match on alias, name, nickname */
if (alias != NULL)
{
p = strstr (alias, term);
if (p == alias)
{
have_name_prefix = TRUE;
matched = TRUE;
}
else if (p != NULL)
{
have_name_substring = TRUE;
matched = TRUE;
}
}
if (name != NULL)
{
p = strstr (name, term);
if (p == name)
{
have_name_prefix = TRUE;
matched = TRUE;
}
else if (p != NULL)
{
have_name_substring = TRUE;
matched = TRUE;
}
}
if (nick != NULL)
{
p = strstr (nick, term);
if (p == nick)
{
have_name_prefix = TRUE;
matched = TRUE;
}
else if (p != NULL)
{
have_name_substring = TRUE;
matched = TRUE;
}
}
/* Match on one or more IM or email addresses */
addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs));
while (gee_iterator_next (addrs_iter))
{
FolksImFieldDetails *field = gee_iterator_get (addrs_iter);
const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field);
p = strstr (addr, term);
if (p == addr)
{
have_addr_prefix = TRUE;
matched = TRUE;
}
else if (p != NULL)
{
have_addr_substring = TRUE;
matched = TRUE;
}
g_object_unref (field);
}
g_object_unref (addrs_iter);
addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs));
while (gee_iterator_next (addrs_iter))
{
FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter);
const gchar *addr = folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field);
p = strstr (addr, term);
if (p == addr)
{
have_addr_prefix = TRUE;
matched = TRUE;
}
else if (p != NULL)
{
have_addr_substring = TRUE;
matched = TRUE;
}
g_object_unref (field);
}
g_object_unref (addrs_iter);
if (!matched)
{
have_name_prefix = FALSE;
have_name_substring = FALSE;
have_addr_prefix = FALSE;
have_addr_substring = FALSE;
break;
}
}
if (have_name_prefix)
weight += NAME_PREFIX_MATCH_WEIGHT;
else if (have_name_substring)
weight += NAME_SUBSTRING_MATCH_WEIGHT;
if (have_addr_prefix)
weight += ADDR_PREFIX_MATCH_WEIGHT;
else if (have_addr_substring)
weight += ADDR_SUBSTRING_MATCH_WEIGHT;
g_free (alias);
g_free (name);
g_free (nick);
g_object_unref (im_addrs);
return weight;
}
static gint
compare_results (gconstpointer a,
gconstpointer b)
{
ContactSearchResult *first = (ContactSearchResult *) a;
ContactSearchResult *second = (ContactSearchResult *) b;
if (first->weight > second->weight)
return 1;
else if (first->weight < second->weight)
return -1;
else
return 0;
}
static void
free_result (gpointer data,
gpointer user_data)
{
g_slice_free (ContactSearchResult, data);
}
/* modifies and frees @results */
static GSList *
sort_and_prepare_results (GSList *results)
{
GSList *iter;
GSList *sorted_results = NULL;
results = g_slist_sort (results, compare_results);
for (iter = results; iter; iter = iter->next)
{
ContactSearchResult *result = iter->data;
gchar *id = result->key;
sorted_results = g_slist_prepend (sorted_results, id);
}
g_slist_free_full (results, (GDestroyNotify) free_result);
return sorted_results;
}
/* Methods */
/**
* shell_contact_system_get_default:
*
* Return Value: (transfer none): The global #ShellContactSystem singleton
*/
ShellContactSystem *
shell_contact_system_get_default (void)
{
static ShellContactSystem *instance = NULL;
if (instance == NULL)
instance = g_object_new (SHELL_TYPE_CONTACT_SYSTEM, NULL);
return instance;
}
/**
* shell_contact_system_get_all:
* @self: A #ShellContactSystem
*
* Returns: (transfer none): All individuals
*/
GeeMap *
shell_contact_system_get_all (ShellContactSystem *self)
{
GeeMap *individuals;
g_return_val_if_fail (SHELL_IS_CONTACT_SYSTEM (self), NULL);
individuals = folks_individual_aggregator_get_individuals (self->priv->aggregator);
return individuals;
}
/**
* shell_contact_system_get_individual:
* @self: A #ShellContactSystem
* @id: A #gchar with the ID of the FolksIndividual to be returned.
*
* Returns: (transfer full): A #FolksIndividual or NULL if @id could not be found.
*/
FolksIndividual *
shell_contact_system_get_individual (ShellContactSystem *self,
gchar *id)
{
GeeMap *individuals;
gpointer key, value;
key = (gpointer) id;
g_return_val_if_fail (SHELL_IS_CONTACT_SYSTEM (self), NULL);
individuals = folks_individual_aggregator_get_individuals (self->priv->aggregator);
value = gee_map_get (individuals, key);
return FOLKS_INDIVIDUAL (value);
}
/**
* shell_contact_system_get_email_for_display:
* @self: A #ShellContactSystem
* @individual A #FolksIndividual
*
* Get an email address (either from IM addresses or email), which can be
* used to represent @individual.
*
* Return: (transfer full): a newly allocated string or %NULL if no address
* was found
*/
char *
shell_contact_system_get_email_for_display (ShellContactSystem *self,
FolksIndividual *individual)
{
GeeMultiMap *im_addr_map = folks_im_details_get_im_addresses (FOLKS_IM_DETAILS (individual));
GeeCollection *im_addrs = gee_multi_map_get_values (im_addr_map);
GeeSet *email_addrs = folks_email_details_get_email_addresses (FOLKS_EMAIL_DETAILS (individual));
GeeIterator *addrs_iter;
char *email = NULL;
addrs_iter = gee_iterable_iterator (GEE_ITERABLE (im_addrs));
if (gee_iterator_first (addrs_iter))
{
FolksImFieldDetails *field = gee_iterator_get (addrs_iter);
email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field));
g_object_unref (field);
}
g_object_unref (addrs_iter);
g_object_unref (im_addrs);
if (email != NULL)
return email;
addrs_iter = gee_iterable_iterator (GEE_ITERABLE (email_addrs));
if (gee_iterator_first (addrs_iter))
{
FolksEmailFieldDetails *field = gee_iterator_get (addrs_iter);
email = g_strdup (folks_abstract_field_details_get_value ((FolksAbstractFieldDetails*)field));
g_object_unref (field);
}
g_object_unref (addrs_iter);
return email;
}
/**
* shell_contact_system_initial_search:
* @shell: A #ShellContactSystem
* @terms: (element-type utf8): List of terms, logical AND
*
* Search through contacts for the given search terms.
*
* Returns: (transfer container) (element-type utf8): List of contact
* identifiers
*/
GSList *
shell_contact_system_initial_search (ShellContactSystem *self,
GSList *terms)
{
FolksIndividual *individual;
GSList *results = NULL;
GeeMap *individuals = NULL;
ContactSearchResult *result;
GeeMapIterator *iter;
gpointer key;
guint weight;
GSList *normalized_terms = normalize_terms (terms);
g_return_val_if_fail (SHELL_IS_CONTACT_SYSTEM (self), NULL);
individuals = folks_individual_aggregator_get_individuals (self->priv->aggregator);
iter = gee_map_map_iterator (individuals);
while (gee_map_iterator_next (iter))
{
individual = gee_map_iterator_get_value (iter);
weight = do_match (self, individual, normalized_terms);
if (weight != 0)
{
key = gee_map_iterator_get_key (iter);
result = g_slice_new (ContactSearchResult);
result->key = (gchar *) key;
result->weight = weight;
results = g_slist_append (results, result);
}
g_object_unref (individual);
}
g_object_unref (iter);
g_slist_free_full (normalized_terms, (GDestroyNotify) g_free);
return sort_and_prepare_results (results);
}
/**
* shell_contact_system_subsearch:
* @shell: A #ShellContactSystem
* @previous_results: (element-type utf8): List of previous results
* @terms: (element-type utf8): List of terms, logical AND
*
* Search through a previous result set; for more information see
* js/ui/search.js.
*
* Returns: (transfer container) (element-type utf8): List of contact
* identifiers
*/
GSList *
shell_contact_system_subsearch (ShellContactSystem *self,
GSList *previous_results,
GSList *terms)
{
return shell_contact_system_initial_search (self, terms);
}

View File

@ -1,53 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __SHELL_CONTACT_SYSTEM_H__
#define __SHELL_CONTACT_SYSTEM_H__
#include <clutter/clutter.h>
#include <gio/gio.h>
#include <folks/folks.h>
#define SHELL_TYPE_CONTACT_SYSTEM (shell_contact_system_get_type ())
#define SHELL_CONTACT_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_CONTACT_SYSTEM, ShellContactSystem))
#define SHELL_CONTACT_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_CONTACT_SYSTEM, ShellContactSystemClass))
#define SHELL_IS_CONTACT_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_CONTACT_SYSTEM))
#define SHELL_IS_CONTACT_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_CONTACT_SYSTEM))
#define SHELL_CONTACT_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_CONTACT_SYSTEM, ShellContactSystemClass))
typedef struct _ShellContactSystem ShellContactSystem;
typedef struct _ShellContactSystemClass ShellContactSystemClass;
typedef struct _ShellContactSystemPrivate ShellContactSystemPrivate;
struct _ShellContactSystem
{
GObject parent;
ShellContactSystemPrivate *priv;
};
struct _ShellContactSystemClass
{
GObjectClass parent_class;
};
GType shell_contact_system_get_type (void) G_GNUC_CONST;
/* Methods */
ShellContactSystem * shell_contact_system_get_default (void);
GeeMap *shell_contact_system_get_all (ShellContactSystem *self);
FolksIndividual *shell_contact_system_get_individual (ShellContactSystem *self,
gchar *id);
char * shell_contact_system_get_email_for_display (ShellContactSystem *self,
FolksIndividual *individual);
GSList * shell_contact_system_initial_search (ShellContactSystem *shell,
GSList *terms);
GSList * shell_contact_system_subsearch (ShellContactSystem *shell,
GSList *previous_results,
GSList *terms);
#endif /* __SHELL_CONTACT_SYSTEM_H__ */

View File

@ -14,7 +14,7 @@ void _shell_embedded_window_allocate (ShellEmbeddedWindow *window,
int width, int width,
int height); int height);
void _shell_embedded_window_realize (ShellEmbeddedWindow *window); void _shell_embedded_window_map (ShellEmbeddedWindow *window);
void _shell_embedded_window_unrealize (ShellEmbeddedWindow *window); void _shell_embedded_window_unmap (ShellEmbeddedWindow *window);
#endif /* __SHELL_EMBEDDED_WINDOW_PRIVATE_H__ */ #endif /* __SHELL_EMBEDDED_WINDOW_PRIVATE_H__ */

View File

@ -19,20 +19,10 @@
* - ShellGtkEmbed is created for the ShellEmbeddedWindow * - ShellGtkEmbed is created for the ShellEmbeddedWindow
* - actor is added to a stage * - actor is added to a stage
* *
* Ideally, the way it would work is that the GtkWindow is mapped * The way it works is that the GtkWindow is mapped if and only if both:
* if and only if both:
* *
* - GTK_WIDGET_VISIBLE (window) [widget has been shown] * - gtk_widget_visible (window) [widget has been shown]
* - Actor is mapped [actor and all parents visible, actor in stage] * - Actor is mapped [actor and all parents visible, actor in stage]
*
* Implementing this perfectly is not currently possible, due to problems
* in Clutter, see:
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1138
*
* So until that is fixed we use the "realized" state of the ClutterActor
* as a stand-in for the ideal mapped state, this will work as long
* as the ClutterActor and all its parents are in fact visible.
*/ */
G_DEFINE_TYPE (ShellEmbeddedWindow, shell_embedded_window, GTK_TYPE_WINDOW); G_DEFINE_TYPE (ShellEmbeddedWindow, shell_embedded_window, GTK_TYPE_WINDOW);
@ -232,7 +222,7 @@ _shell_embedded_window_set_actor (ShellEmbeddedWindow *window,
window->priv->actor = actor; window->priv->actor = actor;
if (actor && if (actor &&
CLUTTER_ACTOR_IS_REALIZED (actor) && CLUTTER_ACTOR_IS_MAPPED (actor) &&
gtk_widget_get_visible (GTK_WIDGET (window))) gtk_widget_get_visible (GTK_WIDGET (window)))
gtk_widget_map (GTK_WIDGET (window)); gtk_widget_map (GTK_WIDGET (window));
} }
@ -272,7 +262,7 @@ _shell_embedded_window_allocate (ShellEmbeddedWindow *window,
} }
void void
_shell_embedded_window_realize (ShellEmbeddedWindow *window) _shell_embedded_window_map (ShellEmbeddedWindow *window)
{ {
g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window)); g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));
@ -281,7 +271,7 @@ _shell_embedded_window_realize (ShellEmbeddedWindow *window)
} }
void void
_shell_embedded_window_unrealize (ShellEmbeddedWindow *window) _shell_embedded_window_unmap (ShellEmbeddedWindow *window)
{ {
g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window)); g_return_if_fail (SHELL_IS_EMBEDDED_WINDOW (window));

View File

@ -1191,35 +1191,6 @@ shell_global_reexec_self (ShellGlobal *global)
g_ptr_array_free (arr, TRUE); g_ptr_array_free (arr, TRUE);
} }
/**
* shell_global_gc:
* @global: A #ShellGlobal
*
* Start a garbage collection process. For more information, see
* https://developer.mozilla.org/En/JS_GC
*/
void
shell_global_gc (ShellGlobal *global)
{
JSContext *context = gjs_context_get_native_context (global->js_context);
JS_GC (context);
}
/**
* shell_global_maybe_gc:
* @global: A #ShellGlobal
*
* Start a garbage collection process when it would free up enough memory
* to be worth the amount of time it would take
* https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_MaybeGC
*/
void
shell_global_maybe_gc (ShellGlobal *global)
{
gjs_context_maybe_gc (global->js_context);
}
static void static void
shell_global_on_gc (GjsContext *context, shell_global_on_gc (GjsContext *context,
ShellGlobal *global) ShellGlobal *global)
@ -1511,13 +1482,6 @@ run_leisure_functions (gpointer data)
if (global->work_count > 0) if (global->work_count > 0)
return FALSE; return FALSE;
/* Previously we called gjs_maybe_gc(). However, it simply doesn't
* trigger often enough. Garbage collection is very fast here, so
* let's just aggressively GC. This will help avoid both heap
* fragmentation, and the GC kicking in when we don't want it to.
*/
gjs_context_gc (global->js_context);
/* No leisure closures, so we are done */ /* No leisure closures, so we are done */
if (global->leisure_closures == NULL) if (global->leisure_closures == NULL)
return FALSE; return FALSE;

View File

@ -84,11 +84,6 @@ void shell_global_get_pointer (ShellGlobal *global,
int *y, int *y,
ClutterModifierType *mods); ClutterModifierType *mods);
/* JavaScript utilities */
void shell_global_gc (ShellGlobal *global);
void shell_global_maybe_gc (ShellGlobal *global);
typedef struct { typedef struct {
guint glibc_uordblks; guint glibc_uordblks;

View File

@ -199,23 +199,23 @@ shell_gtk_embed_allocate (ClutterActor *actor,
} }
static void static void
shell_gtk_embed_realize (ClutterActor *actor) shell_gtk_embed_map (ClutterActor *actor)
{ {
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor); ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
_shell_embedded_window_realize (embed->priv->window); _shell_embedded_window_map (embed->priv->window);
CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->realize (actor); CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->map (actor);
} }
static void static void
shell_gtk_embed_unrealize (ClutterActor *actor) shell_gtk_embed_unmap (ClutterActor *actor)
{ {
ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor); ShellGtkEmbed *embed = SHELL_GTK_EMBED (actor);
_shell_embedded_window_unrealize (embed->priv->window); _shell_embedded_window_unmap (embed->priv->window);
CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->unrealize (actor); CLUTTER_ACTOR_CLASS (shell_gtk_embed_parent_class)->unmap (actor);
} }
static void static void
@ -243,8 +243,8 @@ shell_gtk_embed_class_init (ShellGtkEmbedClass *klass)
actor_class->get_preferred_width = shell_gtk_embed_get_preferred_width; actor_class->get_preferred_width = shell_gtk_embed_get_preferred_width;
actor_class->get_preferred_height = shell_gtk_embed_get_preferred_height; actor_class->get_preferred_height = shell_gtk_embed_get_preferred_height;
actor_class->allocate = shell_gtk_embed_allocate; actor_class->allocate = shell_gtk_embed_allocate;
actor_class->realize = shell_gtk_embed_realize; actor_class->map = shell_gtk_embed_map;
actor_class->unrealize = shell_gtk_embed_unrealize; actor_class->unmap = shell_gtk_embed_unmap;
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_WINDOW, PROP_WINDOW,

View File

@ -406,7 +406,7 @@ shell_network_agent_get_secrets (NMSecretAgent *agent,
g_hash_table_replace (self->priv->requests, request->request_id, request); g_hash_table_replace (self->priv->requests, request->request_id, request);
if ((flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) || if ((flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW) ||
(flags && NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION ((flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
&& is_connection_always_ask (request->connection))) && is_connection_always_ask (request->connection)))
{ {
request_secrets_from_ui (request); request_secrets_from_ui (request);

View File

@ -2,6 +2,7 @@
#include "config.h" #include "config.h"
#define GST_USE_UNSTABLE_API
#include <gst/base/gstpushsrc.h> #include <gst/base/gstpushsrc.h>
#include "shell-recorder-src.h" #include "shell-recorder-src.h"
@ -34,11 +35,10 @@ enum {
/* Special marker value once the source is closed */ /* Special marker value once the source is closed */
#define RECORDER_QUEUE_END ((GstBuffer *)1) #define RECORDER_QUEUE_END ((GstBuffer *)1)
GST_BOILERPLATE(ShellRecorderSrc, shell_recorder_src, GstPushSrc, GST_TYPE_PUSH_SRC); G_DEFINE_TYPE(ShellRecorderSrc, shell_recorder_src, GST_TYPE_PUSH_SRC);
static void static void
shell_recorder_src_init (ShellRecorderSrc *src, shell_recorder_src_init (ShellRecorderSrc *src)
ShellRecorderSrcClass *klass)
{ {
gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
@ -47,11 +47,6 @@ shell_recorder_src_init (ShellRecorderSrc *src,
g_mutex_init (src->mutex); g_mutex_init (src->mutex);
} }
static void
shell_recorder_src_base_init (gpointer klass)
{
}
static gboolean static gboolean
shell_recorder_src_memory_used_update_idle (gpointer data) shell_recorder_src_memory_used_update_idle (gpointer data)
{ {
@ -91,18 +86,18 @@ shell_recorder_src_create (GstPushSrc *push_src,
GstBuffer *buffer; GstBuffer *buffer;
if (src->closed) if (src->closed)
return GST_FLOW_UNEXPECTED; return GST_FLOW_EOS;
buffer = g_async_queue_pop (src->queue); buffer = g_async_queue_pop (src->queue);
if (buffer == RECORDER_QUEUE_END) if (buffer == RECORDER_QUEUE_END)
{ {
/* Returning UNEXPECTED here will cause a EOS message to be sent */ /* Returning UNEXPECTED here will cause a EOS message to be sent */
src->closed = TRUE; src->closed = TRUE;
return GST_FLOW_UNEXPECTED; return GST_FLOW_EOS;
} }
shell_recorder_src_update_memory_used (src, shell_recorder_src_update_memory_used (src,
- (int)(GST_BUFFER_SIZE(buffer) / 1024)); - (int)(gst_buffer_get_size(buffer) / 1024));
*buffer_out = buffer; *buffer_out = buffer;
@ -146,7 +141,7 @@ shell_recorder_src_finalize (GObject *object)
g_mutex_clear (src->mutex); g_mutex_clear (src->mutex);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (shell_recorder_src_parent_class)->finalize (object);
} }
static void static void
@ -250,9 +245,9 @@ shell_recorder_src_add_buffer (ShellRecorderSrc *src,
g_return_if_fail (SHELL_IS_RECORDER_SRC (src)); g_return_if_fail (SHELL_IS_RECORDER_SRC (src));
g_return_if_fail (src->caps != NULL); g_return_if_fail (src->caps != NULL);
gst_buffer_set_caps (buffer, src->caps); gst_base_src_set_caps (GST_BASE_SRC (src), src->caps);
shell_recorder_src_update_memory_used (src, shell_recorder_src_update_memory_used (src,
(int) (GST_BUFFER_SIZE(buffer) / 1024)); (int)(gst_buffer_get_size(buffer) / 1024));
g_async_queue_push (src->queue, gst_buffer_ref (buffer)); g_async_queue_push (src->queue, gst_buffer_ref (buffer));
} }

View File

@ -8,6 +8,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#define GST_USE_UNSTABLE_API
#include <gst/gst.h> #include <gst/gst.h>
#include "shell-recorder-src.h" #include "shell-recorder-src.h"
@ -434,6 +435,7 @@ static void
recorder_draw_cursor (ShellRecorder *recorder, recorder_draw_cursor (ShellRecorder *recorder,
GstBuffer *buffer) GstBuffer *buffer)
{ {
GstMapInfo info;
cairo_surface_t *surface; cairo_surface_t *surface;
cairo_t *cr; cairo_t *cr;
@ -452,7 +454,8 @@ recorder_draw_cursor (ShellRecorder *recorder,
if (!recorder->cursor_image) if (!recorder->cursor_image)
return; return;
surface = cairo_image_surface_create_for_data (GST_BUFFER_DATA(buffer), gst_buffer_map (buffer, &info, GST_MAP_WRITE);
surface = cairo_image_surface_create_for_data (info.data,
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_ARGB32,
recorder->stage_width, recorder->stage_width,
recorder->stage_height, recorder->stage_height,
@ -467,6 +470,7 @@ recorder_draw_cursor (ShellRecorder *recorder,
cairo_destroy (cr); cairo_destroy (cr);
cairo_surface_destroy (surface); cairo_surface_destroy (surface);
gst_buffer_unmap (buffer, &info);
} }
/* Draw an overlay indicating how much of the target memory is used /* Draw an overlay indicating how much of the target memory is used
@ -526,6 +530,8 @@ recorder_record_frame (ShellRecorder *recorder)
guint size; guint size;
GstClockTime now; GstClockTime now;
g_return_if_fail (recorder->current_pipeline != NULL);
/* If we get into the red zone, stop buffering new frames; 13/16 is /* If we get into the red zone, stop buffering new frames; 13/16 is
* a bit more than the 3/4 threshold for a red indicator to keep the * a bit more than the 3/4 threshold for a red indicator to keep the
* indicator from flashing between red and yellow. */ * indicator from flashing between red and yellow. */
@ -549,10 +555,11 @@ recorder_record_frame (ShellRecorder *recorder)
0, 0, recorder->stage_width, recorder->stage_height); 0, 0, recorder->stage_width, recorder->stage_height);
buffer = gst_buffer_new(); buffer = gst_buffer_new();
GST_BUFFER_SIZE(buffer) = size; gst_buffer_insert_memory (buffer, -1,
GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = data; gst_memory_new_wrapped (0, data, size, 0,
size, data, g_free));
GST_BUFFER_TIMESTAMP(buffer) = now - recorder->start_time; GST_BUFFER_PTS(buffer) = now - recorder->start_time;
recorder_draw_cursor (recorder, buffer); recorder_draw_cursor (recorder, buffer);
@ -1044,23 +1051,18 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
{ {
GstCaps *caps; GstCaps *caps;
/* The data is always native-endian xRGB; ffmpegcolorspace /* The data is always native-endian xRGB; videoconvert
* doesn't support little-endian xRGB, but does support * doesn't support little-endian xRGB, but does support
* big-endian BGRx. * big-endian BGRx.
*/ */
caps = gst_caps_new_simple ("video/x-raw-rgb", caps = gst_caps_new_simple ("video/x-raw",
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
"format", G_TYPE_STRING, "BGRx",
#else
"format", G_TYPE_STRING, "xRGB",
#endif
"bpp", G_TYPE_INT, 32, "bpp", G_TYPE_INT, 32,
"depth", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24,
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
"red_mask", G_TYPE_INT, 0x0000ff00,
"green_mask", G_TYPE_INT, 0x00ff0000,
"blue_mask", G_TYPE_INT, 0xff000000,
#else
"red_mask", G_TYPE_INT, 0xff0000,
"green_mask", G_TYPE_INT, 0x00ff00,
"blue_mask", G_TYPE_INT, 0x0000ff,
#endif
"endianness", G_TYPE_INT, G_BIG_ENDIAN,
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1, "framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
"width", G_TYPE_INT, pipeline->recorder->stage_width, "width", G_TYPE_INT, pipeline->recorder->stage_width,
"height", G_TYPE_INT, pipeline->recorder->stage_height, "height", G_TYPE_INT, pipeline->recorder->stage_height,
@ -1078,7 +1080,7 @@ recorder_pipeline_add_source (RecorderPipeline *pipeline)
{ {
GstPad *sink_pad = NULL, *src_pad = NULL; GstPad *sink_pad = NULL, *src_pad = NULL;
gboolean result = FALSE; gboolean result = FALSE;
GstElement *ffmpegcolorspace; GstElement *videoconvert;
sink_pad = gst_bin_find_unlinked_pad (GST_BIN (pipeline->pipeline), GST_PAD_SINK); sink_pad = gst_bin_find_unlinked_pad (GST_BIN (pipeline->pipeline), GST_PAD_SINK);
if (sink_pad == NULL) if (sink_pad == NULL)
@ -1097,19 +1099,19 @@ recorder_pipeline_add_source (RecorderPipeline *pipeline)
recorder_pipeline_set_caps (pipeline); recorder_pipeline_set_caps (pipeline);
/* The ffmpegcolorspace element is a generic converter; it will convert /* The videoconvert element is a generic converter; it will convert
* our supplied fixed format data into whatever the encoder wants * our supplied fixed format data into whatever the encoder wants
*/ */
ffmpegcolorspace = gst_element_factory_make ("ffmpegcolorspace", NULL); videoconvert = gst_element_factory_make ("videoconvert", NULL);
if (!ffmpegcolorspace) if (!videoconvert)
{ {
g_warning("Can't create ffmpegcolorspace element"); g_warning("Can't create videoconvert element");
goto out; goto out;
} }
gst_bin_add (GST_BIN (pipeline->pipeline), ffmpegcolorspace); gst_bin_add (GST_BIN (pipeline->pipeline), videoconvert);
gst_element_link_many (pipeline->src, ffmpegcolorspace, NULL); gst_element_link_many (pipeline->src, videoconvert, NULL);
src_pad = gst_element_get_static_pad (ffmpegcolorspace, "src"); src_pad = gst_element_get_static_pad (videoconvert, "src");
if (!src_pad) if (!src_pad)
{ {

View File

@ -773,34 +773,6 @@ shell_parse_search_provider (const char *data,
return FALSE; return FALSE;
} }
/**
* shell_shader_effect_set_double_uniform:
* @effect: The #ClutterShaderEffect
* @name: The name of the uniform
* @value: The value to set it to.
*
* Set a double uniform on a ClutterShaderEffect.
*
* The problem here is that JavaScript doesn't have more than
* one number type, and gjs tries to automatically guess what
* type we want to set a GValue to. If the number is "1.0" or
* something, it will use an integer, which will cause errors
* in GLSL.
*/
void
shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect,
const gchar *name,
gdouble value)
{
GValue gvalue = G_VALUE_INIT;
g_value_init (&gvalue, G_TYPE_DOUBLE);
g_value_set_double (&gvalue, value);
clutter_shader_effect_set_uniform_value (effect,
name,
&gvalue);
}
/** /**
* shell_session_is_active_for_systemd: * shell_session_is_active_for_systemd:
* *

View File

@ -39,10 +39,6 @@ gboolean shell_parse_search_provider (const char *data,
char **icon_data_uri, char **icon_data_uri,
GError **error); GError **error);
void shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect,
const gchar *name,
gdouble value);
gboolean shell_session_is_active_for_systemd (void); gboolean shell_session_is_active_for_systemd (void);
gboolean shell_util_wifexited (int status, gboolean shell_util_wifexited (int status,

View File

@ -299,7 +299,7 @@ get_app_for_window (ShellWindowTracker *tracker,
result = shell_app_system_lookup_wmclass (app_system, result = shell_app_system_lookup_wmclass (app_system,
meta_window_get_wm_class (window)); meta_window_get_wm_class (window));
if (result != NULL) if (result != NULL)
return result; return g_object_ref (result);
result = get_app_from_window_pid (tracker, window); result = get_app_from_window_pid (tracker, window);
if (result != NULL) if (result != NULL)

View File

@ -302,6 +302,13 @@ st_icon_style_changed (StWidget *widget)
st_shadow_unref (priv->shadow_spec); st_shadow_unref (priv->shadow_spec);
priv->shadow_spec = NULL; priv->shadow_spec = NULL;
} }
if (priv->shadow_material)
{
cogl_handle_unref (priv->shadow_material);
priv->shadow_material = COGL_INVALID_HANDLE;
}
priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow"); priv->shadow_spec = st_theme_node_get_shadow (theme_node, "icon-shadow");
if (priv->shadow_spec && priv->shadow_spec->inset) if (priv->shadow_spec && priv->shadow_spec->inset)

View File

@ -1,5 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#define GST_USE_UNSTABLE_API
#include "shell-recorder.h" #include "shell-recorder.h"
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <gst/gst.h> #include <gst/gst.h>

View File

@ -11,6 +11,7 @@ TEST_JS = \
interactive/calendar.js \ interactive/calendar.js \
interactive/css-fonts.js \ interactive/css-fonts.js \
interactive/entry.js \ interactive/entry.js \
interactive/gapplication.js \
interactive/icons.js \ interactive/icons.js \
interactive/inline-style.js \ interactive/inline-style.js \
interactive/scrolling.js \ interactive/scrolling.js \

View File

@ -1,4 +1,5 @@
#!/usr/bin/env gjs #!/usr/bin/env gjs
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gdk = imports.gi.Gdk; const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@ -24,10 +25,11 @@ function do_action_state_change(action) {
function main() { function main() {
Gtk.init(null, null); Gtk.init(null, null);
Gdk.set_program_class('test-gjsgapp');
let app = new Gtk.Application({ application_id: 'org.gnome.Shell.GtkApplicationTest' }); let app = new Gtk.Application({ application_id: 'org.gnome.Shell.GtkApplicationTest' });
app.connect('activate', function() { app.connect('activate', function() {
print ("Activated"); print ("Activated");
}); });
let action = new Gio.SimpleAction({ name: 'one' }); let action = new Gio.SimpleAction({ name: 'one' });
@ -87,15 +89,14 @@ function main() {
item.set_action_and_target_value('app.parameter-int', GLib.Variant.new('u', 43)); item.set_action_and_target_value('app.parameter-int', GLib.Variant.new('u', 43));
menu.append_item(item); menu.append_item(item);
app.set_app_menu(menu);
let window = null; let window = null;
app.connect_after('startup', function(app) { app.connect_after('startup', function(app) {
window = new Gtk.ApplicationWindow({ title: "Test Application", application: app }); app.set_app_menu(menu);
window = new Gtk.ApplicationWindow({ title: "Test Application", application: app });
}); });
app.connect('activate', function(app) { app.connect('activate', function(app) {
window.present(); window.present();
}); });
app.run(null); app.run(null);