Compare commits

...

140 Commits

Author SHA1 Message Date
2639e30d9c Bump version to 3.11.2
Update NEWS.
2013-11-13 21:24:30 +01:00
78a0218a91 build: Add built js-resources to CLEANFILES 2013-11-13 21:24:30 +01:00
e12bf8daed shellDBus: Fix error message returned from Eval
Annoyingly, `message` on errors are non-enumerable, which mean that
JSON.stringify on the error will produce `{}`. Just cast it to a string
for now.
2013-11-13 15:15:03 -05:00
04e2072e2c Updated Tamil Translations 2013-11-11 14:45:06 +05:30
7bafe20a34 Update Chinese simplified translation 2013-11-10 14:19:51 +08:00
554d5aeb7c More invalid source fixes
https://bugzilla.gnome.org/show_bug.cgi?id=711732
2013-11-09 17:58:59 +01:00
3991d2729d dash: Make sure we clear the timeout IDs for the label tooltip
https://bugzilla.gnome.org/show_bug.cgi?id=711732
2013-11-09 11:44:44 -05:00
5bc8a0860a tweener: Remove the onAnimationStart/onAnimationComplete callbacks
Our gnome-shell tweener integration has had hooks to determine when
the tweens have started and completed... except that they had a bug
in them. When a tween completed, it queued an idle handler to run
the callback in. If no tweens were running when the idle was removing,
it reset the tween state that contained the idle handler ID. It also
returned false, meaning that the source would always get removed.

If the actor had a tween in-flight when the idle was fired, it wouldn't
clean up after itself. While this is also a simple bug fix, remove the
callback so we don't queue unnecessary, unused idles.

https://bugzilla.gnome.org/show_bug.cgi?id=711732
2013-11-09 11:44:44 -05:00
ad03fb0815 app-system: Add back StartupWMClass matching
While unfortunate that we still have to scan all apps with get_all(),
support for this feature will be short-lived, so hopefully we can drop
it in the future as new apps adapt to the desktop file / app ID
recommendations.

For now, simply scan all desktop IDs.

https://bugzilla.gnome.org/show_bug.cgi?id=711631
2013-11-07 16:35:03 -05:00
e10d2a68f3 app-system: Put back support for the installed-changed signal
Use the new GAppInfoMonitor that Ryan added to glib to know when the
set of apps has changed.

https://bugzilla.gnome.org/show_bug.cgi?id=711631
2013-11-07 16:35:03 -05:00
213ee8d381 ShellApp: Connect applications to systemd journal (if available)
Systemd-for-the-user-session would also do this, but that's a deeply
invasive change that I may not actually get to this cycle.  This
change is tiny and non-invasive, but provides an important benefit:
You can actually reliably tell *which* applications are logging which
messages (assuming they're launched by the shell).

This actually complements a recent change in DBus:
See https://bugs.freedesktop.org/show_bug.cgi?id=68559
which does a similar thing for bus activated apps.

https://bugzilla.gnome.org/show_bug.cgi?id=711626
2013-11-07 13:44:03 -05:00
52b1a1b835 popupMenu: Fix removing the active menu from PopupMenuManager
Commit b42af9aa99 changed the parameter list of _closeMenu()
to account for changes in the GrabHelper ungrab mechanism, but
didn't update other callers.

https://bugzilla.gnome.org/show_bug.cgi?id=709806
2013-11-07 00:09:50 +01:00
fce2930b85 dnd: Don't queue an idle handler if we already have one
Removing an existing source before scheduling a new one is not wrong,
but slightly less effective than doing nothing and relying on the
previously created source to do the job.

https://bugzilla.gnome.org/show_bug.cgi?id=711555
2013-11-06 18:36:42 +01:00
735f589b1c dnd: Don't try to remove an invalid idle source
As the handler returns false, the corresponding source is removed
automatically and its id invalidated. Reset the id to 0 to reflect
this, otherwise newer versions of GLib will print a warning when
we later try to remove it explicitly.

https://bugzilla.gnome.org/show_bug.cgi?id=711555
2013-11-06 16:40:50 +01:00
69f17da5ca trivial: Fix the signedness of boolean fields
The standard old kludge with gboolean being signed, not unsigned.
Encountered while printing the values for debugging.

https://bugzilla.gnome.org/show_bug.cgi?id=644306
2013-11-05 09:11:49 -05:00
5c0ee02251 trivial: st-widget: Remove super old 'stylable' property
I don't think we ever used this, even way back in 3.0...

https://bugzilla.gnome.org/show_bug.cgi?id=644306
2013-11-04 21:11:00 -05:00
0cb4c7e437 Updated German translation 2013-11-04 21:05:26 +01:00
842c792868 search: Only do a subsearch if the previous results have returned from DBus
There's a potential race condition in the search code: if we have an
outstanding search call to a provider for search "A", and if before it comes
back we do a subsearch for "AB", we won't have any results to pass along.

Previously, we used an empty list when storing the provider results, so we
effectively told the remote search app to filter through this empty list for
any search results that meet the new query, meaning we showed the user 0
results for the provider in this case.

Now that we don't store an empty list, but instead store `undefined`, this race
raises a warning. Solve it by doing an initial search query in this case
instead.

The search code isn't too smart about chained subsearches: now, if we hit this
race while already on a subsearch, we'll do an initial search for the subsearch
query instead, but that is much better than showing the user nothing. This
could be fixed in the future for a performance improvement.

Reviewed-by: Florian Müllner <fmuellner@gnome.org>
2013-11-04 14:50:45 -05:00
4ba8518462 messageTray: Use a regular tween when expanding the notification
When a notification becomes expanded, it's either already shown,
or in the process of being shown. Don't set the state to SHOWING
again, which confuses our state machine.
2013-11-04 14:25:29 -05:00
143dfb6246 messageTray: Simplify code
If notificationRemoved, then mustClose is true, so we don't need to
double-check for this.
2013-11-04 14:16:28 -05:00
da4238ec68 Synchronize shell startup
The asynchronous nature of extension loading, session loading, and more,
makes the code racy as to what is initialized first, and hard to debug.
Additionally, since gjs is single-threaded, the only code we're running
in a thread anyway is readdir, which is going to be I/O bound, so the
code here is actually likely to be faster.

Drop this in favor of some good old fashioned synchronous loading.
2013-11-04 11:50:20 -05:00
5f9e3edbe1 notificationDaemon: Only store policies for "real" apps
Fake, window-backed apps should not have a policy for them.
2013-11-04 11:47:43 -05:00
1c68aee577 screenShield: Fix details in notifications
bannerBodyMarkup is a boolean flag to indicate that bannerBodyText
contains markup, not the markup text itself.

https://bugzilla.gnome.org/show_bug.cgi?id=711416
2013-11-04 16:46:25 +01:00
e8d9a4bd49 screencast: Validate parameters of ScreencastArea
... just as we do for screenshots.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:21:45 +01:00
9520e87a38 screencast: Fix disabling screencasts via session mode
If screencasts are disabled, we return a DBus error, but still start
the recording happily - add early returns in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:21:45 +01:00
f9f5004909 screenshot: Extend ScreenshotArea parameter validation
We currently only ensure that width and height are positive, so it
is still possible to pass in values that don't make any sense at all
(which may even result in a crash when exceeding limits imposed by
X11).
There is nothing to screenshot outside the actual screen area, so
restrict the parameters to that.

https://bugzilla.gnome.org/show_bug.cgi?id=699752
2013-11-04 16:21:45 +01:00
4f7014b2d5 networkAgent: Make sure to update the OK button on dialog pop up
For consistency.
2013-11-04 08:55:59 -05:00
01dbfddb64 workspace: Remove unused includes and constants 2013-11-04 10:32:17 +01:00
6266a22d86 Updated Greek translation 2013-11-04 10:53:08 +02:00
09fe31179a app-system: Fix memory leak
The shell app takes a ref on the info.
2013-11-03 16:20:00 -05:00
78343f4837 app-system: Fix bad code
I had this locally, but forgot to amend before pushing apparently
2013-11-03 16:19:53 -05:00
a5619bc0a3 app-system: Fix const warning 2013-11-03 12:50:21 -05:00
dcb28aad2a app-system: Fix the keys in the id_to_app table
The ID that's passed to us isn't usable as a key to store, as it's
probably junk after the method returns. Use the app's storage for
the ID instead.
2013-11-03 12:10:00 -05:00
754cf172f5 Updated Norwegian bokmål translation 2013-11-03 16:03:44 +01:00
7890af1659 app-system: Lazily create ShellApps for apps we care about
Rather than create all ShellApps up-front, create them lazily. We really
had no reason to do this before as we were scanning GMenu to get all the
apps, but doing this can remove a need for get_all, which is slow and
memory-hungry.
2013-11-02 20:50:35 -04:00
d27d9fe694 app-system: Remove use of gnome-menus internally
We want to transition to a system in the future where we have a desktop
file cache. As we no longer differentiate categories or similar, it no
longer makes sense to have app visibility based on categories. Thus,
we no longer need to use gnome-menus to list all apps. The potential
issue here is reloading all desktop files when new files are created,
but this can be dealt with individually.

The "All Applications" view still uses gnome-menus.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
634a599db6 appDisplay: Ignore the NoDisplay flag for directories
This makes us match the native app search.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
5d0d859a1f app-system: Remove visible_id_to_app
Since appDisplay.js makes its own GMenu tree, it's not necessary
anymore. This does mean that searches will show apps in NoDisplay
categories, but that's an obscure enough edge case not to matter.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
40c966fcd6 app-system: Remove lookup_app_for_path
It's absurdly silly. Just modify the one place that uses it
to be better.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
d9245598a4 app-system: Remove known_vendor_prefixes
This does remove support for legacy prefixed app infos with
subdirs, but since we want to remove support for the menu spec,
let's not even bother.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
03b0f4b16b app-system: Remove get_tree
Make clients construct their own gmenu tree if they need it.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:37 -04:00
2daa0d057b app-system: Map wmclass to ID rather than apps
This makes the refcounting and memory management easier to understand.
2013-11-02 20:12:36 -04:00
76eca409a3 app-system: Don't use gmenu_tree_entry_get_desktop_app_info
It's a broken method when it comes to giving us a useful GDesktopAppInfo,
and it's hard to fix libgmenu properly, so simply recreate the app info
using the desktop file ID that libgmenu has.
2013-11-02 20:12:36 -04:00
d84b018ba7 app: Port to be based on GDesktopAppInfo
We weren't using the GMenuTreeEntry for anything special anymore,
so remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:36 -04:00
027c3d1661 app-system: Remove lookup_app_by_tree_entry
We want to move away from gnome-menus eventually, so the simple
utility method isn't really worth keeping around. Reimplement it
in the one place that uses it.

https://bugzilla.gnome.org/show_bug.cgi?id=698486
2013-11-02 20:12:36 -04:00
4965b1ca7b search: Fix previous commit
It was pushed by accident before it was tested...
2013-11-02 20:11:13 -04:00
9cd7ea9371 search: Make the internal search interface callback-based
Long ago, the search system worked in a synchronous manner: providers
were given a query, and results were collected in a single array of
[provider, results] pairs, and then the search display was updated
from that.

We introduced an asynchronous search system when we wanted to potentially
add a Zeitgeist search provider to the Shell in 3.2. For a while, search
providers were either async or sync, which worked by storing a dummy array
in the results, and adding a method for search providers to add results
later.

Later, we removed the search system entirely and ported the remaining
search providers to simply use the API to modify the empty array, but the
remains of the synchronous search system with its silly array still
lingered.

Finally, it's time to modernize. Promises^WCallbacks are the future.

Port the one remaining in-shell search engine (app search) to the new
callback based system, and simplify the remote search system in the
process.
2013-11-02 20:07:06 -04:00
dc2468b27b remoteSearch: Do filtering here of providers here
We already do ordering at load time, so why not filtering?
2013-11-02 20:07:06 -04:00
ea2451d882 overviewControls: Fix bad expression causing incorrect thumbnails allocation
`a + b ? c : d` is parsed as `(a + b) ? c : d`, not the more intuitive
`a + (b ? c : d)`.

This was causing a bad slide animation and Clutter warnings when coming
out of the overview.
2013-11-02 20:07:06 -04:00
252617bd70 search: Remove unnecessary import and full reference
I'm surprised this worked, actually...
2013-11-02 18:01:26 -04:00
8bd7003ea7 bluetooth: Parse pins starting with 0 correctly
If we have a numeric PIN that starts with 0, it will be treated
as an octal number rather than a number that just starts with 0.
2013-11-02 17:55:54 -04:00
280203158c Updated Russian translation 2013-11-01 23:32:39 +04:00
d456c3f62e system: Restore support for 'disable-restart-buttons'
The org.gnome.login-screen schema contains a key to disable the
power/restart buttons; our support for this fell victim to the
new combined status menu, add it back.

https://bugzilla.gnome.org/show_bug.cgi?id=711244
2013-11-01 13:08:02 +01:00
f64d17963b Support disabling browser plugin
Some downstreams may not want it for security reasons.

https://bugzilla.gnome.org/show_bug.cgi?id=711218
2013-10-31 12:44:51 -04:00
f12378cf7b search: Hide overview when activating result
This was (accidentally?) dropped by commit 3749b09366.

https://bugzilla.gnome.org/show_bug.cgi?id=711205
2013-10-31 16:19:25 +00:00
15ff426be8 shell_global_reexec_self: add support for OpenBSD
https://bugzilla.gnome.org/show_bug.cgi?id=709571
2013-10-31 11:46:59 +01:00
c4a6837d56 build: Make sure built-sources are introspected as needed 2013-10-31 00:01:38 +01:00
e6c28cf509 Revert "overviewControls: Always allocate the actor its full size"
This reverts commit f5a9dbb348.

This broke the alignment of the workspace thumbnail widget. I don't
know why, but let's not break things if we can...
2013-10-30 18:33:13 -04:00
a347a75617 st-theme: Use constructed instead of constructor 2013-10-30 18:33:13 -04:00
7fc2183826 build: Do not ship generated source-files in tarball 2013-10-30 23:29:45 +01:00
b6c3c9891c workspacesView: Make sure to update workspace actors when entering the overview
Otherwise, they will be in the wrong positions.
2013-10-30 18:20:54 -04:00
d401b493a4 search: Fix Return for searching in the overview 2013-10-30 17:43:12 -04:00
da1a8308b6 build: Also look for generated js-resources.* files in builddir 2013-10-30 21:41:52 +01:00
106d827a21 build: Also look for resources in $(builddir)
Since misc/config.js is built, we need to tell the resource compiler
to find it too.

Fixes the build in Continuous where srcdir != builddir.
2013-10-30 14:00:58 -04:00
1ebb162a00 Load JS from GResource
Since gjs can now load JS from a GResource, compile it in the
gnome-shell binary. This should be a bit faster, and make life easier
with JHBuild.
2013-10-30 13:27:16 -04:00
9d2791d9f8 dnd: Don't use reparent for adding actors to the uiGroup
It's deprecated, terrible, and causes get_theme_node crashes.
2013-10-30 13:20:02 -04:00
04a00f6564 loginDialog: Use UserWidget
https://bugzilla.gnome.org/show_bug.cgi?id=706851
2013-10-30 13:19:02 -04:00
a5dd44c77f userWidget: Use the user name if the real name doesn't fit
This meets the new designs.

https://bugzilla.gnome.org/show_bug.cgi?id=706851
2013-10-30 13:19:02 -04:00
8f86fd6bae workspacesView: Simplify the workspacesOnlyOnPrimary implementation
Before, workspacesOnlyOnPrimary was implemented in quite a crazy manner:

 * If workspacesOnlyOnPrimary was false, we'd create one WorkspacesView per
   monitor, with the primary one being a bit special.

 * If workspacesOnlyOnPrimary was true, we'd create one WorkspacesView, and
   additional montiors would be handled inside that WorkspacesView as
   "extra workspaces".

This caused numerous bugs as the two modes weren't consistently
implemented, and a lot of code was duplicated between all the modes.
Fix this by always creating WorkspaceViews, even if it only handles
one interface. We do this by having two different WorkspacesView-ish
classes: WorkspacesView handles the traditional combination of lots
of workspces, and a new ExtraWorkspaceView is in control of only one
workspace.
2013-10-30 13:17:39 -04:00
d5cd534320 workspacesView: Make each WorkspacesView own its set of workspaces
Right now, the workspace update code is complex and spread across parts:
WorkspacesView takes a set of workspaces and looks like it owns them, but
WorkspacesDisplay is actually in charge of setting them up and creating
new ones for each WorkspacesView.

Change initialization and handling to move all of the creation/destruction
responsibilities to WorkspacesView.

We pass in monitorIndex into each WorkspacesView, which is a lie in the
workspacesOnlyOnPrimary case, as the primary WorkspacesView currently has
the responsibility of handling the extra workspaces on all the other
monitors. The commit will clean this up and punt the responsibility back
to WorkspacesDisplay.
2013-10-30 13:17:39 -04:00
a5a6fd3bc2 workspacesView: Don't tween the upper of our scroll adjustment
This really doesn't make sense. The new upper should be the new workspace
index as soon as it's available.
2013-10-30 13:17:39 -04:00
287ddda5df workspacesView: Don't zoom into the overview based on a signal
Instead, simply have somebody else call us, like we do for hiding
the overview as well.
2013-10-30 13:17:39 -04:00
7747f1c31d workspacesView: Don't use a drag monitor to get the clone
Just use the new variable passed to the signal.
2013-10-30 13:17:39 -04:00
8097cbbbe3 workspacesView: Don't do any special handling for item-dragging
The code here really only cares about new windows.
2013-10-30 13:17:39 -04:00
e4c07875a3 overview: Send the clone with the window-drag events
This allows clients that care about the actual item we're dragging to
make smarter decisions without adding a drag monitor themselves.
2013-10-30 13:17:38 -04:00
026fd4cf35 workspace: Punt the geometry-fizzling-out logic here 2013-10-30 13:17:38 -04:00
87016f9620 workspacesView: Remove spacing
It's not used in the theme and it complicates the layout code a bit
too much; in fact, if set, things start breaking.
2013-10-30 13:17:38 -04:00
88393f0f65 overviewControls: Move translation-x to SlideLayout
Not because ClutterActor is bad or wrong, but because I always get
confused on the difference, and having them both in SlideLayout
makes the code a bit easier to read and understand.
2013-10-30 13:16:45 -04:00
f5a9dbb348 overviewControls: Always allocate the actor its full size
This is the new Clutter way -- if the actor wants to adjust its
alignment, it will do it itself with its alignment flags.
2013-10-30 13:16:45 -04:00
dbf3bb112c overviewControls: Make getSlide/updateSlide private 2013-10-30 13:16:45 -04:00
f3186bd501 overviewControls: Make visible and inDrag private
These don't need to be accessed from outside SlidingControl,
so don't let them be.
2013-10-30 13:16:44 -04:00
3f1a252b91 overviewControls: Move slideOut on overview hide to the parent as well 2013-10-30 13:16:44 -04:00
1240d6be76 overviewControls: Remove dead code
The parent SlidingControl had an onOverviewShowing, but we had
overridden it with the same code in both subclasses. Just move it
back to SlidingControl.
2013-10-30 13:16:44 -04:00
faf7b62f5c overviewControls: Mark the DashSlider as x_expand
Actors need to expand in order for them to their x_aligns to be taken
into account.
2013-10-30 13:16:44 -04:00
445011b1e5 overviewControls: Add the parent's box into the allocation
Currently, this is always 0, but this will change when we introduce
a custom layout manager into the story.
2013-10-30 13:16:44 -04:00
e630fec63a search: Fix adding items to icon grids 2013-10-30 13:06:56 -04:00
17421e8a63 iconGrid: Actually throw programmer errors
This way we get a backtrace.
2013-10-30 13:05:20 -04:00
af06b78605 searchDisplay: Cache result display actors
When we create a result actor, cache it, so it can be used for
subsearches of the same initial. For now, to keep memory usage
and the stage graph relatively clean, don't persist the actors
across searches, but maybe we should do this in the future.

This also means that we don't query getResultMetas for items
that we've seen in the same initial search.

https://bugzilla.gnome.org/show_bug.cgi?id=704912
2013-10-30 13:01:20 -04:00
3749b09366 searchDisplay: Make the search result actors stateless, by removing terms
We want to cache result actors between searches, so we shouldn't
instantiate them with search-specific info.

https://bugzilla.gnome.org/show_bug.cgi?id=704912
2013-10-30 13:01:20 -04:00
27cac10d0c appDisplay: Use a proper string key for the app search provider
Since we're going to be caching results based on the result ID,
we need to return a string-based result ID to cache on.

https://bugzilla.gnome.org/show_bug.cgi?id=704912
2013-10-30 13:00:47 -04:00
0590962d36 viewSelector: Move all of the provider-loading logic to SearchSystem
The existing provider system is split between a confusing mess of
RemoteSearch, SearchSystem, SearchDisplay, and ViewSelector, partly
because of the vestigal in-shell search system. Move most of the
logic to search.js so it's easier to read.
2013-10-30 12:59:41 -04:00
c0c20d49a5 search: Always fetch the list of search providers
We fetch and store the list of providers from the search system when we
construct SearchResults, but we never update this list when providers are
changed at runtime, causing various bugs making the search not seem as
snappy as it should be. Make sure to always fetch the list of providers
from the search system.
2013-10-30 12:59:31 -04:00
cf7cf45003 Bump version to 3.11.1
Update NEWS.
2013-10-30 17:04:40 +01:00
633dd0d9de notificationDaemon: Save notifications on source destruction
While the existing comment is correct in that a source's notifications
will be destroyed first, the code takes a shortcut which prevents the
Source::count-updated signal from being emitted. Given that the purpose
of the signal is to keep notification counters up-to-date which is
pointless when the source is about to be destroyed, the shortcut makes
sense; just save notifications explicitly in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-30 16:40:33 +01:00
b929320d4c lookingGlass: Remove Memory tab and add a gc Icon to toolbar
With js24 it won't be possible to access gjs memory stats from C code.

https://bugzilla.gnome.org/show_bug.cgi?id=711052
2013-10-30 07:44:34 +11:00
7296bedd8e remove direct access to jsapi
with js24 its not possible to access jsapi directly from C code

https://bugzilla.gnome.org/show_bug.cgi?id=711052
2013-10-30 07:44:34 +11:00
e9fbbf4000 port shell-js to c++
https://bugzilla.gnome.org/show_bug.cgi?id=711052
2013-10-30 07:44:34 +11:00
dd44219aa5 Merge searchDisplay.js and search.js
search.js used to do a lot more, but now that most of the
functionality has been moved to the remote search system,
it doesn't do a lot. Merge searchDisplay.js into it.
2013-10-29 16:02:32 -04:00
8cc1fe007d search: Actually crash when seeing errors from a native search provider
We don't implement many of these, and not catching the error lets us
see stack traces and other such information a lot faster.

https://bugzilla.gnome.org/show_bug.cgi?id=704912
2013-10-29 16:02:32 -04:00
c0b45c9fc4 Remove wanda
It's been broken for quite a bit since we removed Panel.Animation,
and hasn't really ever worked with our new search results. It's also
the only non-remote provider left.

Maybe we'll add it back as a remote provider later, but for now, just
ditch it.
2013-10-29 15:46:49 -04:00
41315f45a9 notificationDaemon: Fix custom icons
The 'icon' property contains a serialized GIcon, so we need to
deserialize it when setting the icon.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-28 12:28:37 +01:00
04d28a0eea notificationDaemon: Fix urgency hint
We currently mark notifications as urgent which merely contain the
'urgent' property, even when set to false. Look at the actual value
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-28 12:28:37 +01:00
1e9cd3f785 Updated Brazilian Portuguese translation
Fixes "Off" translation
2013-10-27 15:46:38 -02:00
f462dd6a4c Updated Hebrew translation
Maybe DL not updated?
2013-10-27 16:40:28 +02:00
34e75fc595 notificationDaemon: Fix button parameter name
Gio ended up using 'target' rather than 'action-target'.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-27 11:38:36 +01:00
dac513e046 notificationDaemon: Unpack button label
deep_unpack() doesn't unpack as deeply as one might hope ...

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-27 11:38:36 +01:00
2c538d247b catch more errors on extensions enable() and disable()
https://bugzilla.gnome.org/show_bug.cgi?id=688331
2013-10-26 16:35:47 +02:00
f3b7f61e54 AltTabSwitcherPopup: check the number of items after creating the popup child
The popup can be empty if the alt-tab switcher is configured
in workspace-only mode, even if there are applications running.

https://bugzilla.gnome.org/show_bug.cgi?id=710745
2013-10-26 16:29:27 +02:00
d47ecf19f5 need space between item in endsession dialog session-list and app-list
https://bugzilla.gnome.org/show_bug.cgi?id=710543
2013-10-26 16:24:41 +02:00
da19b344b5 RemoteSearch: don't autostart dbus search providers at login
Use the new glib flag that allows us to create the proxy immediately
but only activate the service when making the first call.

https://bugzilla.gnome.org/show_bug.cgi?id=708830
2013-10-26 15:20:52 +02:00
eb66407926 NotificationDaemon: fix more fallout
Missing Gtk import for action-icon buttons.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-26 14:56:50 +02:00
61c5b8e7d2 notificationDaemon: Pass the correct id to makeButton()
The function expects the action's ID, not the notification's one.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-25 14:15:10 +01:00
4b09d57ec2 Fix fallout from notification changes
Commit 5f081b8f8d moved code without moving a helper function
used.

https://bugzilla.gnome.org/show_bug.cgi?id=710596
2013-10-25 14:15:10 +01:00
a16f699dfc theme: Add some vertical padding on login screen
This was apparently lost during some rewrite this cycle ...

https://bugzilla.gnome.org/show_bug.cgi?id=710555
2013-10-25 14:15:10 +01:00
b908a3d70a Stringify the xml definitions for E4X removal
https://bugzilla.gnome.org/show_bug.cgi?id=691409
2013-10-25 08:57:27 +11:00
d519c7263e Background: Drop "saturation" related source
"saturation" was removed from MetaBackground in mutter with
https://git.gnome.org/browse/mutter/commit/?id=0e589061
2013-10-23 21:37:27 +02:00
5dedc5d8ba shell-app: Remove old unused functionality 2013-10-21 17:49:46 -04:00
3ca1784ff4 notificationDaemon: Fix activating with a target
Targets should not be unpacked, and action IDs should.
2013-10-21 16:50:18 -04:00
b54d512f3f notificationDaemon: Fix loading/saving of notifications 2013-10-21 16:14:14 -04:00
9d8fb19f55 notificationDaemon: Write notifications out to disk
This allows notifications to persist even after reboots and
gnome-shell restarts.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 14:13:21 -04:00
1ac4ab7edc shell-global: Add new APIs for saving/loading persistent state
https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 14:13:21 -04:00
c9b73ac731 shell-global: Handle empty variants better
In cases where we have an array of 0 elements or similar, the
data returned may be NULL. Since g_file_replace_contents will
assert in this case, simply check for this and delete the file
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 14:13:21 -04:00
e0b87f1e14 notificationDaemon: Implement the new GTK+ notifications API
The new API is designed to support features like persistence and uses
the new org.freedesktop.Application specification for activating
actions on notifications. While we won't add support for persistence
yet, implement the new notification spec with parity of the old one.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 14:12:47 -04:00
394743efc8 notificationDaemon: Rename the existing implementation to the FdoNotificationSource
We'll add a new, simpler private implementation that's used by the new
GNotification API in gio.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
27a86a4756 notificationDaemon: Move nextNotificationId inside the daemon class
This won't be used by the new notification daemon.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
8ee0ef2cde messageTray: Don't always open the source when clicking on the notification
Some consumers may not always want to open the app, so make clients that
want to do this explicitly connect to the 'clicked' signal.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
43f4682ec4 messageTray: Make addButton/addAction take a callback
This is a much simpler API for consumers to manage.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
5f081b8f8d messageTray: Remove useActionIcons feature
This can be put in the legacy notification daemon with the new
addButtonFull API, to create icon names for actions.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
5023542882 messageTray: Split out addButton to allow consumers to pass a pre-made button
Some consumers may want to construct their buttons specially, so allow them
to do that by adding a new API that takes a button instead of a label.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
88d0731d80 messageTray: Replace setButtonSensitive by simply returning the button
We want to remove 'id's from buttons, and simply returning the button actor
is more powerful anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=710137
2013-10-21 12:30:25 -04:00
06cb8c52d7 Updated Hebrew translation 2013-10-20 19:52:43 +03:00
4d1358b7ed st-widget: Use g_clear_pointer
https://bugzilla.gnome.org/show_bug.cgi?id=710541
2013-10-20 14:25:16 +02:00
0cfa7c1c56 power: Fix undefined variables
A couple of variables that should have been gathered from the proxy
and weren't.
2013-10-19 18:00:08 +02:00
76928390a3 Updated Russian translation 2013-10-18 18:30:12 +04:00
af1f9cd76d network: Don't use StButtons for items in selector
Their use blocks activation of the default button by keyboard, which
is important for accessibility. Use a Clutter.ClickAction instead,
which doesn't have this problem as it only considers mouse events.

https://bugzilla.gnome.org/show_bug.cgi?id=710144
2013-10-17 19:46:30 +02:00
2f39f3d146 Revert "network: being able to use keyboard to connect to a Wireless"
This reverts commit d175a588f7.

https://bugzilla.gnome.org/show_bug.cgi?id=710144
2013-10-17 19:46:29 +02:00
f72f39bc26 messageTray: Only try to focus the summary when summoning the tray by <Super>M
Otherwise, when closing the tray, we'll try to focus an actor, which will
focus the stage window, which will drop the focus from whatever window we
already had focused.

https://bugzilla.gnome.org/show_bug.cgi?id=710347
2013-10-17 13:07:42 -04:00
2659ba6bb4 power: Fix typo
JS ERROR: ReferenceError: this_proxy is not defined
Indicator<._getStatus@/usr/share/gnome-shell/js/ui/status/power.js:66
2013-10-17 18:12:02 +02:00
0b8c0c202e power: Use UPower directly instead of gnome-settings-daemon
UPower master exports a display device that can be used to
compute whether to show a status icon, and what we should show.

https://bugzilla.gnome.org/show_bug.cgi?id=710273
2013-10-17 17:36:27 +02:00
37c8132632 workspace: Adapt to mutter API changes 2013-10-15 15:46:36 -04:00
93 changed files with 6268 additions and 7591 deletions

2
.gitignore vendored
View File

@ -43,6 +43,8 @@ docs/reference/*/xml/
docs/reference/shell/doc-gen-* docs/reference/shell/doc-gen-*
gtk-doc.make gtk-doc.make
js/misc/config.js js/misc/config.js
js/js-resources.c
js/js-resources.h
intltool-extract.in intltool-extract.in
intltool-merge.in intltool-merge.in
intltool-update.in intltool-update.in

View File

@ -1,7 +1,11 @@
# Point to our macro directory and pick up user flags from the environment # Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src browser-plugin tests po docs SUBDIRS = data js src tests po docs
if BUILD_BROWSER_PLUGIN
SUBDIRS += browser-plugin
endif
if ENABLE_MAN if ENABLE_MAN
SUBDIRS += man SUBDIRS += man

39
NEWS
View File

@ -1,3 +1,42 @@
3.11.2
======
* Cache search result display actors [Jasper; #704912]
* Use username in userWidget if real name doesn't fit [Jasper; #706851]
* Support shell_global_reexec_self() on OpenBSD [Antoine; #709571]
* Support disabling browser plugin [Colin; #711218]
* Restore support for 'disable-restart-buttons' [Florian; #711244]
* Validate parameters of exposed DBus methods [Florian; #699752]
* Connect applications to systemd journal if available [Colin; #711626]
* Misc bug fixes and cleanups [Florian, Jasper; #711205, #698486, #711416,
#644306, #711555, #709806, #711631, #711732]
Contributors:
Cosimo Cecchi, Antoine Jacoutot, Florian Müllner, Jasper St. Pierre,
Rico Tzschichholz, Colin Walters
Translations:
Yuri Myasoedov [ru], Kjartan Maraas [nb], Efstathios Iosifidis [el],
Benjamin Steinwender [de], eternalhui [zh_CN], Shantha kumar [ta]
3.11.1
======
* power: Use UPower directly instead of gnome-settings-daemon [Bastien; #710273]
* Implement support for new GTK+ notification API [Jasper, Giovanni, Florian;
#710137, #710596]
* gdm: Don't allow user-list to fill up the entire screen [Florian; #710555]
* Don't autostart remote search providers at login [Giovanni; #708830]
* Fix spacing in end-session dialog [Sebastien; #710543]
* Prepare for js24 [Tim; #711052]
* Misc bug fixes and cleanups [Jasper, Florian, Adel, Tim, Sebastien; #710347,
#710144, #710541, #691409, #710745, #688331, #704912]
Contributors:
Giovanni Campagna, Adel Gadllah, Sebastien Lafargue, Tim Lunn,
Florian Müllner, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
Translations:
Stas Solovey [ru], Yosef Or Boczko [he], Rafael Ferreira [pt_BR]
3.10.1 3.10.1
====== ======
* Make sure lock screen is drawn once before switching user [Giovanni; #708051] * Make sure lock screen is drawn once before switching user [Giovanni; #708051]

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.10.1],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[3.11.2],[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])
@ -16,6 +16,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
# Checks for programs. # Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_CXX
# Initialize libtool # Initialize libtool
LT_PREREQ([2.2.6]) LT_PREREQ([2.2.6])
@ -57,10 +58,25 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder) AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
AC_ARG_ENABLE([systemd],
AS_HELP_STRING([--enable-systemd], [Use systemd]),
[enable_systemd=$enableval],
[enable_systemd=auto])
AS_IF([test x$enable_systemd != xno], [
AC_MSG_CHECKING([for libsystemd-journal])
PKG_CHECK_EXISTS([libsystemd-journal],
[have_systemd=yes
AC_DEFINE([HAVE_SYSTEMD], [1], [Define if we have systemd])],
[have_systemd=no])
AC_MSG_RESULT($have_systemd)
])
AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.13.4 CLUTTER_MIN_VERSION=1.13.4
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.38.1 GJS_MIN_VERSION=1.38.1
MUTTER_MIN_VERSION=3.10.1 MUTTER_MIN_VERSION=3.11.1
GTK_MIN_VERSION=3.7.9 GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0 GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3 LIBECAL_MIN_VERSION=3.5.3
@ -70,7 +86,6 @@ POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11 STARTUP_NOTIFICATION_MIN_VERSION=0.11
GCR_MIN_VERSION=3.7.5 GCR_MIN_VERSION=3.7.5
GNOME_DESKTOP_REQUIRED_VERSION=3.7.90 GNOME_DESKTOP_REQUIRED_VERSION=3.7.90
GNOME_MENUS_REQUIRED_VERSION=3.5.3
NETWORKMANAGER_MIN_VERSION=0.9.8 NETWORKMANAGER_MIN_VERSION=0.9.8
PULSE_MIN_VERS=2.0 PULSE_MIN_VERS=2.0
@ -80,7 +95,6 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
gtk+-3.0 >= $GTK_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION
atk-bridge-2.0 atk-bridge-2.0
gjs-internals-1.0 >= $GJS_MIN_VERSION gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 >= $GNOME_MENUS_REQUIRED_VERSION
$recorder_modules $recorder_modules
gdk-x11-3.0 libsoup-2.4 gdk-x11-3.0 libsoup-2.4
xtst xtst
@ -94,6 +108,9 @@ SHARED_PCS="gio-unix-2.0 >= $GIO_MIN_VERSION
libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION libnm-glib libnm-util >= $NETWORKMANAGER_MIN_VERSION
libnm-gtk >= $NETWORKMANAGER_MIN_VERSION libnm-gtk >= $NETWORKMANAGER_MIN_VERSION
libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION" libsecret-unstable gcr-base-3 >= $GCR_MIN_VERSION"
if test x$have_systemd = xyes; then
SHARED_PCS="${SHARED_PCS} libsystemd-journal"
fi
PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS) PKG_CHECK_MODULES(GNOME_SHELL, $SHARED_PCS)
PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION) PKG_CHECK_MODULES(MUTTER, libmutter >= $MUTTER_MIN_VERSION)
@ -109,12 +126,20 @@ PKG_CHECK_MODULES(GNOME_SHELL_JS, gio-2.0 gjs-internals-1.0 >= $GJS_MIN_VERSION)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.8 x11)
PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0) PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0) PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
PKG_CHECK_MODULES(TRAY, gtk+-3.0) PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0) PKG_CHECK_MODULES(GVC, libpulse >= $PULSE_MIN_VERS libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4) PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 3.7.4)
PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8) PKG_CHECK_MODULES(CARIBOU, caribou-1.0 >= 0.4.8)
AC_ARG_ENABLE(browser-plugin,
[AS_HELP_STRING([--enable-browser-plugin],
[Enable browser plugin [default=yes]])],,
enable_browser_plugin=yes)
AS_IF([test x$enable_browser_plugin = xyes], [
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
])
AM_CONDITIONAL(BUILD_BROWSER_PLUGIN, test x$enable_browser_plugin = xyes)
AC_MSG_CHECKING([for bluetooth support]) AC_MSG_CHECKING([for bluetooth support])
PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.9.0], PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.9.0],
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0` [BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
@ -147,6 +172,9 @@ AC_SUBST(MUTTER_TYPELIB_DIR)
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0` GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
AC_SUBST(GJS_CONSOLE) AC_SUBST(GJS_CONSOLE)
GLIB_COMPILE_RESOURCES=`$PKG_CONFIG --variable glib_compile_resources gio-2.0`
AC_SUBST(GLIB_COMPILE_RESOURCES)
AC_CHECK_FUNCS(fdwalk) AC_CHECK_FUNCS(fdwalk)
AC_CHECK_FUNCS(mallinfo) AC_CHECK_FUNCS(mallinfo)
AC_CHECK_HEADERS([sys/resource.h]) AC_CHECK_HEADERS([sys/resource.h])

View File

@ -1,6 +1,3 @@
wandadir = $(pkgdatadir)
dist_wanda_DATA = wanda.png
desktopdir=$(datadir)/applications desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop desktop_DATA = gnome-shell.desktop gnome-shell-extension-prefs.desktop
if HAVE_MUTTER_WAYLAND if HAVE_MUTTER_WAYLAND

View File

@ -306,16 +306,13 @@ StScrollBar StButton#vhandle:active {
font-size: 12pt; font-size: 12pt;
border-bottom: 1px solid #666; border-bottom: 1px solid #666;
padding: 12px; padding: 12px;
}
.nm-dialog-item:checked {
background-color: #333;
}
.nm-dialog-item-box {
spacing: 20px; spacing: 20px;
} }
.nm-dialog-item:selected {
background-color: #333;
}
.nm-dialog-icons { .nm-dialog-icons {
spacing: .5em; spacing: .5em;
} }
@ -1970,6 +1967,11 @@ StScrollBar StButton#vhandle:active {
padding-left: 50px; padding-left: 50px;
} }
.end-session-dialog-session-list,
.end-session-dialog-app-list {
spacing: 1em;
}
.end-session-dialog-list-header { .end-session-dialog-list-header {
font-weight: bold; font-weight: bold;
} }
@ -2387,6 +2389,10 @@ StScrollBar StButton#vhandle:active {
padding-top: 1em; padding-top: 1em;
} }
.login-dialog-user-selection-box {
padding: 100px 0;
}
.login-dialog-user-selection-box .login-dialog-not-listed-label { .login-dialog-user-selection-box .login-dialog-not-listed-label {
padding-left: 2px; padding-left: 2px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,7 +1,5 @@
NULL = NULL =
BUILT_SOURCES =
EXTRA_DIST = misc/config.js.in
CLEANFILES = misc/config.js
misc/config.js: misc/config.js.in Makefile misc/config.js: misc/config.js.in Makefile
[ -d $(@D) ] || $(mkdir_p) $(@D) ; \ [ -d $(@D) ] || $(mkdir_p) $(@D) ; \
@ -14,112 +12,26 @@ misc/config.js: misc/config.js.in Makefile
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \ -e "s|[@]sysconfdir@|$(sysconfdir)|g" \
$< > $@ $< > $@
jsdir = $(pkgdatadir)/js js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/js-resources.gresource.xml)
js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
nobase_dist_js_DATA = \ js_built_sources = js-resources.c js-resources.h
gdm/authPrompt.js \
gdm/batch.js \ BUILT_SOURCES += $(js_built_sources)
gdm/fingerprint.js \
gdm/loginDialog.js \ all-local: $(js_built_sources)
gdm/oVirt.js \
gdm/realmd.js \ js_resource_dist_files = $(filter-out misc/config.js, $(js_resource_files))
gdm/util.js \
extensionPrefs/main.js \ EXTRA_DIST = \
misc/config.js \ $(js_resource_dist_files) \
misc/extensionUtils.js \ js-resources.gresource.xml \
misc/fileUtils.js \ misc/config.js.in \
misc/gnomeSession.js \ $(NULL)
misc/hash.js \
misc/history.js \ CLEANFILES = \
misc/jsParse.js \ $(js_built_sources) \
misc/loginManager.js \
misc/modemManager.js \
misc/objectManager.js \
misc/params.js \
misc/smartcardManager.js \
misc/util.js \
perf/core.js \
ui/altTab.js \
ui/animation.js \
ui/appDisplay.js \
ui/appFavorites.js \
ui/backgroundMenu.js \
ui/background.js \
ui/boxpointer.js \
ui/calendar.js \
ui/checkBox.js \
ui/ctrlAltTab.js \
ui/dash.js \
ui/dateMenu.js \
ui/dnd.js \
ui/endSessionDialog.js \
ui/extensionSystem.js \
ui/extensionDownloader.js \
ui/environment.js \
ui/focusCaretTracker.js\
ui/ibusCandidatePopup.js\
ui/grabHelper.js \
ui/iconGrid.js \
ui/keyboard.js \
ui/layout.js \
ui/lightbox.js \
ui/lookingGlass.js \
ui/magnifier.js \
ui/magnifierDBus.js \
ui/main.js \
ui/messageTray.js \
ui/modalDialog.js \
ui/separator.js \
ui/sessionMode.js \
ui/shellEntry.js \
ui/shellMountOperation.js \
ui/slider.js \
ui/notificationDaemon.js \
ui/osdWindow.js \
ui/overview.js \
ui/overviewControls.js \
ui/panel.js \
ui/panelMenu.js \
ui/pointerWatcher.js \
ui/popupMenu.js \
ui/remoteSearch.js \
ui/remoteMenu.js \
ui/runDialog.js \
ui/screencast.js \
ui/screenshot.js \
ui/screenShield.js \
ui/scripting.js \
ui/search.js \
ui/searchDisplay.js \
ui/shellDBus.js \
ui/status/accessibility.js \
ui/status/brightness.js \
ui/status/keyboard.js \
ui/status/network.js \
ui/status/power.js \
ui/status/rfkill.js \
ui/status/volume.js \
ui/status/bluetooth.js \
ui/status/screencast.js \
ui/status/system.js \
ui/switcherPopup.js \
ui/tweener.js \
ui/unlockDialog.js \
ui/userWidget.js \
ui/viewSelector.js \
ui/wanda.js \
ui/windowAttentionHandler.js \
ui/windowManager.js \
ui/workspace.js \
ui/workspaceThumbnail.js \
ui/workspacesView.js \
ui/workspaceSwitcherPopup.js \
ui/xdndHandler.js \
ui/components/__init__.js \
ui/components/autorunManager.js \
ui/components/automountManager.js \
ui/components/networkAgent.js \
ui/components/polkitAgent.js \
ui/components/telepathyClient.js \
ui/components/keyring.js \
$(NULL) $(NULL)

View File

@ -13,13 +13,15 @@ const _ = Gettext.gettext;
const Config = imports.misc.config; const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils; const ExtensionUtils = imports.misc.extensionUtils;
const GnomeShellIface = <interface name="org.gnome.Shell.Extensions"> const GnomeShellIface = '<node> \
<signal name="ExtensionStatusChanged"> <interface name="org.gnome.Shell.Extensions"> \
<arg type="s" name="uuid"/> <signal name="ExtensionStatusChanged"> \
<arg type="i" name="state"/> <arg type="s" name="uuid"/> \
<arg type="s" name="error"/> <arg type="i" name="state"/> \
</signal> <arg type="s" name="error"/> \
</interface>; </signal> \
</interface> \
</node>';
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface); const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -204,11 +206,11 @@ const Application = new Lang.Class({
_scanExtensions: function() { _scanExtensions: function() {
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', Lang.bind(this, this._extensionFound)); finder.connect('extension-found', Lang.bind(this, this._extensionFound));
finder.connect('extensions-loaded', Lang.bind(this, this._extensionsLoaded));
finder.scanExtensions(); finder.scanExtensions();
this._extensionsLoaded();
}, },
_extensionFound: function(signals, extension) { _extensionFound: function(finder, extension) {
let iter = this._model.append(); let iter = this._model.append();
this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]); this._model.set(iter, [0, 1], [extension.uuid, extension.metadata.name]);
this._extensionIters[extension.uuid] = iter; this._extensionIters[extension.uuid] = iter;

View File

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

View File

@ -59,7 +59,7 @@ const UserListItem = new Lang.Class({
this._userChangedId = this.user.connect('changed', this._userChangedId = this.user.connect('changed',
Lang.bind(this, this._onUserChanged)); Lang.bind(this, this._onUserChanged));
let layout = new St.BoxLayout({ vertical: false }); let layout = new St.BoxLayout({ vertical: true });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item', this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
can_focus: true, can_focus: true,
@ -68,39 +68,18 @@ const UserListItem = new Lang.Class({
x_align: St.Align.START, x_align: St.Align.START,
x_fill: true }); x_fill: true });
this._userAvatar = new UserWidget.Avatar(this.user, this._userWidget = new UserWidget.UserWidget(this.user);
{ styleClass: 'login-dialog-user-list-item-icon' }); layout.add(this._userWidget.actor);
layout.add(this._userAvatar.actor);
let textLayout = new St.BoxLayout({ style_class: 'login-dialog-user-list-item-text-box',
vertical: true });
layout.add(textLayout, { expand: true });
this._nameLabel = new St.Label({ style_class: 'login-dialog-user-list-item-name' });
this.actor.label_actor = this._nameLabel;
textLayout.add(this._nameLabel,
{ y_fill: false,
y_align: St.Align.MIDDLE,
expand: true });
this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator', this._timedLoginIndicator = new St.Bin({ style_class: 'login-dialog-timed-login-indicator',
scale_x: 0 }); scale_x: 0 });
textLayout.add(this._timedLoginIndicator, layout.add(this._timedLoginIndicator);
{ x_fill: true,
x_align: St.Align.MIDDLE,
y_fill: false,
y_align: St.Align.END });
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this._onUserChanged(); this._onUserChanged();
}, },
_onUserChanged: function() { _onUserChanged: function() {
this._nameLabel.set_text(this.user.get_real_name());
this._userAvatar.update();
this._updateLoggedIn();
},
syncStyleClasses: function() {
this._updateLoggedIn(); this._updateLoggedIn();
}, },
@ -189,7 +168,6 @@ const UserList = new Lang.Class({
for (let userName in this._items) { for (let userName in this._items) {
let item = this._items[userName]; let item = this._items[userName];
item.actor.sync_hover(); item.actor.sync_hover();
item.syncStyleClasses();
} }
}, },

View File

@ -4,11 +4,13 @@ const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const OVirtCredentialsIface = <interface name='org.ovirt.vdsm.Credentials'> const OVirtCredentialsIface = '<node> \
<signal name="UserAuthenticated"> <interface name="org.ovirt.vdsm.Credentials"> \
<arg type="s" name="token"/> <signal name="UserAuthenticated"> \
</signal> <arg type="s" name="token"/> \
</interface>; </signal> \
</interface> \
</node>';
const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface); const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface);

View File

@ -5,52 +5,58 @@ const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const ProviderIface = <interface name='org.freedesktop.realmd.Provider'> const ProviderIface = '<node> \
<property name="Name" type="s" access="read"/> <interface name="org.freedesktop.realmd.Provider"> \
<property name="Version" type="s" access="read"/> <property name="Name" type="s" access="read"/> \
<property name="Realms" type="ao" access="read"/> <property name="Version" type="s" access="read"/> \
<method name="Discover"> <property name="Realms" type="ao" access="read"/> \
<arg name="string" type="s" direction="in"/> <method name="Discover"> \
<arg name="options" type="a{sv}" direction="in"/> <arg name="string" type="s" direction="in"/> \
<arg name="relevance" type="i" direction="out"/> <arg name="options" type="a{sv}" direction="in"/> \
<arg name="realm" type="ao" direction="out"/> <arg name="relevance" type="i" direction="out"/> \
</method> <arg name="realm" type="ao" direction="out"/> \
</interface>; </method> \
</interface> \
</node>';
const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface); const Provider = Gio.DBusProxy.makeProxyWrapper(ProviderIface);
const ServiceIface = <interface name="org.freedesktop.realmd.Service"> const ServiceIface = '<node> \
<method name="Cancel"> <interface name="org.freedesktop.realmd.Service"> \
<arg name="operation" type="s" direction="in"/> <method name="Cancel"> \
</method> <arg name="operation" type="s" direction="in"/> \
<method name="Release" /> </method> \
<method name="SetLocale"> <method name="Release" /> \
<arg name="locale" type="s" direction="in"/> <method name="SetLocale"> \
</method> <arg name="locale" type="s" direction="in"/> \
<signal name="Diagnostics"> </method> \
<arg name="data" type="s"/> <signal name="Diagnostics"> \
<arg name="operation" type="s"/> <arg name="data" type="s"/> \
</signal> <arg name="operation" type="s"/> \
</interface>; </signal> \
</interface> \
</node>';
const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface); const Service = Gio.DBusProxy.makeProxyWrapper(ServiceIface);
const RealmIface = <interface name="org.freedesktop.realmd.Realm"> const RealmIface = '<node> \
<property name="Name" type="s" access="read"/> <interface name="org.freedesktop.realmd.Realm"> \
<property name="Configured" type="s" access="read"/> <property name="Name" type="s" access="read"/> \
<property name="Details" type="a(ss)" access="read"/> <property name="Configured" type="s" access="read"/> \
<property name="LoginFormats" type="as" access="read"/> <property name="Details" type="a(ss)" access="read"/> \
<property name="LoginPolicy" type="s" access="read"/> <property name="LoginFormats" type="as" access="read"/> \
<property name="PermittedLogins" type="as" access="read"/> <property name="LoginPolicy" type="s" access="read"/> \
<property name="SupportedInterfaces" type="as" access="read"/> <property name="PermittedLogins" type="as" access="read"/> \
<method name="ChangeLoginPolicy"> <property name="SupportedInterfaces" type="as" access="read"/> \
<arg name="login_policy" type="s" direction="in"/> <method name="ChangeLoginPolicy"> \
<arg name="permitted_add" type="as" direction="in"/> <arg name="login_policy" type="s" direction="in"/> \
<arg name="permitted_remove" type="as" direction="in"/> <arg name="permitted_add" type="as" direction="in"/> \
<arg name="options" type="a{sv}" direction="in"/> <arg name="permitted_remove" type="as" direction="in"/> \
</method> <arg name="options" type="a{sv}" direction="in"/> \
<method name="Deconfigure"> </method> \
<arg name="options" type="a{sv}" direction="in"/> <method name="Deconfigure"> \
</method> <arg name="options" type="a{sv}" direction="in"/> \
</interface>; </method> \
</interface> \
</node>';
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface); const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
const Manager = new Lang.Class({ const Manager = new Lang.Class({

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell">
<file>gdm/authPrompt.js</file>
<file>gdm/batch.js</file>
<file>gdm/fingerprint.js</file>
<file>gdm/loginDialog.js</file>
<file>gdm/oVirt.js</file>
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>
<file>extensionPrefs/main.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
<file>misc/gnomeSession.js</file>
<file>misc/hash.js</file>
<file>misc/history.js</file>
<file>misc/jsParse.js</file>
<file>misc/loginManager.js</file>
<file>misc/modemManager.js</file>
<file>misc/objectManager.js</file>
<file>misc/params.js</file>
<file>misc/smartcardManager.js</file>
<file>misc/util.js</file>
<file>perf/core.js</file>
<file>ui/altTab.js</file>
<file>ui/animation.js</file>
<file>ui/appDisplay.js</file>
<file>ui/appFavorites.js</file>
<file>ui/backgroundMenu.js</file>
<file>ui/background.js</file>
<file>ui/boxpointer.js</file>
<file>ui/calendar.js</file>
<file>ui/checkBox.js</file>
<file>ui/ctrlAltTab.js</file>
<file>ui/dash.js</file>
<file>ui/dateMenu.js</file>
<file>ui/dnd.js</file>
<file>ui/endSessionDialog.js</file>
<file>ui/extensionSystem.js</file>
<file>ui/extensionDownloader.js</file>
<file>ui/environment.js</file>
<file>ui/focusCaretTracker.js</file>
<file>ui/ibusCandidatePopup.js</file>
<file>ui/grabHelper.js</file>
<file>ui/iconGrid.js</file>
<file>ui/keyboard.js</file>
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
<file>ui/lookingGlass.js</file>
<file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file>
<file>ui/main.js</file>
<file>ui/messageTray.js</file>
<file>ui/modalDialog.js</file>
<file>ui/separator.js</file>
<file>ui/sessionMode.js</file>
<file>ui/shellEntry.js</file>
<file>ui/shellMountOperation.js</file>
<file>ui/slider.js</file>
<file>ui/notificationDaemon.js</file>
<file>ui/osdWindow.js</file>
<file>ui/overview.js</file>
<file>ui/overviewControls.js</file>
<file>ui/panel.js</file>
<file>ui/panelMenu.js</file>
<file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file>
<file>ui/remoteSearch.js</file>
<file>ui/remoteMenu.js</file>
<file>ui/runDialog.js</file>
<file>ui/screencast.js</file>
<file>ui/screenshot.js</file>
<file>ui/screenShield.js</file>
<file>ui/scripting.js</file>
<file>ui/search.js</file>
<file>ui/shellDBus.js</file>
<file>ui/status/accessibility.js</file>
<file>ui/status/brightness.js</file>
<file>ui/status/keyboard.js</file>
<file>ui/status/network.js</file>
<file>ui/status/power.js</file>
<file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/switcherPopup.js</file>
<file>ui/tweener.js</file>
<file>ui/unlockDialog.js</file>
<file>ui/userWidget.js</file>
<file>ui/viewSelector.js</file>
<file>ui/windowAttentionHandler.js</file>
<file>ui/windowManager.js</file>
<file>ui/workspace.js</file>
<file>ui/workspaceThumbnail.js</file>
<file>ui/workspacesView.js</file>
<file>ui/workspaceSwitcherPopup.js</file>
<file>ui/xdndHandler.js</file>
<file>ui/components/__init__.js</file>
<file>ui/components/autorunManager.js</file>
<file>ui/components/automountManager.js</file>
<file>ui/components/networkAgent.js</file>
<file>ui/components/polkitAgent.js</file>
<file>ui/components/telepathyClient.js</file>
<file>ui/components/keyring.js</file>
</gresource>
</gresources>

View File

@ -174,17 +174,9 @@ const ExtensionFinder = new Lang.Class({
this.emit('extension-found', extension); this.emit('extension-found', extension);
}, },
_extensionsLoaded: function() {
this.emit('extensions-loaded');
},
scanExtensions: function() { scanExtensions: function() {
let perUserDir = Gio.File.new_for_path(global.userdatadir); let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirsAsync('extensions', FileUtils.collectFromDatadirs('extensions', true, Lang.bind(this, this._loadExtension, perUserDir));
{ processFile: Lang.bind(this, this._loadExtension),
loadedCallback: Lang.bind(this, this._extensionsLoaded),
includeUserDir: true,
data: perUserDir });
} }
}); });
Signals.addSignalMethods(ExtensionFinder.prototype); Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -25,60 +25,27 @@ function listDirAsync(file, callback) {
}); });
} }
function _collectFromDirectoryAsync(dir, loadState) { function collectFromDatadirs(subdir, includeUserDir, processFile) {
function done() {
loadState.numLoading--;
if (loadState.loadedCallback &&
loadState.numLoading == 0)
loadState.loadedCallback(loadState.data);
}
dir.query_info_async('standard::type', Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_DEFAULT, null, function(object, res) {
try {
object.query_info_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
log(e.message);
done();
return;
}
listDirAsync(dir, Lang.bind(this, function(infos) {
for (let i = 0; i < infos.length; i++)
loadState.processFile(dir.get_child(infos[i].get_name()),
infos[i], loadState.data);
done();
}));
});
}
function collectFromDatadirsAsync(subdir, params) {
params = Params.parse(params, { includeUserDir: false,
processFile: null,
loadedCallback: null,
data: null });
let loadState = { data: params.data,
numLoading: 0,
loadedCallback: params.loadedCallback,
processFile: params.processFile };
if (params.processFile == null) {
if (params.loadedCallback)
params.loadedCallback(params.data);
return;
}
let dataDirs = GLib.get_system_data_dirs(); let dataDirs = GLib.get_system_data_dirs();
if (params.includeUserDir) if (includeUserDir)
dataDirs.unshift(GLib.get_user_data_dir()); dataDirs.unshift(GLib.get_user_data_dir());
loadState.numLoading = dataDirs.length;
for (let i = 0; i < dataDirs.length; i++) { for (let i = 0; i < dataDirs.length; i++) {
let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]); let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', subdir]);
let dir = Gio.File.new_for_path(path); let dir = Gio.File.new_for_path(path);
_collectFromDirectoryAsync(dir, loadState); let fileEnum;
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum != null) {
let info;
while ((info = fileEnum.next_file(null)))
processFile(fileEnum.get_child(info), info);
}
} }
} }

View File

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

View File

@ -7,58 +7,66 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Signals = imports.signals; const Signals = imports.signals;
const SystemdLoginManagerIface = <interface name='org.freedesktop.login1.Manager'> const SystemdLoginManagerIface = '<node> \
<method name='Suspend'> <interface name="org.freedesktop.login1.Manager"> \
<arg type='b' direction='in'/> <method name="Suspend"> \
</method> <arg type="b" direction="in"/> \
<method name='CanSuspend'> </method> \
<arg type='s' direction='out'/> <method name="CanSuspend"> \
</method> <arg type="s" direction="out"/> \
<method name='Inhibit'> </method> \
<arg type='s' direction='in'/> <method name="Inhibit"> \
<arg type='s' direction='in'/> <arg type="s" direction="in"/> \
<arg type='s' direction='in'/> <arg type="s" direction="in"/> \
<arg type='s' direction='in'/> <arg type="s" direction="in"/> \
<arg type='h' direction='out'/> <arg type="s" direction="in"/> \
</method> <arg type="h" direction="out"/> \
<method name='GetSession'> </method> \
<arg type='s' direction='in'/> <method name="GetSession"> \
<arg type='o' direction='out'/> <arg type="s" direction="in"/> \
</method> <arg type="o" direction="out"/> \
<method name='ListSessions'> </method> \
<arg name='sessions' type='a(susso)' direction='out'/> <method name="ListSessions"> \
</method> <arg name="sessions" type="a(susso)" direction="out"/> \
<signal name='PrepareForSleep'> </method> \
<arg type='b' direction='out'/> <signal name="PrepareForSleep"> \
</signal> <arg type="b" direction="out"/> \
</interface>; </signal> \
</interface> \
</node>';
const SystemdLoginSessionIface = <interface name='org.freedesktop.login1.Session'> const SystemdLoginSessionIface = '<node> \
<signal name='Lock' /> <interface name="org.freedesktop.login1.Session"> \
<signal name='Unlock' /> <signal name="Lock" /> \
</interface>; <signal name="Unlock" /> \
</interface> \
</node>';
const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface); const SystemdLoginManager = Gio.DBusProxy.makeProxyWrapper(SystemdLoginManagerIface);
const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface); const SystemdLoginSession = Gio.DBusProxy.makeProxyWrapper(SystemdLoginSessionIface);
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'> const ConsoleKitManagerIface = '<node> \
<method name='CanRestart'> <interface name="org.freedesktop.ConsoleKit.Manager"> \
<arg type='b' direction='out'/> <method name="CanRestart"> \
</method> <arg type="b" direction="out"/> \
<method name='CanStop'> </method> \
<arg type='b' direction='out'/> <method name="CanStop"> \
</method> <arg type="b" direction="out"/> \
<method name='Restart' /> </method> \
<method name='Stop' /> <method name="Restart" /> \
<method name='GetCurrentSession'> <method name="Stop" /> \
<arg type='o' direction='out' /> <method name="GetCurrentSession"> \
</method> <arg type="o" direction="out" /> \
</interface>; </method> \
</interface> \
</node>';
const ConsoleKitSessionIface = <interface name='org.freedesktop.ConsoleKit.Session'> const ConsoleKitSessionIface = '<node> \
<signal name='Lock' /> <interface name="org.freedesktop.ConsoleKit.Session"> \
<signal name='Unlock' /> <signal name="Lock" /> \
</interface>; <signal name="Unlock" /> \
</interface> \
</node>';
const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface); const ConsoleKitSession = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface); const ConsoleKitManager = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);

View File

@ -92,37 +92,41 @@ function _findProviderForSid(sid) {
// The following are not the complete interfaces, just the methods we need // The following are not the complete interfaces, just the methods we need
// (or may need in the future) // (or may need in the future)
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> const ModemGsmNetworkInterface = '<node> \
<method name="GetRegistrationInfo"> <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network"> \
<arg type="(uss)" direction="out" /> <method name="GetRegistrationInfo"> \
</method> <arg type="(uss)" direction="out" /> \
<method name="GetSignalQuality"> </method> \
<arg type="u" direction="out" /> <method name="GetSignalQuality"> \
</method> <arg type="u" direction="out" /> \
<property name="AccessTechnology" type="u" access="read" /> </method> \
<signal name="SignalQuality"> <property name="AccessTechnology" type="u" access="read" /> \
<arg type="u" direction="out" /> <signal name="SignalQuality"> \
</signal> <arg type="u" direction="out" /> \
<signal name="RegistrationInfo"> </signal> \
<arg type="u" direction="out" /> <signal name="RegistrationInfo"> \
<arg type="s" direction="out" /> <arg type="u" direction="out" /> \
<arg type="s" direction="out" /> <arg type="s" direction="out" /> \
</signal> <arg type="s" direction="out" /> \
</interface>; </signal> \
</interface> \
</node>';
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface); const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma"> const ModemCdmaInterface = '<node> \
<method name="GetSignalQuality"> <interface name="org.freedesktop.ModemManager.Modem.Cdma"> \
<arg type="u" direction="out" /> <method name="GetSignalQuality"> \
</method> <arg type="u" direction="out" /> \
<method name="GetServingSystem"> </method> \
<arg type="(usu)" direction="out" /> <method name="GetServingSystem"> \
</method> <arg type="(usu)" direction="out" /> \
<signal name="SignalQuality"> </method> \
<arg type="u" direction="out" /> <signal name="SignalQuality"> \
</signal> <arg type="u" direction="out" /> \
</interface>; </signal> \
</interface> \
</node>';
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface); const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
@ -218,20 +222,26 @@ Signals.addSignalMethods(ModemCdma.prototype);
// Support for the new ModemManager1 interface (MM >= 0.7) // Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
const BroadbandModemInterface = <interface name="org.freedesktop.ModemManager1.Modem"> const BroadbandModemInterface = '<node> \
<property name="SignalQuality" type="(ub)" access="read" /> <interface name="org.freedesktop.ModemManager1.Modem"> \
</interface>; <property name="SignalQuality" type="(ub)" access="read" /> \
</interface> \
</node>';
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface); const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);
const BroadbandModem3gppInterface = <interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> const BroadbandModem3gppInterface = '<node> \
<property name="OperatorCode" type="s" access="read" /> <interface name="org.freedesktop.ModemManager1.Modem.Modem3gpp"> \
<property name="OperatorName" type="s" access="read" /> <property name="OperatorCode" type="s" access="read" /> \
</interface>; <property name="OperatorName" type="s" access="read" /> \
</interface> \
</node>';
const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface); const BroadbandModem3gppProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModem3gppInterface);
const BroadbandModemCdmaInterface = <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> const BroadbandModemCdmaInterface = '<node> \
<property name="Sid" type="u" access="read" /> <interface name="org.freedesktop.ModemManager1.Modem.ModemCdma"> \
</interface>; <property name="Sid" type="u" access="read" /> \
</interface> \
</node>';
const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface); const BroadbandModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemCdmaInterface);
const BroadbandModem = new Lang.Class({ const BroadbandModem = new Lang.Class({

View File

@ -8,19 +8,21 @@ const Signals = imports.signals;
// Specified in the D-Bus specification here: // Specified in the D-Bus specification here:
// http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager // http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
const ObjectManagerIface = <interface name="org.freedesktop.DBus.ObjectManager"> const ObjectManagerIface = '<node> \
<method name="GetManagedObjects"> <interface name="org.freedesktop.DBus.ObjectManager"> \
<arg name="objects" type="a{oa{sa{sv}}}" direction="out"/> <method name="GetManagedObjects"> \
</method> <arg name="objects" type="a{oa{sa{sv}}}" direction="out"/> \
<signal name="InterfacesAdded"> </method> \
<arg name="objectPath" type="o"/> <signal name="InterfacesAdded"> \
<arg name="interfaces" type="a{sa{sv}}" /> <arg name="objectPath" type="o"/> \
</signal> <arg name="interfaces" type="a{sa{sv}}" /> \
<signal name="InterfacesRemoved"> </signal> \
<arg name="objectPath" type="o"/> <signal name="InterfacesRemoved"> \
<arg name="interfaces" type="as" /> <arg name="objectPath" type="o"/> \
</signal> <arg name="interfaces" type="as" /> \
</interface>; </signal> \
</interface> \
</node>';
const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface); const ObjectManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ObjectManagerIface);

View File

@ -7,12 +7,14 @@ const Signals = imports.signals;
const ObjectManager = imports.misc.objectManager; const ObjectManager = imports.misc.objectManager;
const SmartcardTokenIface = <interface name="org.gnome.SettingsDaemon.Smartcard.Token"> const SmartcardTokenIface = '<node> \
<property name="Name" type="s" access="read"/> <interface name="org.gnome.SettingsDaemon.Smartcard.Token"> \
<property name="Driver" type="o" access="read"/> <property name="Name" type="s" access="read"/> \
<property name="IsInserted" type="b" access="read"/> <property name="Driver" type="o" access="read"/> \
<property name="UsedToLogin" type="b" access="read"/> <property name="IsInserted" type="b" access="read"/> \
</interface>; <property name="UsedToLogin" type="b" access="read"/> \
</interface> \
</node>';
let _smartcardManager = null; let _smartcardManager = null;

View File

@ -106,6 +106,8 @@ const AppSwitcherPopup = new Lang.Class({
this._switcherList = new AppSwitcher(apps, this); this._switcherList = new AppSwitcher(apps, this);
this._items = this._switcherList.icons; this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true; return true;
}, },
@ -375,6 +377,9 @@ const WindowSwitcherPopup = new Lang.Class({
this._switcherList = new WindowList(windows, mode); this._switcherList = new WindowList(windows, mode);
this._items = this._switcherList.icons; this._items = this._switcherList.icons;
if (this._items.length == 0)
return false;
return true; return true;
}, },

View File

@ -55,13 +55,13 @@ function _loadCategory(dir, view) {
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) { while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.ENTRY) { if (nextType == GMenu.TreeItemType.ENTRY) {
let entry = iter.get_entry(); let entry = iter.get_entry();
let app = appSystem.lookup_app_by_tree_entry(entry); let appInfo = entry.get_app_info();
if (!entry.get_app_info().get_nodisplay()) let app = appSystem.lookup_app(entry.get_desktop_file_id());
if (appInfo.should_show())
view.addApp(app); view.addApp(app);
} else if (nextType == GMenu.TreeItemType.DIRECTORY) { } else if (nextType == GMenu.TreeItemType.DIRECTORY) {
let itemDir = iter.get_directory(); let itemDir = iter.get_directory();
if (!itemDir.get_is_nodisplay()) _loadCategory(itemDir, view);
_loadCategory(itemDir, view);
} }
} }
}; };
@ -92,7 +92,7 @@ const BaseAppView = new Lang.Class({
}, },
removeAll: function() { removeAll: function() {
this._grid.removeAll(); this._grid.destroyAll();
this._items = {}; this._items = {};
this._allItems = []; this._allItems = [];
}, },
@ -613,6 +613,10 @@ const FrequentView = new Lang.Class({
return this._usage.get_most_used("").length >= MIN_FREQUENT_APPS_COUNT; return this._usage.get_most_used("").length >= MIN_FREQUENT_APPS_COUNT;
}, },
removeAll: function() {
this._grid.destroyAll();
},
loadApps: function() { loadApps: function() {
let mostUsed = this._usage.get_most_used (""); let mostUsed = this._usage.get_most_used ("");
let hasUsefulData = this.hasUsefulData(); let hasUsefulData = this.hasUsefulData();
@ -691,8 +695,7 @@ const AppDisplay = new Lang.Class({
Name: 'AppDisplay', Name: 'AppDisplay',
_init: function() { _init: function() {
this._appSystem = Shell.AppSystem.get_default(); Shell.AppSystem.get_default().connect('installed-changed', Lang.bind(this, function() {
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
Main.queueDeferredWork(this._allAppsWorkId); Main.queueDeferredWork(this._allAppsWorkId);
})); }));
Main.overview.connect('showing', Lang.bind(this, function() { Main.overview.connect('showing', Lang.bind(this, function() {
@ -813,7 +816,8 @@ const AppDisplay = new Lang.Class({
view.removeAll(); view.removeAll();
let tree = this._appSystem.get_tree(); let tree = new GMenu.Tree({ menu_basename: "applications.menu" });
tree.load_sync();
let root = tree.get_root_directory(); let root = tree.get_root_directory();
let iter = root.iter(); let iter = root.iter();
@ -822,8 +826,6 @@ const AppDisplay = new Lang.Class({
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) { while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.DIRECTORY) { if (nextType == GMenu.TreeItemType.DIRECTORY) {
let dir = iter.get_directory(); let dir = iter.get_directory();
if (dir.get_is_nodisplay())
continue;
if (folderCategories.indexOf(dir.get_menu_id()) != -1) if (folderCategories.indexOf(dir.get_menu_id()) != -1)
view.addFolder(dir); view.addFolder(dir);
@ -871,8 +873,8 @@ const AppSearchProvider = new Lang.Class({
getResultMetas: function(apps, callback) { getResultMetas: function(apps, callback) {
let metas = []; let metas = [];
for (let i = 0; i < apps.length; i++) { for (let i = 0; i < apps.length; i++) {
let app = apps[i]; let app = this._appSys.lookup_app(apps[i]);
metas.push({ 'id': app, metas.push({ 'id': app.get_id(),
'name': app.get_name(), 'name': app.get_name(),
'createIcon': function(size) { 'createIcon': function(size) {
return app.create_icon_texture(size); return app.create_icon_texture(size);
@ -886,15 +888,16 @@ const AppSearchProvider = new Lang.Class({
return results.slice(0, maxNumber); return results.slice(0, maxNumber);
}, },
getInitialResultSet: function(terms) { getInitialResultSet: function(terms, callback, cancellable) {
this.searchSystem.setResults(this, this._appSys.initial_search(terms)); callback(this._appSys.initial_search(terms));
}, },
getSubsearchResultSet: function(previousResults, terms) { getSubsearchResultSet: function(previousResults, terms, callback, cancellable) {
this.searchSystem.setResults(this, this._appSys.subsearch(previousResults, terms)); callback(this._appSys.subsearch(previousResults, terms));
}, },
activateResult: function(app) { activateResult: function(result) {
let app = this._appSys.lookup_app(result);
let event = Clutter.get_current_event(); let event = Clutter.get_current_event();
let modifiers = event ? event.get_state() : 0; let modifiers = event ? event.get_state() : 0;
let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK; let openNewWindow = modifiers & Clutter.ModifierType.CONTROL_MASK;
@ -913,8 +916,8 @@ const AppSearchProvider = new Lang.Class({
app.open_new_window(workspace); app.open_new_window(workspace);
}, },
createResultObject: function (resultMeta, terms) { createResultObject: function (resultMeta) {
let app = resultMeta['id']; let app = this._appSys.lookup_app(resultMeta['id']);
return new AppIcon(app); return new AppIcon(app);
} }
}); });
@ -1352,7 +1355,9 @@ const AppIcon = new Lang.Class({
this._removeMenuTimeout(); this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT, this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() { Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu(); this.popupMenu();
return false;
})); }));
} else if (button == 3) { } else if (button == 3) {
this.popupMenu(); this.popupMenu();

View File

@ -315,7 +315,6 @@ const Background = new Lang.Class({
this._brightness = 1.0; this._brightness = 1.0;
this._vignetteSharpness = 0.2; this._vignetteSharpness = 0.2;
this._saturation = 1.0;
this._cancellable = new Gio.Cancellable(); this._cancellable = new Gio.Cancellable();
this.isLoaded = false; this.isLoaded = false;
@ -416,7 +415,6 @@ const Background = new Lang.Class({
}, },
_addImage: function(content, index, filename) { _addImage: function(content, index, filename) {
content.saturation = this._saturation;
content.brightness = this._brightness; content.brightness = this._brightness;
content.vignette_sharpness = this._vignetteSharpness; content.vignette_sharpness = this._vignetteSharpness;
@ -432,7 +430,6 @@ const Background = new Lang.Class({
}, },
_updateImage: function(content, index, filename) { _updateImage: function(content, index, filename) {
content.saturation = this._saturation;
content.brightness = this._brightness; content.brightness = this._brightness;
content.vignette_sharpness = this._vignetteSharpness; content.vignette_sharpness = this._vignetteSharpness;
@ -590,24 +587,6 @@ const Background = new Lang.Class({
this._loadFile(filename); this._loadFile(filename);
}, },
get saturation() {
return this._saturation;
},
set saturation(saturation) {
this._saturation = saturation;
if (this._pattern && this._pattern.content)
this._pattern.content.saturation = saturation;
let keys = Object.keys(this._images);
for (let i = 0; i < keys.length; i++) {
let image = this._images[keys[i]];
if (image && image.content)
image.content.saturation = saturation;
}
},
get brightness() { get brightness() {
return this._brightness; return this._brightness;
}, },
@ -751,7 +730,6 @@ const BackgroundManager = new Lang.Class({
let newBackground = this._createBackground(monitorIndex); let newBackground = this._createBackground(monitorIndex);
newBackground.vignetteSharpness = background.vignetteSharpness; newBackground.vignetteSharpness = background.vignetteSharpness;
newBackground.brightness = background.brightness; newBackground.brightness = background.brightness;
newBackground.saturation = background.saturation;
newBackground.visible = background.visible; newBackground.visible = background.visible;
newBackground.loadedSignalId = newBackground.connect('loaded', newBackground.loadedSignalId = newBackground.connect('loaded',

View File

@ -190,16 +190,18 @@ const EmptyEventSource = new Lang.Class({
}); });
Signals.addSignalMethods(EmptyEventSource.prototype); Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer"> const CalendarServerIface = '<node> \
<method name="GetEvents"> <interface name="org.gnome.Shell.CalendarServer"> \
<arg type="x" direction="in" /> <method name="GetEvents"> \
<arg type="x" direction="in" /> <arg type="x" direction="in" /> \
<arg type="b" direction="in" /> <arg type="x" direction="in" /> \
<arg type="a(sssbxxa{sv})" direction="out" /> <arg type="b" direction="in" /> \
</method> <arg type="a(sssbxxa{sv})" direction="out" /> \
<property name="HasCalendars" type="b" access="read" /> </method> \
<signal name="Changed" /> <property name="HasCalendars" type="b" access="read" /> \
</interface>; <signal name="Changed" /> \
</interface> \
</node>';
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface); const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);

View File

@ -75,12 +75,14 @@ function startAppForMount(app, mount) {
/******************************************/ /******************************************/
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer"> const HotplugSnifferIface = '<node> \
<method name="SniffURI"> <interface name="org.gnome.Shell.HotplugSniffer"> \
<arg type="s" direction="in" /> <method name="SniffURI"> \
<arg type="as" direction="out" /> <arg type="s" direction="in" /> \
</method> <arg type="as" direction="out" /> \
</interface>; </method> \
</interface> \
</node>';
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface); const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() { function HotplugSniffer() {

View File

@ -138,6 +138,8 @@ const NetworkSecretDialog = new Lang.Class({
key: Clutter.KEY_Escape, key: Clutter.KEY_Escape,
}, },
this._okButton]); this._okButton]);
this._updateOkButton();
}, },
_updateOkButton: function() { _updateOkButton: function() {
@ -432,6 +434,7 @@ const VPNRequestHandler = new Lang.Class({
}, },
_vpnChildFinished: function(pid, status, requestObj) { _vpnChildFinished: function(pid, status, requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) { if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions // For new style plugin, all work is done in the async reading functions
// Just reap the process here // Just reap the process here

View File

@ -446,6 +446,7 @@ const ChatSource = new Lang.Class({
this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed)); this._closedId = this._channel.connect('invalidated', Lang.bind(this, this._channelClosed));
this._notification = new ChatNotification(this); this._notification = new ChatNotification(this);
this._notification.connect('clicked', Lang.bind(this, this.open));
this._notification.setUrgency(MessageTray.Urgency.HIGH); this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notifyTimeoutId = 0; this._notifyTimeoutId = 0;
@ -544,20 +545,19 @@ const ChatSource = new Lang.Class({
this._notification.update(this._notification.title, null, { customContent: true }); this._notification.update(this._notification.title, null, { customContent: true });
}, },
open: function(notification) { open: function() {
if (this._client.is_handling_channel(this._channel)) { if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy // We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel], this._client.delegate_channels_async([this._channel],
global.get_current_time(), global.get_current_time(),
'org.freedesktop.Telepathy.Client.Empathy.Chat', null); 'org.freedesktop.Telepathy.Client.Empathy.Chat', null);
} } else {
else { // We are not the handler, just ask to present the channel
// We are not the handler, just ask to present the channel let dbus = Tp.DBusDaemon.dup();
let dbus = Tp.DBusDaemon.dup(); let cd = Tp.ChannelDispatcher.new(dbus);
let cd = Tp.ChannelDispatcher.new(dbus);
cd.present_channel_async(this._channel, global.get_current_time(), null); cd.present_channel_async(this._channel, global.get_current_time(), null);
} }
}, },
_getLogMessages: function() { _getLogMessages: function() {
@ -960,6 +960,8 @@ const ChatNotification = new Lang.Class({
}, },
appendTimestamp: function() { appendTimestamp: function() {
this._timestampTimeoutId = 0;
let lastMessageTime = this._history[0].time; let lastMessageTime = this._history[0].time;
let lastMessageDate = new Date(lastMessageTime * 1000); let lastMessageDate = new Date(lastMessageTime * 1000);
@ -1095,22 +1097,16 @@ const RoomInviteNotification = new Lang.Class({
* for example. */ * for example. */
this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier())); this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier()));
this.addButton('decline', _("Decline")); this.addAction(_("Decline"), Lang.bind(this, function() {
this.addButton('accept', _("Accept")); dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
this.connect('action-invoked', Lang.bind(this, function(self, action) { });
switch (action) { this.destroy();
case 'decline': }));
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, this.addAction(_("Accept"), Lang.bind(this, function() {
'', function(src, result) { dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.leave_channels_finish(result)}); src.handle_with_time_finish(result);
break; });
case 'accept':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy(); this.destroy();
})); }));
} }
@ -1136,23 +1132,17 @@ const AudioVideoNotification = new Lang.Class({
this.setUrgency(MessageTray.Urgency.CRITICAL); this.setUrgency(MessageTray.Urgency.CRITICAL);
this.addButton('reject', _("Decline")); this.addAction(_("Decline"), Lang.bind(this, function() {
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
});
this.destroy();
}));
/* translators: this is a button label (verb), not a noun */ /* translators: this is a button label (verb), not a noun */
this.addButton('answer', _("Answer")); this.addAction(_("Answer"), Lang.bind(this, function() {
dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
this.connect('action-invoked', Lang.bind(this, function(self, action) { src.handle_with_time_finish(result);
switch (action) { });
case 'reject':
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE,
'', function(src, result) {
src.leave_channels_finish(result)});
break;
case 'answer':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy(); this.destroy();
})); }));
} }
@ -1176,22 +1166,16 @@ const FileTransferNotification = new Lang.Class({
{ customContent: true }); { customContent: true });
this.setResident(true); this.setResident(true);
this.addButton('decline', _("Decline")); this.addAction(_("Decline"), Lang.bind(this, function() {
this.addButton('accept', _("Accept")); dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) {
src.leave_channels_finish(result);
this.connect('action-invoked', Lang.bind(this, function(self, action) { });
switch (action) { this.destroy();
case 'decline': }));
dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, this.addAction(_("Accept"), Lang.bind(this, function() {
'', function(src, result) { dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) {
src.leave_channels_finish(result)}); src.handle_with_time_finish(result);
break; });
case 'accept':
dispatchOp.handle_with_time_async('', global.get_current_time(),
function(src, result) {
src.handle_with_time_finish(result)});
break;
}
this.destroy(); this.destroy();
})); }));
} }
@ -1239,27 +1223,20 @@ const SubscriptionRequestNotification = new Lang.Class({
this.addActor(layout); this.addActor(layout);
this.addButton('decline', _("Decline")); this.addAction(_("Decline"), Lang.bind(this, function() {
this.addButton('accept', _("Accept")); contact.remove_async(function(src, result) {
src.remove_finish(result);
});
}));
this.addAction(_("Accept"), Lang.bind(this, function() {
// Authorize the contact and request to see his status as well
contact.authorize_publication_async(function(src, result) {
src.authorize_publication_finish(result);
});
this.connect('action-invoked', Lang.bind(this, function(self, action) { contact.request_subscription_async('', function(src, result) {
switch (action) { src.request_subscription_finish(result);
case 'decline': });
contact.remove_async(function(src, result) {
src.remove_finish(result)});
break;
case 'accept':
// Authorize the contact and request to see his status as well
contact.authorize_publication_async(function(src, result) {
src.authorize_publication_finish(result)});
contact.request_subscription_async('', function(src, result) {
src.request_subscription_finish(result)});
break;
}
// rely on _subscriptionStatesChangedCb to destroy the
// notification
})); }));
this._changedId = contact.connect('subscription-states-changed', this._changedId = contact.connect('subscription-states-changed',
@ -1358,18 +1335,11 @@ const AccountNotification = new Lang.Class({
this._account = account; this._account = account;
this.addButton('view', _("View account")); this.addAction(_("View account"), Lang.bind(this, function() {
let cmd = 'empathy-accounts --select-account=' +
this.connect('action-invoked', Lang.bind(this, function(self, action) { account.get_path_suffix();
switch (action) { let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
case 'view': app_info.launch([], global.create_app_launch_context());
let cmd = 'empathy-accounts --select-account=' +
account.get_path_suffix();
let app_info = Gio.app_info_create_from_commandline(cmd, null, 0);
app_info.launch([], global.create_app_launch_context());
break;
}
this.destroy();
})); }));
this._enabledId = account.connect('notify::enabled', this._enabledId = account.connect('notify::enabled',

View File

@ -576,6 +576,7 @@ const Dash = new Lang.Class({
Lang.bind(this, function() { Lang.bind(this, function() {
this._labelShowing = true; this._labelShowing = true;
item.showLabel(); item.showLabel();
this._showLabelTimeoutId = 0;
return false; return false;
})); }));
if (this._resetHoverTimeoutId > 0) { if (this._resetHoverTimeoutId > 0) {
@ -592,6 +593,7 @@ const Dash = new Lang.Class({
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT, this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
Lang.bind(this, function() { Lang.bind(this, function() {
this._labelShowing = false; this._labelShowing = false;
this._resetHoverTimeoutId = 0;
return false; return false;
})); }));
} }

View File

@ -236,7 +236,7 @@ const _Draggable = new Lang.Class({
if (this.actor._delegate && this.actor._delegate.getDragActor) { if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(); this._dragActor = this.actor._delegate.getDragActor();
this._dragActor.reparent(Main.uiGroup); Main.uiGroup.add_child(this._dragActor);
this._dragActor.raise_top(); this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true); Shell.util_set_hidden_from_pick(this._dragActor, true);
@ -285,7 +285,8 @@ const _Draggable = new Lang.Class({
this._dragOffsetX = actorStageX - this._dragStartX; this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY; this._dragOffsetY = actorStageY - this._dragStartY;
this._dragActor.reparent(Main.uiGroup); this._dragOrigParent.remove_actor(this._dragActor);
Main.uiGroup.add_child(this._dragActor);
this._dragActor.raise_top(); this._dragActor.raise_top();
Shell.util_set_hidden_from_pick(this._dragActor, true); Shell.util_set_hidden_from_pick(this._dragActor, true);
} }
@ -345,6 +346,7 @@ const _Draggable = new Lang.Class({
}, },
_updateDragHover : function () { _updateDragHover : function () {
this._updateHoverId = 0;
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL, let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
this._dragX, this._dragY); this._dragX, this._dragY);
let dragEvent = { let dragEvent = {
@ -389,7 +391,7 @@ const _Draggable = new Lang.Class({
_queueUpdateDragHover: function() { _queueUpdateDragHover: function() {
if (this._updateHoverId) if (this._updateHoverId)
GLib.source_remove(this._updateHoverId); return;
this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._updateHoverId = GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._updateDragHover)); Lang.bind(this, this._updateDragHover));
@ -555,7 +557,8 @@ const _Draggable = new Lang.Class({
_onAnimationComplete : function (dragActor, eventTime) { _onAnimationComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) { if (this._dragOrigParent) {
dragActor.reparent(this._dragOrigParent); Main.uiGroup.remove_child(this._dragActor);
this._dragOrigParent.add_actor(this._dragActor);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale); dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY); dragActor.set_position(this._dragOrigX, this._dragOrigY);
} else { } else {

View File

@ -43,20 +43,22 @@ const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2; const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog"> const EndSessionDialogIface = '<node> \
<method name="Open"> <interface name="org.gnome.SessionManager.EndSessionDialog"> \
<arg type="u" direction="in" /> <method name="Open"> \
<arg type="u" direction="in" /> <arg type="u" direction="in" /> \
<arg type="u" direction="in" /> <arg type="u" direction="in" /> \
<arg type="ao" direction="in" /> <arg type="u" direction="in" /> \
</method> <arg type="ao" direction="in" /> \
<method name="Close" /> </method> \
<signal name="ConfirmedLogout" /> <method name="Close" /> \
<signal name="ConfirmedReboot" /> <signal name="ConfirmedLogout" /> \
<signal name="ConfirmedShutdown" /> <signal name="ConfirmedReboot" /> \
<signal name="Canceled" /> <signal name="ConfirmedShutdown" /> \
<signal name="Closed" /> <signal name="Canceled" /> \
</interface>; <signal name="Closed" /> \
</interface> \
</node>';
const logoutDialogContent = { const logoutDialogContent = {
subjectWithUser: C_("title", "Log Out %s"), subjectWithUser: C_("title", "Log Out %s"),
@ -131,13 +133,15 @@ const DialogContent = {
const MAX_USERS_IN_SESSION_DIALOG = 5; const MAX_USERS_IN_SESSION_DIALOG = 5;
const LogindSessionIface = <interface name='org.freedesktop.login1.Session'> const LogindSessionIface = '<node> \
<property name="Id" type="s" access="read"/> <interface name="org.freedesktop.login1.Session"> \
<property name="Remote" type="b" access="read"/> <property name="Id" type="s" access="read"/> \
<property name="Class" type="s" access="read"/> <property name="Remote" type="b" access="read"/> \
<property name="Type" type="s" access="read"/> <property name="Class" type="s" access="read"/> \
<property name="State" type="s" access="read"/> <property name="Type" type="s" access="read"/> \
</interface>; <property name="State" type="s" access="read"/> \
</interface> \
</node>';
const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface); const LogindSession = Gio.DBusProxy.makeProxyWrapper(LogindSessionIface);
@ -269,13 +273,15 @@ const EndSessionDialog = new Lang.Class({
this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header', this._applicationHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Some applications are busy or have unsaved work.") }); text: _("Some applications are busy or have unsaved work.") });
this._applicationList = new St.BoxLayout({ vertical: true }); this._applicationList = new St.BoxLayout({ style_class: 'end-session-dialog-app-list',
vertical: true });
this._inhibitorSection.add_actor(this._applicationHeader); this._inhibitorSection.add_actor(this._applicationHeader);
this._inhibitorSection.add_actor(this._applicationList); this._inhibitorSection.add_actor(this._applicationList);
this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header', this._sessionHeader = new St.Label({ style_class: 'end-session-dialog-list-header',
text: _("Other users are logged in.") }); text: _("Other users are logged in.") });
this._sessionList = new St.BoxLayout({ vertical: true }); this._sessionList = new St.BoxLayout({ style_class: 'end-session-dialog-session-list',
vertical: true });
this._inhibitorSection.add_actor(this._sessionHeader); this._inhibitorSection.add_actor(this._sessionHeader);
this._inhibitorSection.add_actor(this._sessionList); this._inhibitorSection.add_actor(this._sessionList);
@ -409,6 +415,7 @@ const EndSessionDialog = new Lang.Class({
let dialogContent = DialogContent[this._type]; let dialogContent = DialogContent[this._type];
let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1]; let button = dialogContent.confirmButtons[dialogContent.confirmButtons.length - 1];
this._confirm(button.signal); this._confirm(button.signal);
this._timerId = 0;
return false; return false;
})); }));

View File

@ -76,7 +76,11 @@ function disableExtension(uuid) {
theme.unload_stylesheet(extension.stylesheet.get_path()); theme.unload_stylesheet(extension.stylesheet.get_path());
} }
extension.stateObj.disable(); try {
extension.stateObj.disable();
} catch(e) {
logExtensionError(uuid, e);
}
for (let i = 0; i < order.length; i++) { for (let i = 0; i < order.length; i++) {
let uuid = order[i]; let uuid = order[i];
@ -89,8 +93,10 @@ function disableExtension(uuid) {
extensionOrder.splice(orderIdx, 1); extensionOrder.splice(orderIdx, 1);
extension.state = ExtensionState.DISABLED; if ( extension.state != ExtensionState.ERROR ) {
_signals.emit('extension-state-changed', extension); extension.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', extension);
}
} }
function enableExtension(uuid) { function enableExtension(uuid) {
@ -117,10 +123,15 @@ function enableExtension(uuid) {
} }
} }
extension.stateObj.enable(); try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED; extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension); _signals.emit('extension-state-changed', extension);
return;
} catch(e) {
logExtensionError(uuid, e);
return;
}
} }
function logExtensionError(uuid, error) { function logExtensionError(uuid, error) {
@ -150,7 +161,8 @@ function loadExtension(extension) {
} else { } else {
let enabled = enabledExtensions.indexOf(extension.uuid) != -1; let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) { if (enabled) {
initExtension(extension.uuid); if (!initExtension(extension.uuid))
return;
if (extension.state == ExtensionState.DISABLED) if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid); enableExtension(extension.uuid);
} else { } else {
@ -205,7 +217,12 @@ function initExtension(uuid) {
extensionModule = extension.imports.extension; extensionModule = extension.imports.extension;
if (extensionModule.init) { if (extensionModule.init) {
extensionState = extensionModule.init(extension); try {
extensionState = extensionModule.init(extension);
} catch(e) {
logExtensionError(uuid, e);
return false;
}
} }
if (!extensionState) if (!extensionState)
@ -214,6 +231,7 @@ function initExtension(uuid) {
extension.state = ExtensionState.DISABLED; extension.state = ExtensionState.DISABLED;
_signals.emit('extension-loaded', uuid); _signals.emit('extension-loaded', uuid);
return true;
} }
function getEnabledExtensions() { function getEnabledExtensions() {
@ -235,11 +253,7 @@ 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) {
try { enableExtension(uuid);
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
@ -247,11 +261,7 @@ 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) {
try { disableExtension(uuid);
disableExtension(uuid);
} catch(e) {
logExtensionError(uuid, e);
}
}); });
enabledExtensions = newEnabledExtensions; enabledExtensions = newEnabledExtensions;
@ -262,12 +272,8 @@ function _loadExtensions() {
enabledExtensions = getEnabledExtensions(); enabledExtensions = getEnabledExtensions();
let finder = new ExtensionUtils.ExtensionFinder(); let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', function(signals, extension) { finder.connect('extension-found', function(finder, extension) {
try { loadExtension(extension);
loadExtension(extension);
} catch(e) {
logExtensionError(extension.uuid, e);
}
}); });
finder.scanExtensions(); finder.scanExtensions();
} }

View File

@ -413,15 +413,18 @@ const IconGrid = new Lang.Class({
}, },
removeAll: function() { removeAll: function() {
this._items = [];
this._grid.remove_all_children();
},
destroyAll: function() {
this._items = []; this._items = [];
this._grid.destroy_all_children(); this._grid.destroy_all_children();
}, },
addItem: function(item, index) { addItem: function(item, index) {
if (!item.icon || !item.icon instanceof BaseIcon) { if (!item.icon instanceof BaseIcon)
log('Only items with a BaseIcon icon property can be added to IconGrid'); throw new Error('Only items with a BaseIcon icon property can be added to IconGrid');
return;
}
this._items.push(item); this._items.push(item);
if (index !== undefined) if (index !== undefined)

View File

@ -23,27 +23,29 @@ const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications'; const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled'; const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'> const CaribouKeyboardIface = '<node> \
<method name='Show'> <interface name="org.gnome.Caribou.Keyboard"> \
<arg type='u' direction='in' /> <method name="Show"> \
</method> <arg type="u" direction="in" /> \
<method name='Hide'> </method> \
<arg type='u' direction='in' /> <method name="Hide"> \
</method> <arg type="u" direction="in" /> \
<method name='SetCursorLocation'> </method> \
<arg type='i' direction='in' /> <method name="SetCursorLocation"> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
</method> <arg type="i" direction="in" /> \
<method name='SetEntryLocation'> </method> \
<arg type='i' direction='in' /> <method name="SetEntryLocation"> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
<arg type='i' direction='in' /> <arg type="i" direction="in" /> \
</method> <arg type="i" direction="in" /> \
<property name='Name' access='read' type='s' /> </method> \
</interface>; <property name="Name" access="read" type="s" /> \
</interface> \
</node>';
const Key = new Lang.Class({ const Key = new Lang.Class({
Name: 'Key', Name: 'Key',

View File

@ -629,55 +629,6 @@ const Inspector = new Lang.Class({
Signals.addSignalMethods(Inspector.prototype); Signals.addSignalMethods(Inspector.prototype);
const Memory = new Lang.Class({
Name: 'Memory',
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
this._glibc_uordblks = new St.Label();
this.actor.add(this._glibc_uordblks);
this._js_bytes = new St.Label();
this.actor.add(this._js_bytes);
this._gjs_boxed = new St.Label();
this.actor.add(this._gjs_boxed);
this._gjs_gobject = new St.Label();
this.actor.add(this._gjs_gobject);
this._gjs_function = new St.Label();
this.actor.add(this._gjs_function);
this._gjs_closure = new St.Label();
this.actor.add(this._gjs_closure);
this._last_gc_seconds_ago = new St.Label();
this.actor.add(this._last_gc_seconds_ago);
this._gcbutton = new St.Button({ label: 'Full GC',
style_class: 'lg-obj-inspector-button' });
this._gcbutton.connect('clicked', Lang.bind(this, function () { System.gc(); this._renderText(); }));
this.actor.add(this._gcbutton, { x_align: St.Align.START,
x_fill: false });
this.actor.connect('notify::mapped', Lang.bind(this, this._renderText));
},
_renderText: function() {
if (!this.actor.mapped)
return;
let memInfo = global.get_memory_info();
this._glibc_uordblks.text = 'glibc_uordblks: ' + memInfo.glibc_uordblks;
this._js_bytes.text = 'js bytes: ' + memInfo.js_bytes;
this._gjs_boxed.text = 'gjs_boxed: ' + memInfo.gjs_boxed;
this._gjs_gobject.text = 'gjs_gobject: ' + memInfo.gjs_gobject;
this._gjs_function.text = 'gjs_function: ' + memInfo.gjs_function;
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
}
});
const Extensions = new Lang.Class({ const Extensions = new Lang.Class({
Name: 'Extensions', Name: 'Extensions',
@ -880,6 +831,19 @@ const LookingGlass = new Lang.Class({
return true; return true;
})); }));
let gcIcon = new St.Icon({ icon_name: 'gnome-fs-trash-full',
icon_size: 24 });
toolbar.add_actor(gcIcon);
gcIcon.reactive = true;
gcIcon.connect('button-press-event', Lang.bind(this, function () {
gcIcon.icon_name = 'gnome-fs-trash-empty';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, Lang.bind(this, function () {
gcIcon.icon_name = 'gnome-fs-trash-full';
Mainloop.source_remove(this._timeoutId);
}));
}));
let notebook = new Notebook(); let notebook = new Notebook();
this._notebook = notebook; this._notebook = notebook;
this.actor.add(notebook.actor, { expand: true }); this.actor.add(notebook.actor, { expand: true });
@ -907,9 +871,6 @@ const LookingGlass = new Lang.Class({
this._windowList = new WindowList(this); this._windowList = new WindowList(this);
notebook.appendPage('Windows', this._windowList.actor); notebook.appendPage('Windows', this._windowList.actor);
this._memory = new Memory();
notebook.appendPage('Memory', this._memory.actor);
this._extensions = new Extensions(this); this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor); notebook.appendPage('Extensions', this._extensions.actor);

View File

@ -9,85 +9,89 @@ const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See: // Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml // http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
const MagnifierIface = <interface name="org.gnome.Magnifier"> const MagnifierIface = '<node> \
<method name="setActive"> <interface name="org.gnome.Magnifier"> \
<arg type="b" direction="in" /> <method name="setActive"> \
</method> <arg type="b" direction="in" /> \
<method name="isActive"> </method> \
<arg type="b" direction="out" /> <method name="isActive"> \
</method> <arg type="b" direction="out" /> \
<method name="showCursor" /> </method> \
<method name="hideCursor" /> <method name="showCursor" /> \
<method name="createZoomRegion"> <method name="hideCursor" /> \
<arg type="d" direction="in" /> <method name="createZoomRegion"> \
<arg type="d" direction="in" /> <arg type="d" direction="in" /> \
<arg type="ai" direction="in" /> <arg type="d" direction="in" /> \
<arg type="ai" direction="in" /> <arg type="ai" direction="in" /> \
<arg type="o" direction="out" /> <arg type="ai" direction="in" /> \
</method> <arg type="o" direction="out" /> \
<method name="addZoomRegion"> </method> \
<arg type="o" direction="in" /> <method name="addZoomRegion"> \
<arg type="b" direction="out" /> <arg type="o" direction="in" /> \
</method> <arg type="b" direction="out" /> \
<method name="getZoomRegions"> </method> \
<arg type="ao" direction="out" /> <method name="getZoomRegions"> \
</method> <arg type="ao" direction="out" /> \
<method name="clearAllZoomRegions" /> </method> \
<method name="fullScreenCapable"> <method name="clearAllZoomRegions" /> \
<arg type="b" direction="out" /> <method name="fullScreenCapable"> \
</method> <arg type="b" direction="out" /> \
<method name="setCrosswireSize"> </method> \
<arg type="i" direction="in" /> <method name="setCrosswireSize"> \
</method> <arg type="i" direction="in" /> \
<method name="getCrosswireSize"> </method> \
<arg type="i" direction="out" /> <method name="getCrosswireSize"> \
</method> <arg type="i" direction="out" /> \
<method name="setCrosswireLength"> </method> \
<arg type="i" direction="in" /> <method name="setCrosswireLength"> \
</method> <arg type="i" direction="in" /> \
<method name="getCrosswireLength"> </method> \
<arg type="i" direction="out" /> <method name="getCrosswireLength"> \
</method> <arg type="i" direction="out" /> \
<method name="setCrosswireClip"> </method> \
<arg type="b" direction="in" /> <method name="setCrosswireClip"> \
</method> <arg type="b" direction="in" /> \
<method name="getCrosswireClip"> </method> \
<arg type="b" direction="out" /> <method name="getCrosswireClip"> \
</method> <arg type="b" direction="out" /> \
<method name="setCrosswireColor"> </method> \
<arg type="u" direction="in" /> <method name="setCrosswireColor"> \
</method> <arg type="u" direction="in" /> \
<method name="getCrosswireColor"> </method> \
<arg type="u" direction="out" /> <method name="getCrosswireColor"> \
</method> <arg type="u" direction="out" /> \
</interface>; </method> \
</interface> \
</node>';
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See: // Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml // http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
const ZoomRegionIface = <interface name="org.gnome.Magnifier.ZoomRegion"> const ZoomRegionIface = '<node> \
<method name="setMagFactor"> <interface name="org.gnome.Magnifier.ZoomRegion"> \
<arg type="d" direction="in" /> <method name="setMagFactor"> \
<arg type="d" direction="in" /> <arg type="d" direction="in" /> \
</method> <arg type="d" direction="in" /> \
<method name="getMagFactor"> </method> \
<arg type="d" direction="out" /> <method name="getMagFactor"> \
<arg type="d" direction="out" /> <arg type="d" direction="out" /> \
</method> <arg type="d" direction="out" /> \
<method name="setRoi"> </method> \
<arg type="ai" direction="in" /> <method name="setRoi"> \
</method> <arg type="ai" direction="in" /> \
<method name="getRoi"> </method> \
<arg type="ai" direction="out" /> <method name="getRoi"> \
</method> <arg type="ai" direction="out" /> \
<method name="shiftContentsTo"> </method> \
<arg type="i" direction="in" /> <method name="shiftContentsTo"> \
<arg type="i" direction="in" /> <arg type="i" direction="in" /> \
<arg type="b" direction="out" /> <arg type="i" direction="in" /> \
</method> <arg type="b" direction="out" /> \
<method name="moveResize"> </method> \
<arg type="ai" direction="in" /> <method name="moveResize"> \
</method> <arg type="ai" direction="in" /> \
</interface>; </method> \
</interface> \
</node>';
// For making unique ZoomRegion DBus proxy object paths of the form: // For making unique ZoomRegion DBus proxy object paths of the form:
// '/org/gnome/Magnifier/ZoomRegion/zoomer0', // '/org/gnome/Magnifier/ZoomRegion/zoomer0',

View File

@ -112,11 +112,6 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME'); Gio.DesktopAppInfo.set_desktop_env('GNOME');
sessionMode = new SessionMode.SessionMode(); sessionMode = new SessionMode.SessionMode();
sessionMode.connect('sessions-loaded', _sessionsLoaded);
sessionMode.init();
}
function _sessionsLoaded() {
sessionMode.connect('updated', _sessionUpdated); sessionMode.connect('updated', _sessionUpdated);
_initializePrefs(); _initializePrefs();
_initializeUI(); _initializeUI();

View File

@ -280,10 +280,6 @@ const URLHighlighter = new Lang.Class({
} }
}); });
function strHasSuffix(string, suffix) {
return string.substr(-suffix.length) == suffix;
}
// NotificationPolicy: // NotificationPolicy:
// An object that holds all bits of configurable policy related to a notification // An object that holds all bits of configurable policy related to a notification
// source, such as whether to play sound or honour the critical bit. // source, such as whether to play sound or honour the critical bit.
@ -503,7 +499,6 @@ const Notification = new Lang.Class({
this.focused = false; this.focused = false;
this.acknowledged = false; this.acknowledged = false;
this._destroyed = false; this._destroyed = false;
this._useActionIcons = false;
this._customContent = false; this._customContent = false;
this.bannerBodyText = null; this.bannerBodyText = null;
this.bannerBodyMarkup = false; this.bannerBodyMarkup = false;
@ -836,17 +831,7 @@ const Notification = new Lang.Class({
} }
}, },
// addButton: addButton: function(button, callback) {
// @id: the action ID
// @label: the label for the action's button
//
// Adds a button with the given @label to the notification. All
// action buttons will appear in a single row at the bottom of
// the notification.
//
// If the button is clicked, the notification will emit the
// %action-invoked signal with @id as a parameter
addButton: function(id, label) {
if (!this._buttonBox) { if (!this._buttonBox) {
let box = new St.BoxLayout({ style_class: 'notification-actions' }); let box = new St.BoxLayout({ style_class: 'notification-actions' });
this.setActionArea(box, { x_expand: false, this.setActionArea(box, { x_expand: false,
@ -858,43 +843,37 @@ const Notification = new Lang.Class({
global.focus_manager.add_group(this._buttonBox); global.focus_manager.add_group(this._buttonBox);
} }
let button = new St.Button({ can_focus: true });
button._actionId = id;
let iconName = strHasSuffix(id, '-symbolic') ? id : id + '-symbolic';
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
button.add_style_class_name('notification-icon-button');
button.child = new St.Icon({ icon_name: iconName });
} else {
button.add_style_class_name('notification-button');
button.label = label;
}
this._buttonBox.add(button); this._buttonBox.add(button);
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id)); button.connect('clicked', Lang.bind(this, function() {
callback();
if (!this.resident) {
// We don't hide a resident notification when the user invokes one of its actions,
// because it is common for such notifications to update themselves with new
// information based on the action. We'd like to display the updated information
// in place, rather than pop-up a new notification.
this.emit('done-displaying');
this.destroy();
}
}));
this.updated(); this.updated();
return button;
}, },
// setButtonSensitive: // addAction:
// @id: the action ID // @label: the label for the action's button
// @sensitive: whether the button should be sensitive // @callback: the callback for the action
// //
// If the notification contains a button with action ID @id, // Adds a button with the given @label to the notification. All
// its sensitivity will be set to @sensitive. Insensitive // action buttons will appear in a single row at the bottom of
// buttons cannot be clicked. // the notification.
setButtonSensitive: function(id, sensitive) { addAction: function(label, callback) {
if (!this._buttonBox) let button = new St.Button({ style_class: 'notification-button',
return; label: label,
can_focus: true });
let button = this._buttonBox.get_children().filter(function(b) { return this.addButton(button, callback);
return b._actionId == id;
})[0];
if (!button || button.reactive == sensitive)
return;
button.reactive = sensitive;
}, },
setUrgency: function(urgency) { setUrgency: function(urgency) {
@ -913,10 +892,6 @@ const Notification = new Lang.Class({
this.forFeedback = forFeedback; this.forFeedback = forFeedback;
}, },
setUseActionIcons: function(useIcons) {
this._useActionIcons = useIcons;
},
_styleChanged: function() { _styleChanged: function() {
this._spacing = this._table.get_theme_node().get_length('spacing-columns'); this._spacing = this._table.get_theme_node().get_length('spacing-columns');
}, },
@ -1141,18 +1116,6 @@ const Notification = new Lang.Class({
this.actor.add_style_class_name('notification-unexpanded'); this.actor.add_style_class_name('notification-unexpanded');
}, },
_onActionInvoked: function(actor, mouseButtonClicked, id) {
this.emit('action-invoked', id);
if (!this.resident) {
// We don't hide a resident notification when the user invokes one of its actions,
// because it is common for such notifications to update themselves with new
// information based on the action. We'd like to display the updated information
// in place, rather than pop-up a new notification.
this.emit('done-displaying');
this.destroy();
}
},
_onClicked: function() { _onClicked: function() {
this.emit('clicked'); this.emit('clicked');
// We hide all types of notifications once the user clicks on them because the common // We hide all types of notifications once the user clicks on them because the common
@ -1418,9 +1381,7 @@ const Source = new Lang.Class({
if (this.notifications.indexOf(notification) >= 0) if (this.notifications.indexOf(notification) >= 0)
return; return;
notification.connect('clicked', Lang.bind(this, this.open));
notification.connect('destroy', Lang.bind(this, this._onNotificationDestroy)); notification.connect('destroy', Lang.bind(this, this._onNotificationDestroy));
this.notifications.push(notification); this.notifications.push(notification);
this.emit('notification-added', notification); this.emit('notification-added', notification);
@ -2212,7 +2173,10 @@ const MessageTray = new Lang.Class({
}, },
toggleAndNavigate: function() { toggleAndNavigate: function() {
if (this.toggle()) if (!this.toggle())
return;
if (this._traySummoned)
this._summary.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); this._summary.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}, },
@ -2409,7 +2373,6 @@ const MessageTray = new Lang.Class({
this._showNotification(); this._showNotification();
} }
} else if (this._notificationState == State.SHOWN) { } else if (this._notificationState == State.SHOWN) {
let pinned = this._pointerInNotification && !this._notificationRemoved;
let expired = (this._userActiveWhileNotificationShown && let expired = (this._userActiveWhileNotificationShown &&
this._notificationTimeoutId == 0 && this._notificationTimeoutId == 0 &&
!(this._notification.urgency == Urgency.CRITICAL) && !(this._notification.urgency == Urgency.CRITICAL) &&
@ -2420,9 +2383,9 @@ const MessageTray = new Lang.Class({
if (mustClose) { if (mustClose) {
let animate = hasNotifications && !this._notificationRemoved; let animate = hasNotifications && !this._notificationRemoved;
this._hideNotification(animate); this._hideNotification(animate);
} else if (pinned && !this._notification.expanded) { } else if (this._pointerInNotification && !this._notification.expanded) {
this._expandNotification(false); this._expandNotification(false);
} else if (pinned) { } else if (this._pointerInNotification) {
this._ensureNotificationFocused(); this._ensureNotificationFocused();
} }
} }
@ -2792,12 +2755,12 @@ const MessageTray = new Lang.Class({
} else if (this._notification.y != expandedY) { } else if (this._notification.y != expandedY) {
// Tween also opacity here, to override a possible tween that's // Tween also opacity here, to override a possible tween that's
// currently hiding the notification. // currently hiding the notification.
this._tween(this._notificationWidget, '_notificationState', State.SHOWN, Tweener.addTween(this._notificationWidget,
{ y: expandedY, { y: expandedY,
opacity: 255, opacity: 255,
time: ANIMATION_TIME, time: ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad'
}); });
} }
}, },

View File

@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf; const GdkPixbuf = imports.gi.GdkPixbuf;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang; const Lang = imports.lang;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
@ -15,54 +16,56 @@ const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params; const Params = imports.misc.params;
const Util = imports.misc.util; const Util = imports.misc.util;
let nextNotificationId = 1;
// Should really be defined in Gio.js // Should really be defined in Gio.js
const BusIface = <interface name="org.freedesktop.DBus"> const BusIface = '<node> \
<method name="GetConnectionUnixProcessID"> <interface name="org.freedesktop.DBus"> \
<arg type="s" direction="in" /> <method name="GetConnectionUnixProcessID"> \
<arg type="u" direction="out" /> <arg type="s" direction="in" /> \
</method> <arg type="u" direction="out" /> \
</interface>; </method> \
</interface> \
</node>';
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface); var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() { function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus'); return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
} }
const NotificationDaemonIface = <interface name="org.freedesktop.Notifications"> const FdoNotificationsIface = '<node> \
<method name="Notify"> <interface name="org.freedesktop.Notifications"> \
<arg type="s" direction="in"/> <method name="Notify"> \
<arg type="u" direction="in"/> <arg type="s" direction="in"/> \
<arg type="s" direction="in"/> <arg type="u" direction="in"/> \
<arg type="s" direction="in"/> <arg type="s" direction="in"/> \
<arg type="s" direction="in"/> <arg type="s" direction="in"/> \
<arg type="as" direction="in"/> <arg type="s" direction="in"/> \
<arg type="a{sv}" direction="in"/> <arg type="as" direction="in"/> \
<arg type="i" direction="in"/> <arg type="a{sv}" direction="in"/> \
<arg type="u" direction="out"/> <arg type="i" direction="in"/> \
</method> <arg type="u" direction="out"/> \
<method name="CloseNotification"> </method> \
<arg type="u" direction="in"/> <method name="CloseNotification"> \
</method> <arg type="u" direction="in"/> \
<method name="GetCapabilities"> </method> \
<arg type="as" direction="out"/> <method name="GetCapabilities"> \
</method> <arg type="as" direction="out"/> \
<method name="GetServerInformation"> </method> \
<arg type="s" direction="out"/> <method name="GetServerInformation"> \
<arg type="s" direction="out"/> <arg type="s" direction="out"/> \
<arg type="s" direction="out"/> <arg type="s" direction="out"/> \
<arg type="s" direction="out"/> <arg type="s" direction="out"/> \
</method> <arg type="s" direction="out"/> \
<signal name="NotificationClosed"> </method> \
<arg type="u"/> <signal name="NotificationClosed"> \
<arg type="u"/> <arg type="u"/> \
</signal> <arg type="u"/> \
<signal name="ActionInvoked"> </signal> \
<arg type="u"/> <signal name="ActionInvoked"> \
<arg type="s"/> <arg type="u"/> \
</signal> <arg type="s"/> \
</interface>; </signal> \
</interface> \
</node>';
const NotificationClosedReason = { const NotificationClosedReason = {
EXPIRED: 1, EXPIRED: 1,
@ -103,11 +106,11 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'keyboard' 'ibus-ui-gtk': 'keyboard'
}; };
const NotificationDaemon = new Lang.Class({ const FdoNotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon', Name: 'FdoNotificationDaemon',
_init: function() { _init: function() {
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FdoNotificationsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications'); this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = []; this._sources = [];
@ -115,6 +118,8 @@ const NotificationDaemon = new Lang.Class({
this._notifications = {}; this._notifications = {};
this._busProxy = new Bus(); this._busProxy = new Bus();
this._nextNotificationId = 1;
this._trayManager = new Shell.TrayManager(); this._trayManager = new Shell.TrayManager();
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded)); this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved)); this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
@ -213,7 +218,7 @@ const NotificationDaemon = new Lang.Class({
} }
} }
let source = new Source(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null); let source = new FdoNotificationDaemonSource(title, pid, sender, trayIcon, ndata ? ndata.hints['desktop-entry'] : null);
source.setTransient(isForTransientNotification); source.setTransient(isForTransientNotification);
if (!isForTransientNotification) { if (!isForTransientNotification) {
@ -252,7 +257,7 @@ const NotificationDaemon = new Lang.Class({
hints['category'] == 'presence.offline')) { hints['category'] == 'presence.offline')) {
// Ignore replacesId since we already sent back a // Ignore replacesId since we already sent back a
// NotificationClosed for that id. // NotificationClosed for that id.
id = nextNotificationId++; id = this._nextNotificationId++;
Mainloop.idle_add(Lang.bind(this, Mainloop.idle_add(Lang.bind(this,
function () { function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED); this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
@ -296,7 +301,7 @@ const NotificationDaemon = new Lang.Class({
ndata.notification = this._notifications[replacesId].notification; ndata.notification = this._notifications[replacesId].notification;
} else { } else {
replacesId = 0; replacesId = 0;
ndata.id = id = nextNotificationId++; ndata.id = id = this._nextNotificationId++;
} }
this._notifications[id] = ndata; this._notifications[id] = ndata;
@ -351,6 +356,19 @@ const NotificationDaemon = new Lang.Class({
return invocation.return_value(GLib.Variant.new('(u)', [id])); return invocation.return_value(GLib.Variant.new('(u)', [id]));
}, },
_makeButton: function(id, label, useActionIcons) {
let button = new St.Button({ can_focus: true });
let iconName = id.endsWith('-symbolic') ? id : id + '-symbolic';
if (useActionIcons && Gtk.IconTheme.get_default().has_icon(iconName)) {
button.add_style_class_name('notification-icon-button');
button.child = new St.Icon({ icon_name: iconName });
} else {
button.add_style_class_name('notification-button');
button.label = label;
}
return button;
},
_notifyForSource: function(source, ndata) { _notifyForSource: function(source, ndata) {
let [id, icon, summary, body, actions, hints, notification] = let [id, icon, summary, body, actions, hints, notification] =
[ndata.id, ndata.icon, ndata.summary, ndata.body, [ndata.id, ndata.icon, ndata.summary, ndata.body,
@ -376,10 +394,6 @@ const NotificationDaemon = new Lang.Class({
} }
this._emitNotificationClosed(ndata.id, notificationClosedReason); this._emitNotificationClosed(ndata.id, notificationClosedReason);
})); }));
notification.connect('action-invoked', Lang.bind(this,
function(n, actionId) {
this._emitActionInvoked(ndata.id, actionId);
}));
} }
// Mark music notifications so they can be shown in the screen shield // Mark music notifications so they can be shown in the screen shield
@ -413,18 +427,33 @@ const NotificationDaemon = new Lang.Class({
soundName: hints['sound-name'] }); soundName: hints['sound-name'] });
notification.setImage(image); notification.setImage(image);
let hasDefaultAction = false;
if (actions.length) { if (actions.length) {
notification.setUseActionIcons(hints['action-icons'] == true); let useActionIcons = (hints['action-icons'] == true);
for (let i = 0; i < actions.length - 1; i += 2) { for (let i = 0; i < actions.length - 1; i += 2) {
if (actions[i] == 'default') let [actionId, label] = [actions[i], actions[i+1]];
notification.connect('clicked', Lang.bind(this, if (actionId == 'default') {
function() { hasDefaultAction = true;
this._emitActionInvoked(ndata.id, "default"); } else {
})); notification.addButton(this._makeButton(actionId, label, useActionIcons), Lang.bind(this, function() {
else this._emitActionInvoked(ndata.id, actionId);
notification.addButton(actions[i], actions[i + 1]); }));
}
} }
} }
if (hasDefaultAction) {
notification.connect('clicked', Lang.bind(this, function() {
this._emitActionInvoked(ndata.id, 'default');
}));
} else {
notification.connect('clicked', Lang.bind(this, function() {
source.open();
}));
}
switch (hints.urgency) { switch (hints.urgency) {
case Urgency.LOW: case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW); notification.setUrgency(MessageTray.Urgency.LOW);
@ -517,8 +546,8 @@ const NotificationDaemon = new Lang.Class({
} }
}); });
const Source = new Lang.Class({ const FdoNotificationDaemonSource = new Lang.Class({
Name: 'NotificationDaemonSource', Name: 'FdoNotificationDaemonSource',
Extends: MessageTray.Source, Extends: MessageTray.Source,
_init: function(title, pid, sender, trayIcon, appId) { _init: function(title, pid, sender, trayIcon, appId) {
@ -553,7 +582,7 @@ const Source = new Lang.Class({
}, },
_createPolicy: function() { _createPolicy: function() {
if (this.app) { if (this.app && this.app.get_app_info()) {
let id = this.app.get_id().replace(/\.desktop$/,''); let id = this.app.get_id().replace(/\.desktop$/,'');
return new MessageTray.NotificationApplicationPolicy(id); return new MessageTray.NotificationApplicationPolicy(id);
} else { } else {
@ -643,7 +672,7 @@ const Source = new Lang.Class({
this.parent(title); this.parent(title);
}, },
open: function(notification) { open: function() {
this.openApp(); this.openApp();
this.destroyNonResidentNotifications(); this.destroyNonResidentNotifications();
}, },
@ -685,3 +714,276 @@ const Source = new Lang.Class({
} }
} }
}); });
const GtkNotificationDaemonNotification = new Lang.Class({
Name: 'GtkNotificationDaemonNotification',
Extends: MessageTray.Notification,
_init: function(source, notification) {
this.parent(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { "title": title,
"body": body,
"icon": gicon,
"urgent": urgent,
"buttons": buttons,
"default-action": defaultAction,
"default-action-target": defaultActionTarget } = notification;
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
if (buttons) {
buttons.deep_unpack().forEach(Lang.bind(this, function(button) {
this.addAction(button.label.unpack(),
Lang.bind(this, this._onButtonClicked, button));
}));
}
this._defaultAction = defaultAction ? defaultAction.unpack() : null;
this._defaultActionTarget = defaultActionTarget;
this.update(title.unpack(), body ? body.unpack() : null,
{ gicon: gicon ? Gio.icon_deserialize(gicon) : null });
},
_activateAction: function(namespacedActionId, target) {
if (namespacedActionId) {
if (namespacedActionId.startsWith('app.')) {
let actionId = namespacedActionId.slice('app.'.length);
this.source.activateAction(actionId, target);
}
} else {
this.source.open();
}
},
_onButtonClicked: function(button) {
let { 'action': action, 'target': actionTarget } = button;
this._activateAction(action.unpack(), actionTarget);
},
_onClicked: function() {
this._activateAction(this._defaultAction, this._defaultActionTarget);
this.parent();
},
serialize: function() {
return this._serialized;
},
});
const FdoApplicationIface = '<node> \
<interface name="org.freedesktop.Application"> \
<method name="ActivateAction"> \
<arg type="s" direction="in" /> \
<arg type="av" direction="in" /> \
<arg type="a{sv}" direction="in" /> \
</method> \
<method name="Activate"> \
<arg type="a{sv}" direction="in" /> \
</method> \
</interface> \
</node>';
const FdoApplicationProxy = Gio.DBusProxy.makeProxyWrapper(FdoApplicationIface);
function objectPathFromAppId(appId) {
return '/' + appId.replace(/\./g, '/');
}
function getPlatformData() {
let startupId = GLib.Variant.new('s', '_TIME' + global.get_current_time());
return { "desktop-startup-id": startupId };
}
function InvalidAppError() {}
const GtkNotificationDaemonAppSource = new Lang.Class({
Name: 'GtkNotificationDaemonAppSource',
Extends: MessageTray.Source,
_init: function(appId) {
this._appId = appId;
this._objectPath = objectPathFromAppId(appId);
this._app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
if (!this._app)
throw new InvalidAppError();
this._notifications = {};
this.parent(this._app.get_name());
},
createIcon: function(size) {
return this._app.create_icon_texture(size);
},
_createPolicy: function() {
return new MessageTray.NotificationApplicationPolicy(this._appId);
},
_createApp: function() {
return new FdoApplicationProxy(Gio.DBus.session, this._appId, this._objectPath);
},
activateAction: function(actionId, target) {
let app = this._createApp();
app.ActivateActionRemote(actionId, target ? [target] : [], getPlatformData());
},
open: function() {
let app = this._createApp();
app.ActivateRemote(getPlatformData());
},
addNotification: function(notificationId, notificationParams, showBanner) {
if (this._notifications[notificationId])
this._notifications[notificationId].destroy();
let notification = new GtkNotificationDaemonNotification(this, notificationParams);
notification.connect('destroy', Lang.bind(this, function() {
delete this._notifications[notificationId];
}));
this._notifications[notificationId] = notification;
if (showBanner)
this.notify(notification);
else
this.pushNotification(notification);
},
removeNotification: function(notificationId) {
if (this._notifications[notificationId])
this._notifications[notificationId].destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
},
serialize: function() {
let notifications = [];
for (let notificationId in this._notifications) {
let notification = this._notifications[notificationId];
notifications.push([notificationId, notification.serialize()]);
}
return [this._appId, notifications];
},
});
const GtkNotificationsIface = '<node> \
<interface name="org.gtk.Notifications"> \
<method name="AddNotification"> \
<arg type="s" direction="in" /> \
<arg type="s" direction="in" /> \
<arg type="a{sv}" direction="in" /> \
</method> \
<method name="RemoveNotification"> \
<arg type="s" direction="in" /> \
<arg type="s" direction="in" /> \
</method> \
</interface> \
</node>';
const GtkNotificationDaemon = new Lang.Class({
Name: 'GtkNotificationDaemon',
_init: function() {
this._sources = {};
this._loadNotifications();
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GtkNotificationsIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gtk/Notifications');
Gio.DBus.session.own_name('org.gtk.Notifications', Gio.BusNameOwnerFlags.REPLACE, null, null);
},
_ensureAppSource: function(appId) {
if (this._sources[appId])
return this._sources[appId];
let source = new GtkNotificationDaemonAppSource(appId);
source.connect('destroy', Lang.bind(this, function() {
delete this._sources[appId];
this._saveNotifications();
}));
source.connect('count-updated', Lang.bind(this, this._saveNotifications));
Main.messageTray.add(source);
this._sources[appId] = source;
return source;
},
_loadNotifications: function() {
this._isLoading = true;
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(Lang.bind(this, function([appId, notifications]) {
if (notifications.length == 0)
return;
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
return;
}
notifications.forEach(function([notificationId, notification]) {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
}));
}
this._isLoading = false;
},
_saveNotifications: function() {
if (this._isLoading)
return;
let sources = [];
for (let appId in this._sources) {
let source = this._sources[appId];
sources.push(source.serialize());
}
global.set_persistent_state('notifications', new GLib.Variant('a(sa(sv))', sources));
},
AddNotificationAsync: function(params, invocation) {
let [appId, notificationId, notification] = params;
let source;
try {
source = this._ensureAppSource(appId);
} catch(e if e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;
}
source.addNotification(notificationId, notification, true);
invocation.return_value(null);
},
RemoveNotificationAsync: function(params, invocation) {
let [appId, notificationId] = params;
let source = this._sources[appId];
if (source)
source.removeNotification(notificationId);
invocation.return_value(null);
},
});
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
_init: function() {
this._fdoNotificationDaemon = new FdoNotificationDaemon();
this._gtkNotificationDaemon = new GtkNotificationDaemon();
},
});

View File

@ -78,10 +78,8 @@ const ShellInfo = new Lang.Class({
} }
this._undoCallback = undoCallback; this._undoCallback = undoCallback;
if (undoCallback) { if (undoCallback)
notification.addButton('system-undo', _("Undo")); notification.addAction(_("Undo"), Lang.bind(this, this._onUndoClicked));
notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked));
}
this._source.notify(notification); this._source.notify(notification);
} }
@ -365,11 +363,13 @@ const Overview = new Lang.Class({
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow; this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT, this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
Lang.bind(this, function() { Lang.bind(this, function() {
this._windowSwitchTimeoutId = 0;
this._needsFakePointerEvent = true; this._needsFakePointerEvent = true;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow, Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
this._windowSwitchTimestamp); this._windowSwitchTimestamp);
this.hide(); this.hide();
this._lastHoveredWindow = null; this._lastHoveredWindow = null;
return false;
})); }));
} }
@ -445,17 +445,17 @@ const Overview = new Lang.Class({
this._inDrag = false; this._inDrag = false;
}, },
beginWindowDrag: function(source) { beginWindowDrag: function(clone) {
this.emit('window-drag-begin'); this.emit('window-drag-begin', clone);
this._inDrag = true; this._inDrag = true;
}, },
cancelledWindowDrag: function(source) { cancelledWindowDrag: function(clone) {
this.emit('window-drag-cancelled'); this.emit('window-drag-cancelled', clone);
}, },
endWindowDrag: function(source) { endWindowDrag: function(clone) {
this.emit('window-drag-end'); this.emit('window-drag-end', clone);
this._inDrag = false; this._inDrag = false;
}, },

View File

@ -36,6 +36,7 @@ const SlideLayout = new Lang.Class({
_init: function(params) { _init: function(params) {
this._slideX = 1; this._slideX = 1;
this._translationX = 0;
this._direction = SlideDirection.LEFT; this._direction = SlideDirection.LEFT;
this.parent(params); this.parent(params);
@ -66,9 +67,9 @@ const SlideLayout = new Lang.Class({
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0; let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth) : 0;
let actorBox = new Clutter.ActorBox(); let actorBox = new Clutter.ActorBox();
actorBox.x1 = alignX; actorBox.x1 = box.x1 + alignX + this._translationX;
actorBox.x2 = actorBox.x1 + child.x_expand ? availWidth : natWidth; actorBox.x2 = actorBox.x1 + (child.x_expand ? availWidth : natWidth);
actorBox.y1 = 0; actorBox.y1 = box.y1;
actorBox.y2 = actorBox.y1 + availHeight; actorBox.y2 = actorBox.y1 + availHeight;
child.allocate(actorBox, flags); child.allocate(actorBox, flags);
@ -90,7 +91,16 @@ const SlideLayout = new Lang.Class({
get slideDirection() { get slideDirection() {
return this._direction; return this._direction;
} },
set translationX(value) {
this._translationX = value;
this.layout_changed();
},
get translationX() {
return this._translationX;
},
}); });
const SlidingControl = new Lang.Class({ const SlidingControl = new Lang.Class({
@ -99,8 +109,8 @@ const SlidingControl = new Lang.Class({
_init: function(params) { _init: function(params) {
params = Params.parse(params, { slideDirection: SlideDirection.LEFT }); params = Params.parse(params, { slideDirection: SlideDirection.LEFT });
this.visible = true; this._visible = true;
this.inDrag = false; this._inDrag = false;
this.layout = new SlideLayout(); this.layout = new SlideLayout();
this.layout.slideDirection = params.slideDirection; this.layout.slideDirection = params.slideDirection;
@ -109,6 +119,7 @@ const SlidingControl = new Lang.Class({
clip_to_allocation: true }); clip_to_allocation: true });
Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing)); Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin)); Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd)); Main.overview.connect('item-drag-end', Lang.bind(this, this._onDragEnd));
@ -119,12 +130,12 @@ const SlidingControl = new Lang.Class({
Main.overview.connect('window-drag-end', Lang.bind(this, this._onWindowDragEnd)); Main.overview.connect('window-drag-end', Lang.bind(this, this._onWindowDragEnd));
}, },
getSlide: function() { _getSlide: function() {
throw new Error('getSlide() must be overridden'); throw new Error('getSlide() must be overridden');
}, },
updateSlide: function() { _updateSlide: function() {
Tweener.addTween(this.layout, { slideX: this.getSlide(), Tweener.addTween(this.layout, { slideX: this._getSlide(),
time: SIDE_CONTROLS_ANIMATION_TIME, time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' }); transition: 'easeOutQuad' });
}, },
@ -151,28 +162,30 @@ const SlidingControl = new Lang.Class({
let translationEnd = 0; let translationEnd = 0;
let translation = this._getTranslation(); let translation = this._getTranslation();
if (this.visible) { if (this._visible) {
translationStart = translation; translationStart = translation;
} else { } else {
translationEnd = translation; translationEnd = translation;
} }
if (this.actor.translation_x == translationEnd) if (this.layout.translationX == translationEnd)
return; return;
this.actor.translation_x = translationStart; this.layout.translationX = translationStart;
Tweener.addTween(this.actor, { translation_x: translationEnd, Tweener.addTween(this.layout, { translationX: translationEnd,
time: SIDE_CONTROLS_ANIMATION_TIME, time: SIDE_CONTROLS_ANIMATION_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad' });
});
}, },
_onOverviewShowing: function() { _onOverviewShowing: function() {
// reset any translation and make sure the actor is visible when this._visible = true;
// entering the overview this.layout.slideX = this._getSlide();
this.visible = true; this.layout.translationX = this._getTranslation();
this.layout.slideX = this.getSlide(); this.slideIn();
this.actor.translation_x = 0; },
_onOverviewHiding: function() {
this.slideOut();
}, },
_onWindowDragBegin: function() { _onWindowDragBegin: function() {
@ -184,14 +197,14 @@ const SlidingControl = new Lang.Class({
}, },
_onDragBegin: function() { _onDragBegin: function() {
this.inDrag = true; this._inDrag = true;
this.actor.translation_x = 0; this.layout.translationX = 0;
this.updateSlide(); this._updateSlide();
}, },
_onDragEnd: function() { _onDragEnd: function() {
this.inDrag = false; this._inDrag = false;
this.updateSlide(); this._updateSlide();
}, },
fadeIn: function() { fadeIn: function() {
@ -209,13 +222,13 @@ const SlidingControl = new Lang.Class({
}, },
slideIn: function() { slideIn: function() {
this.visible = true; this._visible = true;
this._updateTranslation(); this._updateTranslation();
// we will update slideX and the translation from pageEmpty // we will update slideX and the translation from pageEmpty
}, },
slideOut: function() { slideOut: function() {
this.visible = false; this._visible = false;
this._updateTranslation(); this._updateTranslation();
// we will update slideX from pageEmpty // we will update slideX from pageEmpty
}, },
@ -225,7 +238,7 @@ const SlidingControl = new Lang.Class({
// selector; this means we can now safely set the full slide for // selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called, // the next page, since slideIn or slideOut might have been called,
// changing the visiblity // changing the visiblity
this.layout.slideX = this.getSlide(); this.layout.slideX = this._getSlide();
this._updateTranslation(); this._updateTranslation();
} }
}); });
@ -244,16 +257,15 @@ const ThumbnailsSlider = new Lang.Class({
this.actor.track_hover = true; this.actor.track_hover = true;
this.actor.add_actor(this._thumbnailsBox.actor); this.actor.add_actor(this._thumbnailsBox.actor);
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this.updateSlide)); Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateSlide));
Main.overview.connect('hiding', Lang.bind(this, this.slideOut)); this.actor.connect('notify::hover', Lang.bind(this, this._updateSlide));
this.actor.connect('notify::hover', Lang.bind(this, this.updateSlide));
this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE); this._thumbnailsBox.actor.bind_property('visible', this.actor, 'visible', GObject.BindingFlags.SYNC_CREATE);
}, },
_getAlwaysZoomOut: function() { _getAlwaysZoomOut: function() {
// Always show the pager when hover, during a drag, or if workspaces are // Always show the pager when hover, during a drag, or if workspaces are
// actually used, e.g. there are windows on more than one // actually used, e.g. there are windows on more than one
let alwaysZoomOut = this.actor.hover || this.inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2; let alwaysZoomOut = this.actor.hover || this._inDrag || !Meta.prefs_get_dynamic_workspaces() || global.screen.n_workspaces > 2;
if (!alwaysZoomOut) { if (!alwaysZoomOut) {
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;
@ -273,20 +285,13 @@ const ThumbnailsSlider = new Lang.Class({
return alwaysZoomOut; return alwaysZoomOut;
}, },
_onOverviewShowing: function() {
this.visible = true;
this.layout.slideX = this.getSlide();
this.actor.translation_x = this._getTranslation();
this.slideIn();
},
getNonExpandedWidth: function() { getNonExpandedWidth: function() {
let child = this.actor.get_first_child(); let child = this.actor.get_first_child();
return child.get_theme_node().get_length('visible-width'); return child.get_theme_node().get_length('visible-width');
}, },
getSlide: function() { _getSlide: function() {
if (!this.visible) if (!this._visible)
return 0; return 0;
let alwaysZoomOut = this._getAlwaysZoomOut(); let alwaysZoomOut = this._getAlwaysZoomOut();
@ -323,29 +328,22 @@ const DashSlider = new Lang.Class({
// available allocation // available allocation
this._dash.actor.x_expand = true; this._dash.actor.x_expand = true;
this.actor.x_expand = true;
this.actor.x_align = Clutter.ActorAlign.START; this.actor.x_align = Clutter.ActorAlign.START;
this.actor.y_expand = true; this.actor.y_expand = true;
this.actor.add_actor(this._dash.actor); this.actor.add_actor(this._dash.actor);
this._dash.connect('icon-size-changed', Lang.bind(this, this.updateSlide)); this._dash.connect('icon-size-changed', Lang.bind(this, this._updateSlide));
Main.overview.connect('hiding', Lang.bind(this, this.slideOut));
}, },
getSlide: function() { _getSlide: function() {
if (this.visible || this.inDrag) if (this._visible || this._inDrag)
return 1; return 1;
else else
return 0; return 0;
}, },
_onOverviewShowing: function() {
this.visible = true;
this.layout.slideX = this.getSlide();
this.actor.translation_x = this._getTranslation();
this.slideIn();
},
_onWindowDragBegin: function() { _onWindowDragBegin: function() {
this.fadeHalf(); this.fadeHalf();
}, },

View File

@ -1114,7 +1114,7 @@ const PopupMenuManager = new Lang.Class({
removeMenu: function(menu) { removeMenu: function(menu) {
if (menu == this.activeMenu) if (menu == this.activeMenu)
this._closeMenu(menu); this._closeMenu(false, menu);
let position = this._findMenu(menu); let position = this._findMenu(menu);
if (position == -1) // not a menu we manage if (position == -1) // not a menu we manage

View File

@ -7,58 +7,63 @@ const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
const FileUtils = imports.misc.fileUtils;
const Search = imports.ui.search; const Search = imports.ui.search;
const KEY_FILE_GROUP = 'Shell Search Provider'; const KEY_FILE_GROUP = 'Shell Search Provider';
const SearchProviderIface = <interface name="org.gnome.Shell.SearchProvider"> const SearchProviderIface = '<node> \
<method name="GetInitialResultSet"> <interface name="org.gnome.Shell.SearchProvider"> \
<arg type="as" direction="in" /> <method name="GetInitialResultSet"> \
<arg type="as" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="as" direction="out" /> \
<method name="GetSubsearchResultSet"> </method> \
<arg type="as" direction="in" /> <method name="GetSubsearchResultSet"> \
<arg type="as" direction="in" /> <arg type="as" direction="in" /> \
<arg type="as" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="as" direction="out" /> \
<method name="GetResultMetas"> </method> \
<arg type="as" direction="in" /> <method name="GetResultMetas"> \
<arg type="aa{sv}" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="aa{sv}" direction="out" /> \
<method name="ActivateResult"> </method> \
<arg type="s" direction="in" /> <method name="ActivateResult"> \
</method> <arg type="s" direction="in" /> \
</interface>; </method> \
</interface> \
</node>';
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2"> const SearchProvider2Iface = '<node> \
<method name="GetInitialResultSet"> <interface name="org.gnome.Shell.SearchProvider2"> \
<arg type="as" direction="in" /> <method name="GetInitialResultSet"> \
<arg type="as" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="as" direction="out" /> \
<method name="GetSubsearchResultSet"> </method> \
<arg type="as" direction="in" /> <method name="GetSubsearchResultSet"> \
<arg type="as" direction="in" /> <arg type="as" direction="in" /> \
<arg type="as" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="as" direction="out" /> \
<method name="GetResultMetas"> </method> \
<arg type="as" direction="in" /> <method name="GetResultMetas"> \
<arg type="aa{sv}" direction="out" /> <arg type="as" direction="in" /> \
</method> <arg type="aa{sv}" direction="out" /> \
<method name="ActivateResult"> </method> \
<arg type="s" direction="in" /> <method name="ActivateResult"> \
<arg type="as" direction="in" /> <arg type="s" direction="in" /> \
<arg type="u" direction="in" /> <arg type="as" direction="in" /> \
</method> <arg type="u" direction="in" /> \
<method name="LaunchSearch"> </method> \
<arg type="as" direction="in" /> <method name="LaunchSearch"> \
<arg type="u" direction="in" /> <arg type="as" direction="in" /> \
</method> <arg type="u" direction="in" /> \
</interface>; </method> \
</interface> \
</node>';
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface); var SearchProviderProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProviderIface);
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface); var SearchProvider2ProxyInfo = Gio.DBusInterfaceInfo.new_for_xml(SearchProvider2Iface);
function loadRemoteSearchProviders(addProviderCallback) { function loadRemoteSearchProviders(callback) {
let objectPaths = {}; let objectPaths = {};
let loadedProviders = []; let loadedProviders = [];
@ -112,30 +117,25 @@ function loadRemoteSearchProviders(addProviderCallback) {
} }
} }
let dataDirs = GLib.get_system_data_dirs();
dataDirs.forEach(function(dataDir) {
let path = GLib.build_filenamev([dataDir, 'gnome-shell', 'search-providers']);
let dir = Gio.File.new_for_path(path);
let fileEnum;
try {
fileEnum = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
fileEnum = null;
}
if (fileEnum != null) {
let info;
while ((info = fileEnum.next_file(null)))
loadRemoteSearchProvider(fileEnum.get_child(info));
}
});
let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA }); let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
if (searchSettings.get_boolean('disable-external')) {
callback([]);
return;
}
FileUtils.collectFromDatadirs('search-providers', false, loadRemoteSearchProvider);
let sortOrder = searchSettings.get_strv('sort-order'); let sortOrder = searchSettings.get_strv('sort-order');
// Special case gnome-control-center to be always active and always first // Special case gnome-control-center to be always active and always first
sortOrder.unshift('gnome-control-center.desktop'); sortOrder.unshift('gnome-control-center.desktop');
loadedProviders = loadedProviders.filter(function(provider) {
let appId = provider.appInfo.get_id();
let disabled = searchSettings.get_strv('disabled');
return disabled.indexOf(appId) == -1;
});
loadedProviders.sort(function(providerA, providerB) { loadedProviders.sort(function(providerA, providerB) {
let idxA, idxB; let idxA, idxB;
let appIdA, appIdB; let appIdA, appIdB;
@ -166,28 +166,28 @@ function loadRemoteSearchProviders(addProviderCallback) {
return (idxA - idxB); return (idxA - idxB);
}); });
loadedProviders.forEach(addProviderCallback); callback(loadedProviders);
} }
const RemoteSearchProvider = new Lang.Class({ const RemoteSearchProvider = new Lang.Class({
Name: 'RemoteSearchProvider', Name: 'RemoteSearchProvider',
_init: function(appInfo, dbusName, dbusPath, proxyType) { _init: function(appInfo, dbusName, dbusPath, proxyInfo) {
if (!proxyType) if (!proxyInfo)
proxyType = SearchProviderProxy; proxyInfo = SearchProviderProxyInfo;
this.proxy = new proxyType(Gio.DBus.session, this.proxy = new Gio.DBusProxy({ g_bus_type: Gio.BusType.SESSION,
dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed)); g_name: dbusName,
g_object_path: dbusPath,
g_interface_info: proxyInfo,
g_interface_name: proxyInfo.name,
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
this.proxy.init_async(GLib.PRIORITY_DEFAULT, null, null);
this.appInfo = appInfo; this.appInfo = appInfo;
this.id = appInfo.get_id(); this.id = appInfo.get_id();
this.isRemoteProvider = true; this.isRemoteProvider = true;
this._cancellable = new Gio.Cancellable();
},
_onProxyConstructed: function(proxy) {
// Do nothing
}, },
createIcon: function(size, meta) { createIcon: function(size, meta) {
@ -217,40 +217,33 @@ const RemoteSearchProvider = new Lang.Class({
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber)); return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
}, },
_getResultsFinished: function(results, error) { _getResultsFinished: function(results, error, callback) {
if (error) if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from DBus search provider %s: %s'.format(this.id, String(error)));
callback([]);
return; return;
this.searchSystem.setResults(this, results[0]); }
callback(results[0]);
}, },
getInitialResultSet: function(terms) { getInitialResultSet: function(terms, callback, cancellable) {
this._cancellable.cancel(); this.proxy.GetInitialResultSetRemote(terms,
this._cancellable.reset(); Lang.bind(this, this._getResultsFinished, callback),
try { cancellable);
this.proxy.GetInitialResultSetRemote(terms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
this.searchSystem.setResults(this, []);
}
}, },
getSubsearchResultSet: function(previousResults, newTerms) { getSubsearchResultSet: function(previousResults, newTerms, callback, cancellable) {
this._cancellable.cancel(); this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
this._cancellable.reset(); Lang.bind(this, this._getResultsFinished, callback),
try { cancellable);
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
Lang.bind(this, this._getResultsFinished),
this._cancellable);
} catch(e) {
log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
this.searchSystem.setResults(this, []);
}
}, },
_getResultMetasFinished: function(results, error, callback) { _getResultMetasFinished: function(results, error, callback) {
if (error) { if (error) {
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log('Received error from DBus search provider %s during GetResultMetas: %s'.format(this.id, String(error)));
callback([]); callback([]);
return; return;
} }
@ -272,17 +265,10 @@ const RemoteSearchProvider = new Lang.Class({
callback(resultMetas); callback(resultMetas);
}, },
getResultMetas: function(ids, callback) { getResultMetas: function(ids, callback, cancellable) {
this._cancellable.cancel(); this.proxy.GetResultMetasRemote(ids,
this._cancellable.reset(); Lang.bind(this, this._getResultMetasFinished, callback),
try { cancellable);
this.proxy.GetResultMetasRemote(ids,
Lang.bind(this, this._getResultMetasFinished, callback),
this._cancellable);
} catch(e) {
log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
callback([]);
}
}, },
activateResult: function(id) { activateResult: function(id) {
@ -302,7 +288,7 @@ const RemoteSearchProvider2 = new Lang.Class({
Extends: RemoteSearchProvider, Extends: RemoteSearchProvider,
_init: function(appInfo, dbusName, dbusPath) { _init: function(appInfo, dbusName, dbusPath) {
this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy); this.parent(appInfo, dbusName, dbusPath, SearchProvider2ProxyInfo);
this.canLaunchSearch = true; this.canLaunchSearch = true;
}, },

View File

@ -198,8 +198,8 @@ const NotificationsBox = new Lang.Class({
let body = ''; let body = '';
if (n.bannerBodyText) { if (n.bannerBodyText) {
body = n.bannerBodyMarkup ? n.bannerBodyText : body = n.bannerBodyMarkup ? n.bannerBodyText
GLib.markup_escape_text(n.bannerBodyMarkup, -1); : GLib.markup_escape_text(n.bannerBodyText, -1);
} }
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' }); let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });

View File

@ -9,27 +9,29 @@ const Signals = imports.signals;
const Hash = imports.misc.hash; const Hash = imports.misc.hash;
const Main = imports.ui.main; const Main = imports.ui.main;
const ScreencastIface = <interface name="org.gnome.Shell.Screencast"> const ScreencastIface = '<node> \
<method name="Screencast"> <interface name="org.gnome.Shell.Screencast"> \
<arg type="s" direction="in" name="file_template"/> <method name="Screencast"> \
<arg type="a{sv}" direction="in" name="options"/> <arg type="s" direction="in" name="file_template"/> \
<arg type="b" direction="out" name="success"/> <arg type="a{sv}" direction="in" name="options"/> \
<arg type="s" direction="out" name="filename_used"/> <arg type="b" direction="out" name="success"/> \
</method> <arg type="s" direction="out" name="filename_used"/> \
<method name="ScreencastArea"> </method> \
<arg type="i" direction="in" name="x"/> <method name="ScreencastArea"> \
<arg type="i" direction="in" name="y"/> <arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="width"/> <arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="height"/> <arg type="i" direction="in" name="width"/> \
<arg type="s" direction="in" name="file_template"/> <arg type="i" direction="in" name="height"/> \
<arg type="a{sv}" direction="in" name="options"/> <arg type="s" direction="in" name="file_template"/> \
<arg type="b" direction="out" name="success"/> <arg type="a{sv}" direction="in" name="options"/> \
<arg type="s" direction="out" name="filename_used"/> <arg type="b" direction="out" name="success"/> \
</method> <arg type="s" direction="out" name="filename_used"/> \
<method name="StopScreencast"> </method> \
<arg type="b" direction="out" name="success"/> <method name="StopScreencast"> \
</method> <arg type="b" direction="out" name="success"/> \
</interface>; </method> \
</interface> \
</node>';
const ScreencastService = new Lang.Class({ const ScreencastService = new Lang.Class({
Name: 'ScreencastService', Name: 'ScreencastService',
@ -103,8 +105,10 @@ const ScreencastService = new Lang.Class({
ScreencastAsync: function(params, invocation) { ScreencastAsync: function(params, invocation) {
let returnValue = [false, '']; let returnValue = [false, ''];
if (!Main.sessionMode.allowScreencast) if (!Main.sessionMode.allowScreencast) {
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));
return;
}
let sender = invocation.get_sender(); let sender = invocation.get_sender();
let recorder = this._ensureRecorderForSender(sender); let recorder = this._ensureRecorderForSender(sender);
@ -122,8 +126,10 @@ const ScreencastService = new Lang.Class({
ScreencastAreaAsync: function(params, invocation) { ScreencastAreaAsync: function(params, invocation) {
let returnValue = [false, '']; let returnValue = [false, ''];
if (!Main.sessionMode.allowScreencast) if (!Main.sessionMode.allowScreencast) {
invocation.return_value(GLib.Variant.new('(bs)', returnValue)); invocation.return_value(GLib.Variant.new('(bs)', returnValue));
return;
}
let sender = invocation.get_sender(); let sender = invocation.get_sender();
let recorder = this._ensureRecorderForSender(sender); let recorder = this._ensureRecorderForSender(sender);
@ -131,6 +137,16 @@ const ScreencastService = new Lang.Class({
if (!recorder.is_recording()) { if (!recorder.is_recording()) {
let [x, y, width, height, fileTemplate, options] = params; let [x, y, width, height, fileTemplate, options] = params;
if (x < 0 || y < 0 ||
width <= 0 || height <= 0 ||
x + width > global.screen_width ||
y + height > global.screen_height) {
invocation.return_error_literal(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED,
"Invalid params");
return;
}
recorder.set_file_template(fileTemplate); recorder.set_file_template(fileTemplate);
recorder.set_area(x, y, width, height); recorder.set_area(x, y, width, height);
this._applyOptionalParameters(recorder, options); this._applyOptionalParameters(recorder, options);

View File

@ -15,45 +15,47 @@ const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const ScreenshotIface = <interface name="org.gnome.Shell.Screenshot"> const ScreenshotIface = '<node> \
<method name="ScreenshotArea"> <interface name="org.gnome.Shell.Screenshot"> \
<arg type="i" direction="in" name="x"/> <method name="ScreenshotArea"> \
<arg type="i" direction="in" name="y"/> <arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="width"/> <arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="height"/> <arg type="i" direction="in" name="width"/> \
<arg type="b" direction="in" name="flash"/> <arg type="i" direction="in" name="height"/> \
<arg type="s" direction="in" name="filename"/> <arg type="b" direction="in" name="flash"/> \
<arg type="b" direction="out" name="success"/> <arg type="s" direction="in" name="filename"/> \
<arg type="s" direction="out" name="filename_used"/> <arg type="b" direction="out" name="success"/> \
</method> <arg type="s" direction="out" name="filename_used"/> \
<method name="ScreenshotWindow"> </method> \
<arg type="b" direction="in" name="include_frame"/> <method name="ScreenshotWindow"> \
<arg type="b" direction="in" name="include_cursor"/> <arg type="b" direction="in" name="include_frame"/> \
<arg type="b" direction="in" name="flash"/> <arg type="b" direction="in" name="include_cursor"/> \
<arg type="s" direction="in" name="filename"/> <arg type="b" direction="in" name="flash"/> \
<arg type="b" direction="out" name="success"/> <arg type="s" direction="in" name="filename"/> \
<arg type="s" direction="out" name="filename_used"/> <arg type="b" direction="out" name="success"/> \
</method> <arg type="s" direction="out" name="filename_used"/> \
<method name="Screenshot"> </method> \
<arg type="b" direction="in" name="include_cursor"/> <method name="Screenshot"> \
<arg type="b" direction="in" name="flash"/> <arg type="b" direction="in" name="include_cursor"/> \
<arg type="s" direction="in" name="filename"/> <arg type="b" direction="in" name="flash"/> \
<arg type="b" direction="out" name="success"/> <arg type="s" direction="in" name="filename"/> \
<arg type="s" direction="out" name="filename_used"/> <arg type="b" direction="out" name="success"/> \
</method> <arg type="s" direction="out" name="filename_used"/> \
<method name="SelectArea"> </method> \
<arg type="i" direction="out" name="x"/> <method name="SelectArea"> \
<arg type="i" direction="out" name="y"/> <arg type="i" direction="out" name="x"/> \
<arg type="i" direction="out" name="width"/> <arg type="i" direction="out" name="y"/> \
<arg type="i" direction="out" name="height"/> <arg type="i" direction="out" name="width"/> \
</method> <arg type="i" direction="out" name="height"/> \
<method name="FlashArea"> </method> \
<arg type="i" direction="in" name="x"/> <method name="FlashArea"> \
<arg type="i" direction="in" name="y"/> <arg type="i" direction="in" name="x"/> \
<arg type="i" direction="in" name="width"/> <arg type="i" direction="in" name="y"/> \
<arg type="i" direction="in" name="height"/> <arg type="i" direction="in" name="width"/> \
</method> <arg type="i" direction="in" name="height"/> \
</interface>; </method> \
</interface> \
</node>';
const ScreenshotService = new Lang.Class({ const ScreenshotService = new Lang.Class({
Name: 'ScreenshotService', Name: 'ScreenshotService',
@ -77,7 +79,9 @@ const ScreenshotService = new Lang.Class({
ScreenshotAreaAsync : function (params, invocation) { ScreenshotAreaAsync : function (params, invocation) {
let [x, y, width, height, flash, filename, callback] = params; let [x, y, width, height, flash, filename, callback] = params;
if (height <= 0 || width <= 0) { if (x < 0 || y < 0 ||
width <= 0 || height <= 0 ||
x + width > global.screen_width || y + height > global.screen_height) {
invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED, invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
"Invalid params"); "Invalid params");
return; return;

View File

@ -69,16 +69,18 @@ function waitLeisure() {
}; };
} }
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper"> const PerfHelperIface = '<node> \
<method name="CreateWindow"> <interface name="org.gnome.Shell.PerfHelper"> \
<arg type="i" direction="in" /> <method name="CreateWindow"> \
<arg type="i" direction="in" /> <arg type="i" direction="in" /> \
<arg type="b" direction="in" /> <arg type="i" direction="in" /> \
<arg type="b" direction="in" /> <arg type="b" direction="in" /> \
</method> <arg type="b" direction="in" /> \
<method name="WaitWindows" /> </method> \
<method name="DestroyWindows" /> <method name="WaitWindows" /> \
</interface>; <method name="DestroyWindows" /> \
</interface> \
</node>';
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface); var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
function PerfHelper() { function PerfHelper() {

View File

@ -1,105 +1,706 @@
// -*- 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 Lang = imports.lang; const Lang = imports.lang;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Signals = imports.signals; const Signals = imports.signals;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const AppDisplay = imports.ui.appDisplay;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const RemoteSearch = imports.ui.remoteSearch;
const Separator = imports.ui.separator;
const Util = imports.misc.util;
const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers'; const SEARCH_PROVIDERS_SCHEMA = 'org.gnome.desktop.search-providers';
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const SearchSystem = new Lang.Class({ const SearchSystem = new Lang.Class({
Name: 'SearchSystem', Name: 'SearchSystem',
_init: function() { _init: function() {
this._providers = []; this._providers = [];
this._remoteProviders = [];
this.reset(); this._registerProvider(new AppDisplay.AppSearchProvider());
this._searchSettings = new Gio.Settings({ schema: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
this._reloadRemoteProviders();
this._cancellable = new Gio.Cancellable();
}, },
registerProvider: function (provider) { addProvider: function(provider) {
provider.searchSystem = this;
this._providers.push(provider); this._providers.push(provider);
this.emit('providers-changed');
if (provider.isRemoteProvider)
this._remoteProviders.push(provider);
}, },
unregisterProvider: function (provider) { _reloadRemoteProviders: function() {
let index = this._providers.indexOf(provider); let remoteProviders = this._providers.filter(function(provider) {
if (index == -1) return provider.isRemoteProvider;
return; });
provider.searchSystem = null; remoteProviders.forEach(Lang.bind(this, function(provider) {
this._providers.splice(index, 1); this._unregisterProvider(provider);
}));
let remoteIndex = this._remoteProviders.indexOf(provider); RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, function(providers) {
if (remoteIndex != -1) providers.forEach(Lang.bind(this, this._registerProvider));
this._remoteProviders.splice(remoteIndex, 1); }));
this.emit('providers-changed');
},
_registerProvider: function (provider) {
this._providers.push(provider);
},
_unregisterProvider: function (provider) {
let index = this._providers.indexOf(provider);
this._providers.splice(index, 1);
}, },
getProviders: function() { getProviders: function() {
return this._providers; return this._providers;
}, },
getRemoteProviders: function() {
return this._remoteProviders;
},
getTerms: function() { getTerms: function() {
return this._previousTerms; return this._terms;
}, },
reset: function() { reset: function() {
this._previousTerms = []; this._terms = [];
this._previousResults = []; this._results = {};
}, },
setResults: function(provider, results) { _gotResults: function(results, provider) {
let i = this._providers.indexOf(provider); this._results[provider.id] = results;
if (i == -1) this.emit('search-updated', provider, results);
return;
this._previousResults[i] = [provider, results];
this.emit('search-updated', this._previousResults[i]);
}, },
updateSearchResults: function(terms) { setTerms: function(terms) {
this._cancellable.cancel();
this._cancellable.reset();
let previousResults = this._results;
let previousTerms = this._terms;
this.reset();
if (!terms) if (!terms)
return; return;
let searchString = terms.join(' '); let searchString = terms.join(' ');
let previousSearchString = this._previousTerms.join(' '); let previousSearchString = previousTerms.join(' ');
if (searchString == previousSearchString) if (searchString == previousSearchString)
return; return;
let isSubSearch = false; let isSubSearch = false;
if (this._previousTerms.length > 0) if (previousTerms.length > 0)
isSubSearch = searchString.indexOf(previousSearchString) == 0; isSubSearch = searchString.indexOf(previousSearchString) == 0;
let previousResultsArr = this._previousResults; this._terms = terms;
let results = []; this._providers.forEach(Lang.bind(this, function(provider) {
this._previousTerms = terms; let previousProviderResults = previousResults[provider.id];
this._previousResults = results; if (isSubSearch && previousProviderResults)
provider.getSubsearchResultSet(previousProviderResults, terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
if (isSubSearch) { else
for (let i = 0; i < this._providers.length; i++) { provider.getInitialResultSet(terms, Lang.bind(this, this._gotResults, provider), this._cancellable);
let [provider, previousResults] = previousResultsArr[i]; }));
try {
results.push([provider, []]);
provider.getSubsearchResultSet(previousResults, terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
}
}
} else {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
try {
results.push([provider, []]);
provider.getInitialResultSet(terms);
} catch (error) {
log('A ' + error.name + ' has occured in ' + provider.id + ': ' + error.message);
}
}
}
} }
}); });
Signals.addSignalMethods(SearchSystem.prototype); Signals.addSignalMethods(SearchSystem.prototype);
const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin',
Extends: St.Bin,
vfunc_allocate: function(box, flags) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
let adjustedBox = box;
if (availWidth > maxWidth) {
let excessWidth = availWidth - maxWidth;
adjustedBox.x1 += Math.floor(excessWidth / 2);
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
this.parent(adjustedBox, flags);
}
});
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo) {
this.provider = provider;
this.metaInfo = metaInfo;
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this.activate));
},
activate: function() {
this.emit('activate', this.metaInfo.id);
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
}
});
Signals.addSignalMethods(SearchResult.prototype);
const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon) {
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let title = new St.Label({ style_class: 'list-search-result-title',
text: this.metaInfo['name'] })
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.label_actor = title;
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
}
}
});
const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo) {
this.parent(provider, metaInfo);
this.actor.style_class = 'grid-search-result';
let content = provider.createResultObject(metaInfo);
let dragSource = null;
if (content == null) {
let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
this._dragActorSource = dragSource;
},
getDragActorSource: function() {
return this._dragActorSource;
},
getDragActor: function() {
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
},
shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params);
else
this.provider.activateResult(this.metaInfo.id, this.terms);
}
});
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
this.provider = provider;
this._terms = [];
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
this._resultDisplays = {};
this._cancellable = new Gio.Cancellable();
},
destroy: function() {
this.actor.destroy();
this._terms = [];
},
_clearResultDisplay: function() {
},
clear: function() {
this._resultDisplays = {};
this._clearResultDisplay();
this.actor.hide();
},
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_activateResult: function(result, id) {
this.provider.activateResult(id, this._terms);
Main.overview.toggle();
},
_setMoreIconVisible: function(visible) {
},
_ensureResultActors: function(results, callback) {
let metasNeeded = results.filter(Lang.bind(this, function(resultId) {
return this._resultDisplays[resultId] === undefined;
}));
if (metasNeeded.length === 0) {
callback();
} else {
this._cancellable.cancel();
this._cancellable.reset();
this.provider.getResultMetas(metasNeeded, Lang.bind(this, function(metas) {
metasNeeded.forEach(Lang.bind(this, function(resultId, i) {
let meta = metas[i];
let display = this._createResultDisplay(meta);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._resultDisplays[resultId] = display;
}));
callback();
}), this._cancellable);
}
},
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = this.provider.filterResults(providerResults, maxResults);
let hasMoreResults = results.length < providerResults.length;
this._ensureResultActors(results, Lang.bind(this, function() {
this._clearResultDisplay();
// To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the
// content while filling in the results.
this.actor.hide();
this._clearResultDisplay();
results.forEach(Lang.bind(this, function(resultId) {
this._addItem(this._resultDisplays[resultId]);
}));
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this.actor.show();
callback();
}));
}
}
});
const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this._container.add(this._content, { expand: true });
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = true;
},
_getMaxDisplayedResults: function() {
return MAX_LIST_SEARCH_RESULTS_ROWS;
},
_clearResultDisplay: function () {
this._content.remove_all_children();
},
_createResultDisplay: function(meta) {
return new ListSearchResult(this.provider, meta);
},
_addItem: function(display) {
this._content.add_actor(display.actor);
},
getFirstResult: function() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(ListSearchResults.prototype);
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid.actor);
this._resultDisplayBin.set_child(this._bin);
},
_getMaxDisplayedResults: function() {
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i]);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
},
_clearResultDisplay: function () {
this._grid.removeAll();
},
_createResultDisplay: function(meta) {
return new GridSearchResult(this.provider, meta);
},
_addItem: function(display) {
this._grid.addItem(display);
},
getFirstResult: function() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(GridSearchResults.prototype);
const SearchResults = new Lang.Class({
Name: 'SearchResults',
_init: function() {
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true });
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
x_fill: true,
y_fill: true,
child: this._content });
let scrollChild = new St.BoxLayout();
scrollChild.add(this._contentBin, { expand: true });
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
overlay_scrollbars: true,
style_class: 'search-display vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(scrollChild);
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this._scrollView.add_action(action);
this.actor.add(this._scrollView, { x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._highlightDefault = false;
this._defaultResult = null;
this._searchSystem = new SearchSystem();
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this._searchSystem.connect('providers-changed', Lang.bind(this, this._updateProviderDisplays));
this._updateProviderDisplays();
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
_keyFocusIn: function(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
_ensureProviderDisplay: function(provider) {
if (provider.display)
return;
let providerDisplay;
if (provider.appInfo)
providerDisplay = new ListSearchResults(provider);
else
providerDisplay = new GridSearchResults(provider);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._content.add(providerDisplay.actor);
provider.display = providerDisplay;
},
_updateProviderDisplays: function() {
this._searchSystem.getProviders().forEach(Lang.bind(this, this._ensureProviderDisplay));
},
_clearDisplay: function() {
this._searchSystem.getProviders().forEach(function(provider) {
provider.display.clear();
});
},
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._clearDisplay();
this._defaultResult = null;
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching…"));
this._statusBin.show();
},
setTerms: function(terms) {
this._searchSystem.setTerms(terms);
},
_maybeSetInitialSelection: function() {
let newDefaultResult = null;
let providers = this._searchSystem.getProviders();
for (let i = 0; i < providers.length; i++) {
let provider = providers[i];
let display = provider.display;
if (!display.actor.visible)
continue;
let firstResult = display.getFirstResult();
if (firstResult) {
newDefaultResult = firstResult;
break; // select this one!
}
}
if (newDefaultResult != this._defaultResult) {
if (this._defaultResult)
this._defaultResult.setSelected(false);
if (newDefaultResult)
newDefaultResult.setSelected(this._highlightDefault);
this._defaultResult = newDefaultResult;
}
},
_updateStatusText: function () {
let haveResults = this._searchSystem.getProviders().some(function(provider) {
let display = provider.display;
return (display.getFirstResult() != null);
});
if (!haveResults) {
this._statusText.set_text(_("No results."));
this._statusBin.show();
} else {
this._statusBin.hide();
}
},
_updateResults: function(searchSystem, provider, results) {
let terms = searchSystem.getTerms();
let display = provider.display;
display.updateSearch(results, terms, Lang.bind(this, function() {
this._maybeSetInitialSelection();
this._updateStatusText();
}));
},
activateDefault: function() {
if (this._defaultResult)
this._defaultResult.activate();
},
highlightDefault: function(highlight) {
this._highlightDefault = highlight;
if (this._defaultResult)
this._defaultResult.setSelected(highlight);
},
navigateFocus: function(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
direction == (rtl ? Gtk.DirectionType.RIGHT
: Gtk.DirectionType.LEFT) ||
direction == Gtk.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
}
});
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
_init: function(provider) {
this.provider = provider;
this.parent({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
}
});

View File

@ -1,567 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Signals = imports.signals;
const St = imports.gi.St;
const Atk = imports.gi.Atk;
const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Separator = imports.ui.separator;
const Search = imports.ui.search;
const Util = imports.misc.util;
const MAX_LIST_SEARCH_RESULTS_ROWS = 3;
const MAX_GRID_SEARCH_RESULTS_ROWS = 1;
const MaxWidthBin = new Lang.Class({
Name: 'MaxWidthBin',
Extends: St.Bin,
vfunc_allocate: function(box, flags) {
let themeNode = this.get_theme_node();
let maxWidth = themeNode.get_max_width();
let availWidth = box.x2 - box.x1;
let adjustedBox = box;
if (availWidth > maxWidth) {
let excessWidth = availWidth - maxWidth;
adjustedBox.x1 += Math.floor(excessWidth / 2);
adjustedBox.x2 -= Math.floor(excessWidth / 2);
}
this.parent(adjustedBox, flags);
}
});
const SearchResult = new Lang.Class({
Name: 'SearchResult',
_init: function(provider, metaInfo, terms) {
this.provider = provider;
this.metaInfo = metaInfo;
this.terms = terms;
this.actor = new St.Button({ reactive: true,
can_focus: true,
track_hover: true,
x_align: St.Align.START,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('clicked', Lang.bind(this, this.activate));
},
activate: function() {
this.provider.activateResult(this.metaInfo.id, this.terms);
Main.overview.toggle();
},
setSelected: function(selected) {
if (selected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
}
});
const ListSearchResult = new Lang.Class({
Name: 'ListSearchResult',
Extends: SearchResult,
ICON_SIZE: 64,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'list-search-result';
this.actor.x_fill = true;
let content = new St.BoxLayout({ style_class: 'list-search-result-content',
vertical: false });
this.actor.set_child(content);
// An icon for, or thumbnail of, content
let icon = this.metaInfo['createIcon'](this.ICON_SIZE);
if (icon) {
content.add(icon);
}
let details = new St.BoxLayout({ vertical: true });
content.add(details, { x_fill: true,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let title = new St.Label({ style_class: 'list-search-result-title',
text: this.metaInfo['name'] })
details.add(title, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.label_actor = title;
if (this.metaInfo['description']) {
let description = new St.Label({ style_class: 'list-search-result-description' });
description.clutter_text.set_markup(this.metaInfo['description']);
details.add(description, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.END });
}
}
});
const GridSearchResult = new Lang.Class({
Name: 'GridSearchResult',
Extends: SearchResult,
_init: function(provider, metaInfo, terms) {
this.parent(provider, metaInfo, terms);
this.actor.style_class = 'grid-search-result';
let content = provider.createResultObject(metaInfo, terms);
let dragSource = null;
if (content == null) {
let actor = new St.Bin();
let icon = new IconGrid.BaseIcon(this.metaInfo['name'],
{ createIcon: this.metaInfo['createIcon'] });
actor.set_child(icon.actor);
actor.label_actor = icon.label;
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
}
this.actor.set_child(content.actor);
this.actor.label_actor = content.actor.label_actor;
this.icon = content.icon;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-cancelled',
Lang.bind(this, function() {
Main.overview.cancelledItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
this._dragActorSource = dragSource;
},
getDragActorSource: function() {
return this._dragActorSource;
},
getDragActor: function() {
return this.metaInfo['createIcon'](Main.overview.dashIconSize);
},
shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id, params);
else
this.provider.activateResult(this.metaInfo.id, this.terms);
}
});
const SearchResultsBase = new Lang.Class({
Name: 'SearchResultsBase',
_init: function(provider) {
this.provider = provider;
this._terms = [];
this.actor = new St.BoxLayout({ style_class: 'search-section',
vertical: true });
this._resultDisplayBin = new St.Bin({ x_fill: true,
y_fill: true });
this.actor.add(this._resultDisplayBin, { expand: true });
let separator = new Separator.HorizontalSeparator({ style_class: 'search-section-separator' });
this.actor.add(separator.actor);
},
destroy: function() {
this.actor.destroy();
this._terms = [];
},
_clearResultDisplay: function() {
},
clear: function() {
this._clearResultDisplay();
this.actor.hide();
},
_keyFocusIn: function(actor) {
this.emit('key-focus-in', actor);
},
_setMoreIconVisible: function(visible) {
},
updateSearch: function(providerResults, terms, callback) {
this._terms = terms;
if (providerResults.length == 0) {
this._clearResultDisplay();
this.actor.hide();
callback();
} else {
let maxResults = this._getMaxDisplayedResults();
let results = this.provider.filterResults(providerResults, maxResults);
let hasMoreResults = results.length < providerResults.length;
this.provider.getResultMetas(results, Lang.bind(this, function(metas) {
this.clear();
// To avoid CSS transitions causing flickering when
// the first search result stays the same, we hide the
// content while filling in the results.
this.actor.hide();
this._clearResultDisplay();
this._renderResults(metas);
this._setMoreIconVisible(hasMoreResults && this.provider.canLaunchSearch);
this.actor.show();
callback();
}));
}
}
});
const ListSearchResults = new Lang.Class({
Name: 'ListSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._container = new St.BoxLayout({ style_class: 'search-section-content' });
this.providerIcon = new ProviderIcon(provider);
this.providerIcon.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this.providerIcon.connect('clicked', Lang.bind(this,
function() {
provider.launchSearch(this._terms);
Main.overview.toggle();
}));
this._container.add(this.providerIcon, { x_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
this._content = new St.BoxLayout({ style_class: 'list-search-results',
vertical: true });
this._container.add(this._content, { expand: true });
this._resultDisplayBin.set_child(this._container);
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = true;
},
_getMaxDisplayedResults: function() {
return MAX_LIST_SEARCH_RESULTS_ROWS;
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new ListSearchResult(this.provider, metas[i], this._terms);
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._content.add_actor(display.actor);
}
},
_clearResultDisplay: function () {
this._content.destroy_all_children();
},
getFirstResult: function() {
if (this._content.get_n_children() > 0)
return this._content.get_child_at_index(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(ListSearchResults.prototype);
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
this.parent(provider);
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this._bin = new St.Bin({ x_align: St.Align.MIDDLE });
this._bin.set_child(this._grid.actor);
this._resultDisplayBin.set_child(this._bin);
},
_getMaxDisplayedResults: function() {
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i], this._terms);
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
},
_clearResultDisplay: function () {
this._grid.removeAll();
},
getFirstResult: function() {
if (this._grid.visibleItemsCount() > 0)
return this._grid.getItemAtIndex(0)._delegate;
else
return null;
}
});
Signals.addSignalMethods(GridSearchResults.prototype);
const SearchResults = new Lang.Class({
Name: 'SearchResults',
_init: function(searchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateResults));
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true });
this._contentBin = new MaxWidthBin({ name: 'searchResultsBin',
x_fill: true,
y_fill: true,
child: this._content });
let scrollChild = new St.BoxLayout();
scrollChild.add(this._contentBin, { expand: true });
this._scrollView = new St.ScrollView({ x_fill: true,
y_fill: false,
overlay_scrollbars: true,
style_class: 'search-display vfade' });
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._scrollView.add_actor(scrollChild);
let action = new Clutter.PanAction({ interpolate: true });
action.connect('pan', Lang.bind(this, this._onPan));
this._scrollView.add_action(action);
this.actor.add(this._scrollView, { x_fill: true,
y_fill: true,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this._statusText = new St.Label({ style_class: 'search-statustext' });
this._statusBin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._content.add(this._statusBin, { expand: true });
this._statusBin.add_actor(this._statusText);
this._providers = this._searchSystem.getProviders();
this._providerDisplays = {};
for (let i = 0; i < this._providers.length; i++) {
this.createProviderDisplay(this._providers[i]);
}
this._highlightDefault = false;
this._defaultResult = null;
},
_onPan: function(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let adjustment = this._scrollView.vscroll.adjustment;
adjustment.value -= (dy / this.actor.height) * adjustment.page_size;
return false;
},
_keyFocusIn: function(provider, actor) {
Util.ensureActorVisibleInScrollView(this._scrollView, actor);
},
createProviderDisplay: function(provider) {
let providerDisplay = null;
if (provider.appInfo) {
providerDisplay = new ListSearchResults(provider);
} else {
providerDisplay = new GridSearchResults(provider);
}
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._providerDisplays[provider.id] = providerDisplay;
this._content.add(providerDisplay.actor);
},
destroyProviderDisplay: function(provider) {
this._providerDisplays[provider.id].destroy();
delete this._providerDisplays[provider.id];
},
_clearDisplay: function() {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let providerDisplay = this._providerDisplays[provider.id];
providerDisplay.clear();
}
},
reset: function() {
this._searchSystem.reset();
this._statusBin.hide();
this._clearDisplay();
this._defaultResult = null;
},
startingSearch: function() {
this.reset();
this._statusText.set_text(_("Searching…"));
this._statusBin.show();
},
_maybeSetInitialSelection: function() {
let newDefaultResult = null;
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let display = this._providerDisplays[provider.id];
if (!display.actor.visible)
continue;
let firstResult = display.getFirstResult();
if (firstResult) {
newDefaultResult = firstResult;
break; // select this one!
}
}
if (newDefaultResult != this._defaultResult) {
if (this._defaultResult)
this._defaultResult.setSelected(false);
if (newDefaultResult)
newDefaultResult.setSelected(this._highlightDefault);
this._defaultResult = newDefaultResult;
}
},
_updateStatusText: function () {
let haveResults = false;
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let display = this._providerDisplays[provider.id];
if (display.getFirstResult()) {
haveResults = true;
break;
}
}
if (!haveResults) {
this._statusText.set_text(_("No results."));
this._statusBin.show();
} else {
this._statusBin.hide();
}
},
_updateResults: function(searchSystem, results) {
let terms = searchSystem.getTerms();
let [provider, providerResults] = results;
let display = this._providerDisplays[provider.id];
display.updateSearch(providerResults, terms, Lang.bind(this, function() {
this._maybeSetInitialSelection();
this._updateStatusText();
}));
},
activateDefault: function() {
if (this._defaultResult)
this._defaultResult.activate();
},
highlightDefault: function(highlight) {
this._highlightDefault = highlight;
if (this._defaultResult)
this._defaultResult.setSelected(highlight);
},
navigateFocus: function(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == Gtk.DirectionType.TAB_BACKWARD ||
direction == (rtl ? Gtk.DirectionType.RIGHT
: Gtk.DirectionType.LEFT) ||
direction == Gtk.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
return;
}
let from = this._defaultResult ? this._defaultResult.actor : null;
this.actor.navigate_focus(from, direction, false);
}
});
const ProviderIcon = new Lang.Class({
Name: 'ProviderIcon',
Extends: St.Button,
PROVIDER_ICON_SIZE: 48,
_init: function(provider) {
this.provider = provider;
this.parent({ style_class: 'search-provider-icon',
reactive: true,
can_focus: true,
accessible_name: provider.appInfo.get_name(),
track_hover: true });
this._content = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this.set_child(this._content);
let rtl = (this.get_text_direction() == Clutter.TextDirection.RTL);
this.moreIcon = new St.Widget({ style_class: 'search-provider-icon-more',
visible: false,
x_align: rtl ? Clutter.ActorAlign.START : Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.END,
x_expand: true,
y_expand: true });
let icon = new St.Icon({ icon_size: this.PROVIDER_ICON_SIZE,
gicon: provider.appInfo.get_icon() });
this._content.add_actor(icon);
this._content.add_actor(this.moreIcon);
}
});

View File

@ -102,19 +102,12 @@ const _modes = {
} }
}; };
function _getModes(modesLoadedCallback) { function _loadMode(file, info) {
FileUtils.collectFromDatadirsAsync('modes',
{ processFile: _loadMode,
loadedCallback: modesLoadedCallback,
data: _modes });
}
function _loadMode(file, info, loadedData) {
let name = info.get_name(); let name = info.get_name();
let suffix = name.indexOf('.json'); let suffix = name.indexOf('.json');
let modeName = suffix == -1 ? name : name.slice(name, suffix); let modeName = suffix == -1 ? name : name.slice(name, suffix);
if (loadedData.hasOwnProperty(modeName)) if (_modes.hasOwnProperty(modeName))
return; return;
let fileContent, success, tag, newMode; let fileContent, success, tag, newMode;
@ -125,18 +118,23 @@ function _loadMode(file, info, loadedData) {
return; return;
} }
loadedData[modeName] = {}; _modes[modeName] = {};
let propBlacklist = ['unlockDialog']; let propBlacklist = ['unlockDialog'];
for (let prop in loadedData[DEFAULT_MODE]) { for (let prop in loadedData[DEFAULT_MODE]) {
if (newMode[prop] !== undefined && if (newMode[prop] !== undefined &&
propBlacklist.indexOf(prop) == -1) propBlacklist.indexOf(prop) == -1)
loadedData[modeName][prop]= newMode[prop]; loadedData[modeName][prop] = newMode[prop];
} }
loadedData[modeName]['isPrimary'] = true; _modes[modeName]['isPrimary'] = true;
}
function _getModes() {
FileUtils.collectFromDatadirs('modes', false, _loadMode);
} }
function listModes() { function listModes() {
_getModes(function(modes) { let modes = _getModes();
modes.forEach(function() {
let names = Object.getOwnPropertyNames(modes); let names = Object.getOwnPropertyNames(modes);
for (let i = 0; i < names.length; i++) for (let i = 0; i < names.length; i++)
if (_modes[names[i]].isPrimary) if (_modes[names[i]].isPrimary)
@ -149,17 +147,12 @@ function listModes() {
const SessionMode = new Lang.Class({ const SessionMode = new Lang.Class({
Name: 'SessionMode', Name: 'SessionMode',
init: function() { _init: function() {
_getModes(Lang.bind(this, function(modes) { let isPrimary = (_modes[global.session_mode] &&
this._modes = modes; _modes[global.session_mode].isPrimary);
let primary = modes[global.session_mode] && let mode = isPrimary ? global.session_mode : 'user';
modes[global.session_mode].isPrimary; this._modeStack = [mode];
let mode = primary ? global.session_mode : 'user'; this._sync();
this._modeStack = [mode];
this._sync();
this.emit('sessions-loaded');
}));
}, },
pushMode: function(mode) { pushMode: function(mode) {
@ -186,13 +179,13 @@ const SessionMode = new Lang.Class({
}, },
_sync: function() { _sync: function() {
let params = this._modes[this.currentMode]; let params = _modes[this.currentMode];
let defaults; let defaults;
if (params.parentMode) if (params.parentMode)
defaults = Params.parse(this._modes[params.parentMode], defaults = Params.parse(_modes[params.parentMode],
this._modes[DEFAULT_MODE]); _modes[DEFAULT_MODE]);
else else
defaults = this._modes[DEFAULT_MODE]; defaults = _modes[DEFAULT_MODE];
params = Params.parse(params, defaults); params = Params.parse(params, defaults);
// A simplified version of Lang.copyProperties, handles // A simplified version of Lang.copyProperties, handles

View File

@ -15,59 +15,63 @@ const Main = imports.ui.main;
const Screenshot = imports.ui.screenshot; const Screenshot = imports.ui.screenshot;
const ViewSelector = imports.ui.viewSelector; const ViewSelector = imports.ui.viewSelector;
const GnomeShellIface = <interface name="org.gnome.Shell"> const GnomeShellIface = '<node> \
<method name="Eval"> <interface name="org.gnome.Shell"> \
<arg type="s" direction="in" name="script" /> <method name="Eval"> \
<arg type="b" direction="out" name="success" /> <arg type="s" direction="in" name="script" /> \
<arg type="s" direction="out" name="result" /> <arg type="b" direction="out" name="success" /> \
</method> <arg type="s" direction="out" name="result" /> \
<method name="FocusSearch"/> </method> \
<method name="ShowOSD"> <method name="FocusSearch"/> \
<arg type="a{sv}" direction="in" name="params"/> <method name="ShowOSD"> \
</method> <arg type="a{sv}" direction="in" name="params"/> \
<method name="FocusApp"> </method> \
<arg type="s" direction="in" name="id"/> <method name="FocusApp"> \
</method> <arg type="s" direction="in" name="id"/> \
<method name="ShowApplications" /> </method> \
<method name="GrabAccelerator"> <method name="ShowApplications" /> \
<arg type="s" direction="in" name="accelerator"/> <method name="GrabAccelerator"> \
<arg type="u" direction="in" name="flags"/> <arg type="s" direction="in" name="accelerator"/> \
<arg type="u" direction="out" name="action"/> <arg type="u" direction="in" name="flags"/> \
</method> <arg type="u" direction="out" name="action"/> \
<method name="GrabAccelerators"> </method> \
<arg type="a(su)" direction="in" name="accelerators"/> <method name="GrabAccelerators"> \
<arg type="au" direction="out" name="actions"/> <arg type="a(su)" direction="in" name="accelerators"/> \
</method> <arg type="au" direction="out" name="actions"/> \
<method name="UngrabAccelerator"> </method> \
<arg type="u" direction="in" name="action"/> <method name="UngrabAccelerator"> \
<arg type="b" direction="out" name="success"/> <arg type="u" direction="in" name="action"/> \
</method> <arg type="b" direction="out" name="success"/> \
<signal name="AcceleratorActivated"> </method> \
<arg name="action" type="u" /> <signal name="AcceleratorActivated"> \
<arg name="deviceid" type="u" /> <arg name="action" type="u" /> \
<arg name="timestamp" type="u" /> <arg name="deviceid" type="u" /> \
</signal> <arg name="timestamp" type="u" /> \
<property name="Mode" type="s" access="read" /> </signal> \
<property name="OverviewActive" type="b" access="readwrite" /> <property name="Mode" type="s" access="read" /> \
<property name="ShellVersion" type="s" access="read" /> <property name="OverviewActive" type="b" access="readwrite" /> \
</interface>; <property name="ShellVersion" type="s" access="read" /> \
</interface> \
</node>';
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver"> const ScreenSaverIface = '<node> \
<method name="Lock"> <interface name="org.gnome.ScreenSaver"> \
</method> <method name="Lock"> \
<method name="GetActive"> </method> \
<arg name="active" direction="out" type="b" /> <method name="GetActive"> \
</method> <arg name="active" direction="out" type="b" /> \
<method name="SetActive"> </method> \
<arg name="value" direction="in" type="b" /> <method name="SetActive"> \
</method> <arg name="value" direction="in" type="b" /> \
<method name="GetActiveTime"> </method> \
<arg name="value" direction="out" type="u" /> <method name="GetActiveTime"> \
</method> <arg name="value" direction="out" type="u" /> \
<signal name="ActiveChanged"> </method> \
<arg name="new_value" type="b" /> <signal name="ActiveChanged"> \
</signal> <arg name="new_value" type="b" /> \
</interface>; </signal> \
</interface> \
</node>';
const GnomeShell = new Lang.Class({ const GnomeShell = new Lang.Class({
Name: 'GnomeShellDBus', Name: 'GnomeShellDBus',
@ -115,7 +119,7 @@ const GnomeShell = new Lang.Class({
returnValue = ''; returnValue = '';
success = true; success = true;
} catch (e) { } catch (e) {
returnValue = JSON.stringify(e); returnValue = '' + e;
success = false; success = false;
} }
return [success, returnValue]; return [success, returnValue];
@ -246,41 +250,43 @@ const GnomeShell = new Lang.Class({
ShellVersion: Config.PACKAGE_VERSION ShellVersion: Config.PACKAGE_VERSION
}); });
const GnomeShellExtensionsIface = <interface name="org.gnome.Shell.Extensions"> const GnomeShellExtensionsIface = '<node> \
<method name="ListExtensions"> <interface name="org.gnome.Shell.Extensions"> \
<arg type="a{sa{sv}}" direction="out" name="extensions" /> <method name="ListExtensions"> \
</method> <arg type="a{sa{sv}}" direction="out" name="extensions" /> \
<method name="GetExtensionInfo"> </method> \
<arg type="s" direction="in" name="extension" /> <method name="GetExtensionInfo"> \
<arg type="a{sv}" direction="out" name="info" /> <arg type="s" direction="in" name="extension" /> \
</method> <arg type="a{sv}" direction="out" name="info" /> \
<method name="GetExtensionErrors"> </method> \
<arg type="s" direction="in" name="extension" /> <method name="GetExtensionErrors"> \
<arg type="as" direction="out" name="errors" /> <arg type="s" direction="in" name="extension" /> \
</method> <arg type="as" direction="out" name="errors" /> \
<signal name="ExtensionStatusChanged"> </method> \
<arg type="s" name="uuid"/> <signal name="ExtensionStatusChanged"> \
<arg type="i" name="state"/> <arg type="s" name="uuid"/> \
<arg type="s" name="error"/> <arg type="i" name="state"/> \
</signal> <arg type="s" name="error"/> \
<method name="InstallRemoteExtension"> </signal> \
<arg type="s" direction="in" name="uuid"/> <method name="InstallRemoteExtension"> \
<arg type="s" direction="out" name="result"/> <arg type="s" direction="in" name="uuid"/> \
</method> <arg type="s" direction="out" name="result"/> \
<method name="UninstallExtension"> </method> \
<arg type="s" direction="in" name="uuid"/> <method name="UninstallExtension"> \
<arg type="b" direction="out" name="success"/> <arg type="s" direction="in" name="uuid"/> \
</method> <arg type="b" direction="out" name="success"/> \
<method name="LaunchExtensionPrefs"> </method> \
<arg type="s" direction="in" name="uuid"/> <method name="LaunchExtensionPrefs"> \
</method> <arg type="s" direction="in" name="uuid"/> \
<method name="ReloadExtension"> </method> \
<arg type="s" direction="in" name="uuid"/> <method name="ReloadExtension"> \
</method> <arg type="s" direction="in" name="uuid"/> \
<method name="CheckForUpdates"> </method> \
</method> <method name="CheckForUpdates"> \
<property name="ShellVersion" type="s" access="read" /> </method> \
</interface>; <property name="ShellVersion" type="s" access="read" /> \
</interface> \
</node>';
const GnomeShellExtensions = new Lang.Class({ const GnomeShellExtensions = new Lang.Class({
Name: 'GnomeShellExtensionsDBus', Name: 'GnomeShellExtensionsDBus',

View File

@ -521,36 +521,38 @@ const ShellProcessesDialog = new Lang.Class({
}); });
Signals.addSignalMethods(ShellProcessesDialog.prototype); Signals.addSignalMethods(ShellProcessesDialog.prototype);
const GnomeShellMountOpIface = <interface name="org.Gtk.MountOperationHandler"> const GnomeShellMountOpIface = '<node> \
<method name="AskPassword"> <interface name="org.Gtk.MountOperationHandler"> \
<arg type="s" direction="in" name="object_id"/> <method name="AskPassword"> \
<arg type="s" direction="in" name="message"/> <arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="icon_name"/> <arg type="s" direction="in" name="message"/> \
<arg type="s" direction="in" name="default_user"/> <arg type="s" direction="in" name="icon_name"/> \
<arg type="s" direction="in" name="default_domain"/> <arg type="s" direction="in" name="default_user"/> \
<arg type="u" direction="in" name="flags"/> <arg type="s" direction="in" name="default_domain"/> \
<arg type="u" direction="out" name="response"/> <arg type="u" direction="in" name="flags"/> \
<arg type="a{sv}" direction="out" name="response_details"/> <arg type="u" direction="out" name="response"/> \
</method> <arg type="a{sv}" direction="out" name="response_details"/> \
<method name="AskQuestion"> </method> \
<arg type="s" direction="in" name="object_id"/> <method name="AskQuestion"> \
<arg type="s" direction="in" name="message"/> <arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="icon_name"/> <arg type="s" direction="in" name="message"/> \
<arg type="as" direction="in" name="choices"/> <arg type="s" direction="in" name="icon_name"/> \
<arg type="u" direction="out" name="response"/> <arg type="as" direction="in" name="choices"/> \
<arg type="a{sv}" direction="out" name="response_details"/> <arg type="u" direction="out" name="response"/> \
</method> <arg type="a{sv}" direction="out" name="response_details"/> \
<method name="ShowProcesses"> </method> \
<arg type="s" direction="in" name="object_id"/> <method name="ShowProcesses"> \
<arg type="s" direction="in" name="message"/> <arg type="s" direction="in" name="object_id"/> \
<arg type="s" direction="in" name="icon_name"/> <arg type="s" direction="in" name="message"/> \
<arg type="ai" direction="in" name="application_pids"/> <arg type="s" direction="in" name="icon_name"/> \
<arg type="as" direction="in" name="choices"/> <arg type="ai" direction="in" name="application_pids"/> \
<arg type="u" direction="out" name="response"/> <arg type="as" direction="in" name="choices"/> \
<arg type="a{sv}" direction="out" name="response_details"/> <arg type="u" direction="out" name="response"/> \
</method> <arg type="a{sv}" direction="out" name="response_details"/> \
<method name="Close"/> </method> \
</interface>; <method name="Close"/> \
</interface> \
</node>';
const ShellMountOperationType = { const ShellMountOperationType = {
NONE: 0, NONE: 0,

View File

@ -105,8 +105,8 @@ const AuthNotification = new Lang.Class({
this._devicePath = device_path; this._devicePath = device_path;
this.addBody(_("Device %s wants to pair with this computer").format(long_name)); this.addBody(_("Device %s wants to pair with this computer").format(long_name));
this.addButton('allow', _("Allow")); this.addAction('allow', _("Allow"));
this.addButton('deny', _("Deny")); this.addAction('deny', _("Deny"));
this.connect('action-invoked', Lang.bind(this, function(self, action) { this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'allow') if (action == 'allow')
@ -133,9 +133,9 @@ const AuthServiceNotification = new Lang.Class({
this._devicePath = device_path; this._devicePath = device_path;
this.addBody(_("Device %s wants access to the service '%s'").format(long_name, uuid)); this.addBody(_("Device %s wants access to the service '%s'").format(long_name, uuid));
this.addButton('always-grant', _("Always grant access")); this.addAction('always-grant', _("Always grant access"));
this.addButton('grant', _("Grant this time only")); this.addAction('grant', _("Grant this time only"));
this.addButton('reject', _("Reject")); this.addAction('reject', _("Reject"));
this.connect('action-invoked', Lang.bind(this, function(self, action) { this.connect('action-invoked', Lang.bind(this, function(self, action) {
switch (action) { switch (action) {
@ -172,8 +172,8 @@ const ConfirmNotification = new Lang.Class({
this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin)); this.addBody(_("Please confirm whether the Passkey '%06d' matches the one on the device.").format(pin));
/* Translators: this is the verb, not the noun */ /* Translators: this is the verb, not the noun */
this.addButton('matches', _("Matches")); this.addAction('matches', _("Matches"));
this.addButton('does-not-match', _("Does not match")); this.addAction('does-not-match', _("Does not match"));
this.connect('action-invoked', Lang.bind(this, function(self, action) { this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'matches') if (action == 'matches')
@ -207,47 +207,48 @@ const PinNotification = new Lang.Class({
let key = event.get_key_symbol(); let key = event.get_key_symbol();
if (key == Clutter.KEY_Return) { if (key == Clutter.KEY_Return) {
if (this._canActivateOkButton()) if (this._canActivateOkButton())
this.emit('action-invoked', 'ok'); this._ok();
return true; return true;
} else if (key == Clutter.KEY_Escape) { } else if (key == Clutter.KEY_Escape) {
this.emit('action-invoked', 'cancel'); this._cancel();
return true; return true;
} }
return false; return false;
})); }));
this.addActor(this._entry); this.addActor(this._entry);
this.addButton('ok', _("OK")); let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok));
this.addButton('cancel', _("Cancel")); this.addAction(_("Cancel"), Lang.bind(this, this._cancel));
this.setButtonSensitive('ok', this._canActivateOkButton()); okButton.reactive = this._canActivateOkButton();
this._entry.clutter_text.connect('text-changed', Lang.bind(this, this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
function() { okButton.reactive = this._canActivateOkButton();
this.setButtonSensitive('ok', this._canActivateOkButton());
}));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
if (action == 'ok') {
if (this._numeric) {
let num = parseInt(this._entry.text);
if (isNaN(num)) {
// user reply was empty, or was invalid
// cancel the operation
num = -1;
}
this._applet.agent_reply_passkey(this._devicePath, num);
} else
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
} else {
if (this._numeric)
this._applet.agent_reply_passkey(this._devicePath, -1);
else
this._applet.agent_reply_pincode(this._devicePath, null);
}
this.destroy();
})); }));
}, },
_ok: function() {
if (this._numeric) {
let num = parseInt(this._entry.text, 10);
if (isNaN(num)) {
// user reply was empty, or was invalid
// cancel the operation
num = -1;
}
this._applet.agent_reply_passkey(this._devicePath, num);
} else {
this._applet.agent_reply_pincode(this._devicePath, this._entry.text);
}
this.destroy();
},
_cancel: function() {
if (this._numeric)
this._applet.agent_reply_passkey(this._devicePath, -1);
else
this._applet.agent_reply_pincode(this._devicePath, null);
this.destroy();
},
_canActivateOkButton: function() { _canActivateOkButton: function() {
// PINs have a fixed length of 6 // PINs have a fixed length of 6
if (this._numeric) if (this._numeric)

View File

@ -11,9 +11,11 @@ const Slider = imports.ui.slider;
const BUS_NAME = 'org.gnome.SettingsDaemon.Power'; const BUS_NAME = 'org.gnome.SettingsDaemon.Power';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power'; const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power';
const BrightnessInterface = <interface name="org.gnome.SettingsDaemon.Power.Screen"> const BrightnessInterface = '<node> \
<property name='Brightness' type='i' access='readwrite'/> <interface name="org.gnome.SettingsDaemon.Power.Screen"> \
</interface>; <property name="Brightness" type="i" access="readwrite"/> \
</interface> \
</node>';
const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface); const BrightnessProxy = Gio.DBusProxy.makeProxyWrapper(BrightnessInterface);

View File

@ -41,11 +41,13 @@ const MAX_INPUT_SOURCE_ACTIVATION_TIME = 4000; // ms
const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard'; const BUS_NAME = 'org.gnome.SettingsDaemon.Keyboard';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard'; const OBJECT_PATH = '/org/gnome/SettingsDaemon/Keyboard';
const KeyboardManagerInterface = <interface name="org.gnome.SettingsDaemon.Keyboard"> const KeyboardManagerInterface = '<node> \
<method name="SetInputSource"> <interface name="org.gnome.SettingsDaemon.Keyboard"> \
<arg type="u" direction="in" /> <method name="SetInputSource"> \
</method> <arg type="u" direction="in" /> \
</interface>; </method> \
</interface> \
</node>';
const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface); const KeyboardManagerProxy = Gio.DBusProxy.makeProxyWrapper(KeyboardManagerInterface);

View File

@ -549,33 +549,30 @@ const NMWirelessDialogItem = new Lang.Class({
this._network = network; this._network = network;
this._ap = network.accessPoints[0]; this._ap = network.accessPoints[0];
this.actor = new St.Button({ style_class: 'nm-dialog-item', this.actor = new St.BoxLayout({ style_class: 'nm-dialog-item',
can_focus: true, can_focus: true,
x_fill: true }); reactive: true });
this.actor.connect('key-focus-in', Lang.bind(this, function() { this.actor.connect('key-focus-in', Lang.bind(this, function() {
this.emit('selected'); this.emit('selected');
})); }));
this.actor.connect('clicked', Lang.bind(this, function() { let action = new Clutter.ClickAction();
action.connect('clicked', Lang.bind(this, function() {
this.actor.grab_key_focus(); this.actor.grab_key_focus();
})); }));
this.actor.add_action(action);
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._content = new St.BoxLayout({ style_class: 'nm-dialog-item-box' });
this.actor.set_child(this._content);
let title = ssidToLabel(this._ap.get_ssid()); let title = ssidToLabel(this._ap.get_ssid());
this._label = new St.Label({ text: title }); this._label = new St.Label({ text: title });
this.actor.label_actor = this._label; this.actor.label_actor = this._label;
this._content.add(this._label, { x_align: St.Align.START }); this.actor.add(this._label, { x_align: St.Align.START });
this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon', this._selectedIcon = new St.Icon({ style_class: 'nm-dialog-icon',
icon_name: 'object-select-symbolic' }); icon_name: 'object-select-symbolic' });
this._content.add(this._selectedIcon); this.actor.add(this._selectedIcon);
this._icons = new St.BoxLayout({ style_class: 'nm-dialog-icons' }); this._icons = new St.BoxLayout({ style_class: 'nm-dialog-icons' });
this._content.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END }); this.actor.add(this._icons, { expand: true, x_fill: false, x_align: St.Align.END });
this._secureIcon = new St.Icon({ style_class: 'nm-dialog-icon' }); this._secureIcon = new St.Icon({ style_class: 'nm-dialog-icon' });
if (this._ap._secType != NMAccessPointSecurity.NONE) if (this._ap._secType != NMAccessPointSecurity.NONE)
@ -606,16 +603,6 @@ const NMWirelessDialogItem = new Lang.Class({
return 'network-workgroup-symbolic'; return 'network-workgroup-symbolic';
else else
return 'network-wireless-signal-' + signalToIcon(this._ap.strength) + '-symbolic'; return 'network-wireless-signal-' + signalToIcon(this._ap.strength) + '-symbolic';
},
_onKeyPressEvent: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return
|| symbol == Clutter.KEY_KP_Enter) {
this.emit('connect');
return true;
}
return false;
} }
}); });
Signals.addSignalMethods(NMWirelessDialogItem.prototype); Signals.addSignalMethods(NMWirelessDialogItem.prototype);
@ -968,13 +955,13 @@ const NMWirelessDialog = new Lang.Class({
_selectNetwork: function(network) { _selectNetwork: function(network) {
if (this._selectedNetwork) if (this._selectedNetwork)
this._selectedNetwork.item.actor.checked = false; this._selectedNetwork.item.actor.remove_style_pseudo_class('selected');
this._selectedNetwork = network; this._selectedNetwork = network;
this._updateSensitivity(); this._updateSensitivity();
if (this._selectedNetwork) if (this._selectedNetwork)
this._selectedNetwork.item.actor.checked = true; this._selectedNetwork.item.actor.add_style_pseudo_class('selected');
}, },
_createNetworkItem: function(network) { _createNetworkItem: function(network) {
@ -984,9 +971,6 @@ const NMWirelessDialog = new Lang.Class({
Util.ensureActorVisibleInScrollView(this._scrollView, network.item.actor); Util.ensureActorVisibleInScrollView(this._scrollView, network.item.actor);
this._selectNetwork(network); this._selectNetwork(network);
})); }));
network.item.connect('connect', Lang.bind(this, function() {
this._connect();
}));
}, },
}); });

View File

@ -8,20 +8,22 @@ const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const BUS_NAME = 'org.gnome.SettingsDaemon.Power'; const BUS_NAME = 'org.freedesktop.UPower';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Power'; const OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice';
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power"> const DisplayDeviceInterface = '<node> \
<method name="GetDevices"> <interface name="org.freedesktop.UPower.Device"> \
<arg type="a(susdut)" direction="out" /> <property name="Type" type="u" access="read"/> \
</method> <property name="State" type="u" access="read"/> \
<method name="GetPrimaryDevice"> <property name="Percentage" type="d" access="read"/> \
<arg type="(susdut)" direction="out" /> <property name="TimeToEmpty" type="x" access="read"/> \
</method> <property name="TimeToFull" type="x" access="read"/> \
<property name="Icon" type="s" access="read" /> <property name="IsPresent" type="b" access="read"/> \
</interface>; <property name="IconName" type="s" access="read"/> \
</interface> \
</node>';
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface); const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(DisplayDeviceInterface);
const Indicator = new Lang.Class({ const Indicator = new Lang.Class({
Name: 'PowerIndicator', Name: 'PowerIndicator',
@ -32,7 +34,7 @@ const Indicator = new Lang.Class({
this._indicator = this._addIndicator(); this._indicator = this._addIndicator();
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH, this._proxy = new PowerManagerProxy(Gio.DBus.system, BUS_NAME, OBJECT_PATH,
Lang.bind(this, function(proxy, error) { Lang.bind(this, function(proxy, error) {
if (error) { if (error) {
log(error.message); log(error.message);
@ -43,7 +45,7 @@ const Indicator = new Lang.Class({
this._sync(); this._sync();
})); }));
this._item = new PopupMenu.PopupSubMenuMenuItem(_("Battery"), true); this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop'); this._item.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this.menu.addMenuItem(this._item); this.menu.addMenuItem(this._item);
@ -56,11 +58,18 @@ const Indicator = new Lang.Class({
this.menu.setSensitive(sensitive); this.menu.setSensitive(sensitive);
}, },
_statusForDevice: function(device) { _getStatus: function() {
let [device_id, device_type, icon, percentage, state, seconds] = device; let seconds = 0;
if (state == UPower.DeviceState.FULLY_CHARGED) if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED)
return _("Fully Charged"); return _("Fully Charged");
else if (this._proxy.State == UPower.DeviceState.CHARGING)
seconds = this._proxy.TimeToFull;
else if (this._proxy.State == UPower.DeviceState.DISCHARGING)
seconds = this._proxy.TimeToEmpty;
// state is one of PENDING_CHARGING, PENDING_DISCHARGING
else
return _("Estimating…");
let time = Math.round(seconds / 60); let time = Math.round(seconds / 60);
if (time == 0) { if (time == 0) {
@ -72,44 +81,43 @@ const Indicator = new Lang.Class({
let minutes = time % 60; let minutes = time % 60;
let hours = Math.floor(time / 60); let hours = Math.floor(time / 60);
if (state == UPower.DeviceState.DISCHARGING) { if (this._proxy.State == UPower.DeviceState.DISCHARGING) {
// Translators: this is <hours>:<minutes> Remaining (<percentage>) // Translators: this is <hours>:<minutes> Remaining (<percentage>)
return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, percentage); return _("%d\u2236%02d Remaining (%d%%)").format(hours, minutes, this._proxy.Percentage);
} }
if (state == UPower.DeviceState.CHARGING) { if (this._proxy.State == UPower.DeviceState.CHARGING) {
// Translators: this is <hours>:<minutes> Until Full (<percentage>) // Translators: this is <hours>:<minutes> Until Full (<percentage>)
return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, percentage); return _("%d\u2236%02d Until Full (%d%%)").format(hours, minutes, this._proxy.Percentage);
} }
// state is one of PENDING_CHARGING, PENDING_DISCHARGING return null;
return _("Estimating…");
}, },
_sync: function() { _sync: function() {
function isBattery(result) { // Do we have batteries or a UPS?
if (!result) let visible = this._proxy.IsPresent;
return false; if (visible) {
this._item.actor.show();
let [device] = result; } else {
let [, deviceType] = device; // If there's no battery, then we use the power icon.
return (deviceType == UPower.DeviceKind.BATTERY); this._item.actor.hide();
this._indicator.icon_name = 'system-shutdown-symbolic';
return;
} }
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) { // The icons
if (isBattery(result)) { let icon = this._proxy.IconName;
let [device] = result; this._indicator.icon_name = icon;
let [,, icon] = device; this._item.icon.icon_name = icon;
let gicon = Gio.icon_new_for_string(icon);
this._indicator.gicon = gicon; // The status label
this._item.icon.gicon = gicon; this._item.status.text = this._getStatus();
this._item.status.text = this._statusForDevice(device);
this._item.actor.show(); // The sub-menu heading
} else { if (this._proxy.Type == UPower.DeviceKind.UPS)
// If there's no battery, then we use the power icon. this._item.label.text = _("UPS");
this._indicator.icon_name = 'system-shutdown-symbolic'; else
this._item.actor.hide(); this._item.label.text = _("Battery");
}
}));
}, },
}); });

View File

@ -9,9 +9,11 @@ const PopupMenu = imports.ui.popupMenu;
const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill'; const BUS_NAME = 'org.gnome.SettingsDaemon.Rfkill';
const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill'; const OBJECT_PATH = '/org/gnome/SettingsDaemon/Rfkill';
const RfkillManagerInterface = <interface name="org.gnome.SettingsDaemon.Rfkill"> const RfkillManagerInterface = '<node> \
<property name="AirplaneMode" type="b" access="readwrite" /> <interface name="org.gnome.SettingsDaemon.Rfkill"> \
</interface>; <property name="AirplaneMode" type="b" access="readwrite" /> \
</interface> \
</node>';
const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface); const RfkillManagerProxy = Gio.DBusProxy.makeProxyWrapper(RfkillManagerInterface);

View File

@ -18,10 +18,12 @@ const PopupMenu = imports.ui.popupMenu;
const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy' const PRIVACY_SCHEMA = 'org.gnome.desktop.privacy'
const DISABLE_USER_SWITCH_KEY = 'disable-user-switching'; const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen'; const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out'; const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const DISABLE_RESTART_KEY = 'disable-restart-buttons';
const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out'; const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out';
const AltSwitcher = new Lang.Class({ const AltSwitcher = new Lang.Class({
@ -91,6 +93,7 @@ const Indicator = new Lang.Class({
this.parent(); this.parent();
this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA }); this._screenSaverSettings = new Gio.Settings({ schema: SCREENSAVER_SCHEMA });
this._loginScreenSettings = new Gio.Settings({ schema: LOGIN_SCREEN_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA }); this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA }); this._privacySettings = new Gio.Settings({ schema: PRIVACY_SCHEMA });
this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' }); this._orientationSettings = new Gio.Settings({ schema: 'org.gnome.settings-daemon.peripherals.touchscreen' });
@ -261,7 +264,10 @@ const Indicator = new Lang.Class({
}, },
_updatePowerOff: function() { _updatePowerOff: function() {
this._powerOffAction.visible = this._haveShutdown && !Main.sessionMode.isLocked; let disabled = Main.sessionMode.isLocked ||
(Main.sessionMode.isGreeter &&
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._powerOffAction.visible = this._haveShutdown && !disabled;
this._updateActionsVisibility(); this._updateActionsVisibility();
}, },
@ -273,7 +279,10 @@ const Indicator = new Lang.Class({
}, },
_updateSuspend: function() { _updateSuspend: function() {
this._suspendAction.visible = this._haveSuspend && !Main.sessionMode.isLocked; let disabled = Main.sessionMode.isLocked ||
(Main.sessionMode.isGreeter &&
this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY));
this._suspendAction.visible = this._haveShutdown && !disabled;
this._updateActionsVisibility(); this._updateActionsVisibility();
}, },

View File

@ -11,29 +11,8 @@ const Signals = imports.signals;
const Tweener = imports.tweener.tweener; const Tweener = imports.tweener.tweener;
// This is a wrapper around imports.tweener.tweener that adds a bit of // This is a wrapper around imports.tweener.tweener that adds a bit of
// Clutter integration and some additional callbacks: // Clutter integration. If the tweening target is a Clutter.Actor, then
// // the tweenings will automatically be removed if the actor is destroyed.
// 1. If the tweening target is a Clutter.Actor, then the tweenings
// will automatically be removed if the actor is destroyed
//
// 2. If target._delegate.onAnimationStart() exists, it will be
// called when the target starts being animated.
//
// 3. If target._delegate.onAnimationComplete() exists, it will be
// called once the target is no longer being animated.
//
// The onAnimationStart() and onAnimationComplete() callbacks differ
// from the tweener onStart and onComplete parameters, in that (1)
// they track whether or not the target has *any* tweens attached to
// it, as opposed to be called for *each* tween, and (2)
// onAnimationComplete() is always called when the object stops being
// animated, regardless of whether it stopped normally or abnormally.
//
// onAnimationComplete() is called at idle time, which means that if a
// tween completes and then another is added before returning to the
// main loop, the complete callback will not be called (until the new
// tween finishes).
// ActionScript Tweener methods that imports.tweener.tweener doesn't // ActionScript Tweener methods that imports.tweener.tweener doesn't
// currently implement: getTweens, getVersion, registerTransition, // currently implement: getTweens, getVersion, registerTransition,
@ -77,7 +56,6 @@ function _wrapTweening(target, tweeningParameters) {
if (!Gtk.Settings.get_default().gtk_enable_animations) if (!Gtk.Settings.get_default().gtk_enable_animations)
tweeningParameters['time'] = 0.000001; tweeningParameters['time'] = 0.000001;
_addHandler(target, tweeningParameters, 'onStart', _tweenStarted);
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted); _addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
} }
@ -85,7 +63,7 @@ function _getTweenState(target) {
// If we were paranoid, we could keep a plist mapping targets to // If we were paranoid, we could keep a plist mapping targets to
// states... but we're not that paranoid. // states... but we're not that paranoid.
if (!target.__ShellTweenerState) if (!target.__ShellTweenerState)
_resetTweenState(target); target.__ShellTweenerState = {};
return target.__ShellTweenerState; return target.__ShellTweenerState;
} }
@ -95,8 +73,6 @@ function _resetTweenState(target) {
if (state) { if (state) {
if (state.destroyedId) if (state.destroyedId)
state.actor.disconnect(state.destroyedId); state.actor.disconnect(state.destroyedId);
if (state.idleCompletedId)
Mainloop.source_remove(state.idleCompletedId);
} }
target.__ShellTweenerState = {}; target.__ShellTweenerState = {};
@ -122,32 +98,9 @@ function _actorDestroyed(target) {
Tweener.removeTweens(target); Tweener.removeTweens(target);
} }
function _tweenStarted(target) {
let state = _getTweenState(target);
let delegate = target._delegate;
if (!state.running && delegate && delegate.onAnimationStart)
delegate.onAnimationStart();
state.running = true;
}
function _tweenCompleted(target) { function _tweenCompleted(target) {
let state = _getTweenState(target); if (!isTweening(target))
if (!state.idleCompletedId)
state.idleCompletedId = Mainloop.idle_add(Lang.bind(null, _idleCompleted, target));
}
function _idleCompleted(target) {
let state = _getTweenState(target);
let delegate = target._delegate;
if (!isTweening(target)) {
_resetTweenState(target); _resetTweenState(target);
if (delegate && delegate.onAnimationComplete)
delegate.onAnimationComplete();
}
return false;
} }
function getTweenCount(scope) { function getTweenCount(scope) {

View File

@ -1,7 +1,8 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
// //
// A widget showing the user avatar and name // A widget showing the user avatar and name
const Clutter = imports.gi.Clutter;
const AccountsService = imports.gi.AccountsService; const AccountsService = imports.gi.AccountsService;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
@ -56,6 +57,83 @@ const Avatar = new Lang.Class({
} }
}); });
const UserWidgetLabel = new Lang.Class({
Name: 'UserWidgetLabel',
Extends: St.Widget,
_init: function(user) {
this.parent({ layout_manager: new Clutter.BinLayout() });
this._user = user;
this._realNameLabel = new St.Label({ style_class: 'user-widget-label',
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this._realNameLabel);
this._userNameLabel = new St.Label({ style_class: 'user-widget-label',
y_align: Clutter.ActorAlign.CENTER });
this.add_child(this._userNameLabel);
this._currentLabel = null;
this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUser));
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUser));
this._updateUser();
},
vfunc_destroy: function() {
if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userChangedId != 0) {
this._user.disconnect(this._userChangedId);
this._userChangedId = 0;
}
},
vfunc_allocate: function(box, flags) {
this.set_allocation(box, flags);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [minRealNameWidth, minRealNameHeight,
natRealNameWidth, natRealNameHeight] = this._realNameLabel.get_preferred_size();
let [minUserNameWidth, minUserNameHeight,
natUserNameWidth, natUserNameHeight] = this._userNameLabel.get_preferred_size();
if (natRealNameWidth <= availWidth)
this._currentLabel = this._realNameLabel;
else
this._currentLabel = this._userNameLabel;
let childBox = new Clutter.ActorBox();
childBox.x1 = 0;
childBox.y1 = 0;
childBox.x2 = availWidth;
childBox.y2 = availHeight;
this._currentLabel.allocate(childBox, flags);
},
vfunc_paint: function() {
this._currentLabel.paint();
},
_updateUser: function() {
if (this._user.is_loaded) {
this._realNameLabel.text = this._user.get_real_name();
this._userNameLabel.text = this._user.get_user_name();
} else {
this._realNameLabel.text = '';
this._userNameLabel.text = '';
}
},
});
const UserWidget = new Lang.Class({ const UserWidget = new Lang.Class({
Name: 'UserWidget', Name: 'UserWidget',
@ -67,22 +145,14 @@ const UserWidget = new Lang.Class({
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._avatar = new Avatar(user); this._avatar = new Avatar(user);
this.actor.add(this._avatar.actor, this.actor.add_child(this._avatar.actor);
{ x_fill: true, y_fill: true });
this._label = new St.Label({ style_class: 'user-widget-label' }); this._label = new UserWidgetLabel(user);
this.actor.add(this._label, this.actor.add_child(this._label);
{ expand: true,
x_fill: true,
y_fill: false,
y_align: St.Align.MIDDLE });
this._userLoadedId = this._user.connect('notify::is-loaded', this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUser));
Lang.bind(this, this._updateUser)); this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUser));
this._userChangedId = this._user.connect('changed', this._updateUser();
Lang.bind(this, this._updateUser));
if (this._user.is_loaded)
this._updateUser();
}, },
_onDestroy: function() { _onDestroy: function() {
@ -98,11 +168,6 @@ const UserWidget = new Lang.Class({
}, },
_updateUser: function() { _updateUser: function() {
if (this._user.is_loaded)
this._label.text = this._user.get_real_name();
else
this._label.text = '';
this._avatar.update(); this._avatar.update();
} }
}); });

View File

@ -14,12 +14,9 @@ const AppDisplay = imports.ui.appDisplay;
const Main = imports.ui.main; const Main = imports.ui.main;
const OverviewControls = imports.ui.overviewControls; const OverviewControls = imports.ui.overviewControls;
const Params = imports.misc.params; const Params = imports.misc.params;
const RemoteSearch = imports.ui.remoteSearch;
const Search = imports.ui.search; const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry; const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Wanda = imports.ui.wanda;
const WorkspacesView = imports.ui.workspacesView; const WorkspacesView = imports.ui.workspacesView;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings'; const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@ -66,8 +63,6 @@ const ViewSelector = new Lang.Class({
this._searchActive = false; this._searchActive = false;
this._searchTimeoutId = 0; this._searchTimeoutId = 0;
this._searchSystem = new Search.SearchSystem();
this._entry = searchEntry; this._entry = searchEntry;
ShellEntry.addContextMenu(this._entry); ShellEntry.addContextMenu(this._entry);
@ -103,24 +98,11 @@ const ViewSelector = new Lang.Class({
this._appsPage = this._addPage(this.appDisplay.actor, this._appsPage = this._addPage(this.appDisplay.actor,
_("Applications"), 'view-grid-symbolic'); _("Applications"), 'view-grid-symbolic');
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem); this._searchResults = new Search.SearchResults();
this._searchPage = this._addPage(this._searchResults.actor, this._searchPage = this._addPage(this._searchResults.actor,
_("Search"), 'edit-find-symbolic', _("Search"), 'edit-find-symbolic',
{ a11yFocus: this._entry }); { a11yFocus: this._entry });
this._searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
// Default search providers
// Wanda comes obviously first
this.addSearchProvider(new Wanda.WandaSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
// Load remote search providers provided by applications
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
// Since the entry isn't inside the results container we install this // Since the entry isn't inside the results container we install this
// dummy widget as the last results container child so that we can // dummy widget as the last results container child so that we can
// include the entry in the keynav tab path // include the entry in the keynav tab path
@ -486,45 +468,10 @@ const ViewSelector = new Lang.Class({
let terms = getTermsForSearchString(this._entry.get_text()); let terms = getTermsForSearchString(this._entry.get_text());
this._searchSystem.updateSearchResults(terms); this._searchResults.setTerms(terms);
this._showPage(this._searchPage); this._showPage(this._searchPage);
}, },
_shouldUseSearchProvider: function(provider) {
// the disable-external GSetting only affects remote providers
if (!provider.isRemoteProvider)
return true;
if (this._searchSettings.get_boolean('disable-external'))
return false;
let appId = provider.appInfo.get_id();
let disable = this._searchSettings.get_strv('disabled');
return disable.indexOf(appId) == -1;
},
_reloadRemoteProviders: function() {
// removeSearchProvider() modifies the provider list we iterate on,
// so make a copy first
let remoteProviders = this._searchSystem.getRemoteProviders().slice(0);
remoteProviders.forEach(Lang.bind(this, this.removeSearchProvider));
RemoteSearch.loadRemoteSearchProviders(Lang.bind(this, this.addSearchProvider));
},
addSearchProvider: function(provider) {
if (!this._shouldUseSearchProvider(provider))
return;
this._searchSystem.registerProvider(provider);
this._searchResults.createProviderDisplay(provider);
},
removeSearchProvider: function(provider) {
this._searchSystem.unregisterProvider(provider);
this._searchResults.destroyProviderDisplay(provider);
},
getActivePage: function() { getActivePage: function() {
if (this._activePage == this._workspacesPage) if (this._activePage == this._workspacesPage)
return ViewPage.WINDOWS; return ViewPage.WINDOWS;

View File

@ -1,160 +0,0 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GdkPixbuf = imports.gi.GdkPixbuf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const St = imports.gi.St;
const IconGrid = imports.ui.iconGrid;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const FISH_NAME = 'wanda';
const FISH_FILENAME = 'wanda.png';
const FISH_SPEED = 300;
const FISH_COMMAND = 'fortune';
// The size of an individual frame in the animation
const FISH_HEIGHT = 22;
const FISH_WIDTH = 36;
const FISH_GROUP = 'Fish Animation';
const MAGIC_FISH_KEY = 'free the fish';
const WandaIcon = new Lang.Class({
Name: 'WandaIcon',
Extends: IconGrid.BaseIcon,
_init : function(fish, label, params) {
this.parent(label, params);
this._fish = fish;
this._imageFile = GLib.build_filenamev([global.datadir, fish + '.png']);
this._imgHeight = FISH_HEIGHT;
this._imgWidth = FISH_WIDTH;
},
createIcon: function(iconSize) {
this._animations = new Panel.Animation(this._imageFile, this._imgWidth, this._imgHeight, FISH_SPEED);
this._animations.play();
return this._animations.actor;
},
_createIconTexture: function(size) {
if (size == this.iconSize)
return;
this.parent(size);
}
});
const WandaIconBin = new Lang.Class({
Name: 'WandaIconBin',
_init: function(fish, label, params) {
this.actor = new St.Bin({ reactive: true,
track_hover: true });
this.icon = new WandaIcon(fish, label, params);
this.actor.child = this.icon.actor;
this.actor.label_actor = this.icon.label;
},
});
const FortuneDialog = new Lang.Class({
Name: 'FortuneDialog',
_init: function(name, command) {
let text;
try {
let [res, stdout, stderr, status] = GLib.spawn_command_line_sync(command);
text = String.fromCharCode.apply(null, stdout);
} catch(e) {
text = _("Sorry, no wisdom for you today:\n%s").format(e.message);
}
this._title = new St.Label({ style_class: 'prompt-dialog-headline',
text: _("%s the Oracle says").format(name) });
this._label = new St.Label({ style_class: 'prompt-dialog-description',
text: text });
this._label.clutter_text.line_wrap = true;
this._box = new St.BoxLayout({ vertical: true,
style_class: 'prompt-dialog' // this is just to force a reasonable width
});
this._box.add(this._title, { align: St.Align.MIDDLE });
this._box.add(this._label, { expand: true });
this._button = new St.Button({ button_mask: St.ButtonMask.ONE,
style_class: 'modal-dialog',
reactive: true });
this._button.connect('clicked', Lang.bind(this, this.destroy));
this._button.child = this._box;
this._bin = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._bin.add_constraint(new Layout.MonitorConstraint({ primary: true }));
this._bin.add_actor(this._button);
Main.layoutManager.addChrome(this._bin);
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, Lang.bind(this, this.destroy));
},
destroy: function() {
this._bin.destroy();
}
});
function capitalize(str) {
return str[0].toUpperCase() + str.substring(1, str.length);
}
const WandaSearchProvider = new Lang.Class({
Name: 'WandaSearchProvider',
_init: function() {
this.id = 'wanda';
},
getResultMetas: function(fish, callback) {
callback([{ 'id': fish[0], // there may be many fish in the sea, but
// only one which speaks the truth!
'name': capitalize(fish[0]),
'createIcon': function(iconSize) {
return new St.Icon({ gicon: Gio.icon_new_for_string('face-smile'),
icon_size: iconSize });
}
}]);
},
filterResults: function(results) {
return results;
},
getInitialResultSet: function(terms) {
if (terms.join(' ') == MAGIC_FISH_KEY) {
this.searchSystem.setResults(this, [ FISH_NAME ]);
} else {
this.searchSystem.setResults(this, []);
}
},
getSubsearchResultSet: function(previousResults, terms) {
this.getInitialResultSet(terms);
},
activateResult: function(fish) {
if (this._dialog)
this._dialog.destroy();
this._dialog = new FortuneDialog(capitalize(fish), FISH_COMMAND);
},
createResultObject: function (resultMeta, terms) {
return new WandaIconBin(resultMeta.id, resultMeta.name);
}
});

View File

@ -39,6 +39,9 @@ const WindowAttentionHandler = new Lang.Class({
let [title, banner] = this._getTitleAndBanner(app, window); let [title, banner] = this._getTitleAndBanner(app, window);
let notification = new MessageTray.Notification(source, title, banner); let notification = new MessageTray.Notification(source, title, banner);
notification.connect('clicked', function() {
source.open();
});
notification.setForFeedback(true); notification.setForFeedback(true);
source.notify(notification); source.notify(notification);
@ -79,7 +82,7 @@ const Source = new Lang.Class({
return this._app.create_icon_texture(size); return this._app.create_icon_texture(size);
}, },
open : function(notification) { open: function() {
Main.activateWindow(this._window); Main.activateWindow(this._window);
this.destroy(); this.destroy();
} }

View File

@ -10,19 +10,14 @@ const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const FOCUS_ANIMATION_TIME = 0.15;
const WINDOW_DND_SIZE = 256; const WINDOW_DND_SIZE = 256;
const WINDOW_CLONE_MAXIMUM_SCALE = 0.7; const WINDOW_CLONE_MAXIMUM_SCALE = 0.7;
const LIGHTBOX_FADE_TIME = 0.1;
const CLOSE_BUTTON_FADE_TIME = 0.1; const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100; const DRAGGING_WINDOW_OPACITY = 100;
@ -892,6 +887,19 @@ function padArea(area, padding) {
}; };
} }
function rectEqual(one, two) {
if (one == two)
return true;
if (!one || !two)
return false;
return (one.x == two.x &&
one.y == two.y &&
one.width == two.width &&
one.height == two.height);
}
/** /**
* @metaWorkspace: a #Meta.Workspace, or null * @metaWorkspace: a #Meta.Workspace, or null
*/ */
@ -967,11 +975,17 @@ const Workspace = new Lang.Class({
}, },
setFullGeometry: function(geom) { setFullGeometry: function(geom) {
if (rectEqual(this._fullGeometry, geom))
return;
this._fullGeometry = geom; this._fullGeometry = geom;
this._recalculateWindowPositions(WindowPositionFlags.NONE); this._recalculateWindowPositions(WindowPositionFlags.NONE);
}, },
setActualGeometry: function(geom) { setActualGeometry: function(geom) {
if (rectEqual(this._actualGeometry, geom))
return;
this._actualGeometry = geom; this._actualGeometry = geom;
if (this._actualGeometryLater) if (this._actualGeometryLater)
@ -1194,6 +1208,7 @@ const Workspace = new Lang.Class({
} }
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE); this._recalculateWindowPositions(WindowPositionFlags.ANIMATE);
this._repositionWindowsId = 0;
return false; return false;
}, },
@ -1449,17 +1464,17 @@ const Workspace = new Lang.Class({
clone.connect('selected', clone.connect('selected',
Lang.bind(this, this._onCloneSelected)); Lang.bind(this, this._onCloneSelected));
clone.connect('drag-begin', clone.connect('drag-begin',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.beginWindowDrag(); Main.overview.beginWindowDrag(clone);
overlay.hide(); overlay.hide();
})); }));
clone.connect('drag-cancelled', clone.connect('drag-cancelled',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(); Main.overview.cancelledWindowDrag(clone);
})); }));
clone.connect('drag-end', clone.connect('drag-end',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.endWindowDrag(); Main.overview.endWindowDrag(clone);
overlay.show(); overlay.show();
})); }));
clone.connect('size-changed', clone.connect('size-changed',
@ -1621,9 +1636,7 @@ const Workspace = new Lang.Class({
metaWindow.move_to_monitor(this.monitorIndex); metaWindow.move_to_monitor(this.monitorIndex);
let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index(); let index = this.metaWorkspace ? this.metaWorkspace.index() : global.screen.get_active_workspace_index();
metaWindow.change_workspace_by_index(index, metaWindow.change_workspace_by_index(index, false);
false, // don't create workspace
time);
return true; return true;
} else if (source.shellWorkspaceLaunch) { } else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1, source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,

View File

@ -438,16 +438,16 @@ const WorkspaceThumbnail = new Lang.Class({
this.activate(time); this.activate(time);
})); }));
clone.connect('drag-begin', clone.connect('drag-begin',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.beginWindowDrag(); Main.overview.beginWindowDrag(clone);
})); }));
clone.connect('drag-cancelled', clone.connect('drag-cancelled',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.cancelledWindowDrag(); Main.overview.cancelledWindowDrag(clone);
})); }));
clone.connect('drag-end', clone.connect('drag-end',
Lang.bind(this, function(clone) { Lang.bind(this, function() {
Main.overview.endWindowDrag(); Main.overview.endWindowDrag(clone);
})); }));
this._contents.add_actor(clone.actor); this._contents.add_actor(clone.actor);
@ -507,9 +507,7 @@ const WorkspaceThumbnail = new Lang.Class({
if (metaWindow.get_monitor() != this.monitorIndex) if (metaWindow.get_monitor() != this.monitorIndex)
metaWindow.move_to_monitor(this.monitorIndex); metaWindow.move_to_monitor(this.monitorIndex);
metaWindow.change_workspace_by_index(this.metaWorkspace.index(), metaWindow.change_workspace_by_index(this.metaWorkspace.index(), false);
false, // don't create workspace
time);
return true; return true;
} else if (source.shellWorkspaceLaunch) { } else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1, source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
@ -739,14 +737,12 @@ const ThumbnailsBox = new Lang.Class({
// ... move them down one. // ... move them down one.
windows.forEach(function(win) { windows.forEach(function(win) {
win.meta_window.change_workspace_by_index(win.get_workspace() + 1, win.meta_window.change_workspace_by_index(win.get_workspace() + 1, true);
true, time);
}); });
if (isWindow) if (isWindow)
// ... and bam, a workspace, good as new. // ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex, source.metaWindow.change_workspace_by_index(newWorkspaceIndex, true);
true, time);
else if (source.shellWorkspaceLaunch) { else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex, source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time }); timestamp: time });

View File

@ -23,75 +23,92 @@ const MAX_WORKSPACES = 16;
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides'; const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
function rectEqual(one, two) { const WorkspacesViewBase = new Lang.Class({
if (one == two) Name: 'WorkspacesViewBase',
return true;
if (!one || !two) _init: function(monitorIndex) {
return false;
return (one.x == two.x &&
one.y == two.y &&
one.width == two.width &&
one.height == two.height);
}
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
_init: function(workspaces) {
this.actor = new St.Widget({ style_class: 'workspaces-view', this.actor = new St.Widget({ style_class: 'workspaces-view',
reactive: true }); reactive: true });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
// The actor itself isn't a drop target, so we don't want to pick on its area // The actor itself isn't a drop target, so we don't want to pick on its area
this.actor.set_size(0, 0); this.actor.set_size(0, 0);
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this._monitorIndex = monitorIndex;
this.actor.connect('style-changed', Lang.bind(this,
function() {
let node = this.actor.get_theme_node();
this._spacing = node.get_length('spacing');
this._updateWorkspaceActors(false);
}));
this._fullGeometry = null; this._fullGeometry = null;
this._actualGeometry = null; this._actualGeometry = null;
this._spacing = 0; this._inDrag = false;
this._windowDragBeginId = Main.overview.connect('window-drag-begin', Lang.bind(this, this._dragBegin));
this._windowDragEndId = Main.overview.connect('window-drag-end', Lang.bind(this, this._dragEnd));
},
_onDestroy: function() {
this._dragEnd();
if (this._windowDragBeginId > 0) {
Main.overview.disconnect(this._windowDragBeginId);
this._windowDragBeginId = 0;
}
if (this._windowDragEndId > 0) {
Main.overview.disconnect(this._windowDragEndId);
this._windowDragEndId = 0;
}
},
_dragBegin: function(overview, clone) {
this._inDrag = true;
this._setReservedSlot(clone);
},
_dragEnd: function() {
this._inDrag = false;
this._setReservedSlot(null);
},
destroy: function() {
this.actor.destroy();
},
setFullGeometry: function(geom) {
this._fullGeometry = geom;
this._syncGeometry();
},
setActualGeometry: function(geom) {
this._actualGeometry = geom;
this._syncGeometry();
},
});
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
Extends: WorkspacesViewBase,
_init: function(monitorIndex) {
this.parent(monitorIndex);
this._animating = false; // tweening this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling this._scrolling = false; // swipe-scrolling
this._animatingScroll = false; // programatically updating the adjustment this._animatingScroll = false; // programatically updating the adjustment
this._inDrag = false; // dragging a window
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
this._updateExtraWorkspacesId =
this._settings.connect('changed::workspaces-only-on-primary',
Lang.bind(this, this._updateExtraWorkspaces));
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); let activeWorkspaceIndex = global.screen.get_active_workspace_index();
this._workspaces = workspaces; this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: 0 });
this.scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
// Add workspace actors this._workspaces = [];
for (let w = 0; w < global.screen.n_workspaces; w++) this._updateWorkspaces();
this.actor.add_actor(this._workspaces[w].actor); this._updateWorkspacesId = global.screen.connect('notify::n-workspaces', Lang.bind(this, this._updateWorkspaces));
this._workspaces[activeWorkspaceIndex].actor.raise_top();
this._extraWorkspaces = [];
this._updateExtraWorkspaces();
// Position/scale the desktop windows and their children after the
// workspaces have been created. This cannot be done first because
// window movement depends on the Workspaces object being accessible
// as an Overview member.
this._overviewShowingId =
Main.overview.connect('showing',
Lang.bind(this, function() {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomToOverview();
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomToOverview();
}));
this._overviewShownId = this._overviewShownId =
Main.overview.connect('shown', Main.overview.connect('shown',
Lang.bind(this, function() { Lang.bind(this, function() {
@ -99,72 +116,21 @@ const WorkspacesView = new Lang.Class({
this._fullGeometry.width, this._fullGeometry.height); this._fullGeometry.width, this._fullGeometry.height);
})); }));
this.scrollAdjustment = new St.Adjustment({ value: activeWorkspaceIndex,
lower: 0,
page_increment: 1,
page_size: 1,
step_increment: 0,
upper: this._workspaces.length });
this.scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._switchWorkspaceNotifyId = this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace', global.window_manager.connect('switch-workspace',
Lang.bind(this, this._activeWorkspaceChanged)); Lang.bind(this, this._activeWorkspaceChanged));
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
Lang.bind(this, this._dragBegin));
this._itemDragEndId = Main.overview.connect('item-drag-end',
Lang.bind(this, this._dragEnd));
this._windowDragBeginId = Main.overview.connect('window-drag-begin',
Lang.bind(this, this._dragBegin));
this._windowDragEndId = Main.overview.connect('window-drag-end',
Lang.bind(this, this._dragEnd));
}, },
_updateExtraWorkspaces: function() { _setReservedSlot: function(clone) {
this._destroyExtraWorkspaces();
if (!this._settings.get_boolean('workspaces-only-on-primary'))
return;
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
if (i == Main.layoutManager.primaryIndex)
continue;
let ws = new Workspace.Workspace(null, i);
ws.setFullGeometry(monitors[i]);
ws.setActualGeometry(monitors[i]);
Main.layoutManager.overviewGroup.add_actor(ws.actor);
this._extraWorkspaces.push(ws);
}
},
_destroyExtraWorkspaces: function() {
for (let m = 0; m < this._extraWorkspaces.length; m++)
this._extraWorkspaces[m].destroy();
this._extraWorkspaces = [];
},
setFullGeometry: function(geom) {
if (rectEqual(this._fullGeometry, geom))
return;
this._fullGeometry = geom;
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setFullGeometry(geom); this._workspaces[i].setReservedSlot(clone);
}, },
setActualGeometry: function(geom) { _syncGeometry: function() {
if (rectEqual(this._actualGeometry, geom))
return;
this._actualGeometry = geom;
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setActualGeometry(geom); this._workspaces[i].setFullGeometry(this._fullGeometry);
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setActualGeometry(this._actualGeometry);
}, },
getActiveWorkspace: function() { getActiveWorkspace: function() {
@ -172,29 +138,22 @@ const WorkspacesView = new Lang.Class({
return this._workspaces[active]; return this._workspaces[active];
}, },
hide: function() { zoomToOverview: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); for (let w = 0; w < this._workspaces.length; w++)
let activeWorkspace = this._workspaces[activeWorkspaceIndex]; this._workspaces[w].zoomToOverview();
this._updateWorkspaceActors(false);
activeWorkspace.actor.raise_top(); },
zoomFromOverview: function() {
this.actor.remove_clip(); this.actor.remove_clip();
for (let w = 0; w < this._workspaces.length; w++) for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomFromOverview(); this._workspaces[w].zoomFromOverview();
for (let w = 0; w < this._extraWorkspaces.length; w++)
this._extraWorkspaces[w].zoomFromOverview();
},
destroy: function() {
this.actor.destroy();
}, },
syncStacking: function(stackIndices) { syncStacking: function(stackIndices) {
for (let i = 0; i < this._workspaces.length; i++) for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].syncStacking(stackIndices); this._workspaces[i].syncStacking(stackIndices);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].syncStacking(stackIndices);
}, },
_scrollToActive: function() { _scrollToActive: function() {
@ -216,7 +175,7 @@ const WorkspacesView = new Lang.Class({
Tweener.removeTweens(workspace.actor); Tweener.removeTweens(workspace.actor);
let y = (w - active) * (this._fullGeometry.height + this._spacing); let y = (w - active) * this._fullGeometry.height;
if (showAnimation) { if (showAnimation) {
let params = { y: y, let params = { y: y,
@ -276,25 +235,31 @@ const WorkspacesView = new Lang.Class({
}); });
}, },
updateWorkspaces: function(oldNumWorkspaces, newNumWorkspaces) { _updateWorkspaces: function() {
let active = global.screen.get_active_workspace_index(); let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
Tweener.addTween(this.scrollAdjustment, this.scrollAdjustment.upper = newNumWorkspaces;
{ upper: newNumWorkspaces,
time: WORKSPACE_SWITCH_TIME,
transition: 'easeOutQuad'
});
if (newNumWorkspaces > oldNumWorkspaces) { if (newNumWorkspaces > oldNumWorkspaces) {
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) { for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
this._workspaces[w].setFullGeometry(this._fullGeometry); let metaWorkspace = global.screen.get_workspace_by_index(w);
if (this._actualGeometry) let workspace = new Workspace.Workspace(metaWorkspace, this._monitorIndex);
this._workspaces[w].setActualGeometry(this._actualGeometry); this._workspaces.push(workspace);
this.actor.add_actor(this._workspaces[w].actor); this.actor.add_actor(workspace.actor);
} }
this._updateWorkspaceActors(false); if (this._fullGeometry)
this._updateWorkspaceActors(false);
} else if (newNumWorkspaces < oldNumWorkspaces) {
let nRemoved = (newNumWorkspaces - oldNumWorkspaces);
let removed = this._workspaces.splice(oldNumWorkspaces, nRemoved);
removed.forEach(function(workspace) {
workspace.destroy();
});
} }
this._syncGeometry();
}, },
_activeWorkspaceChanged: function(wm, from, to, direction) { _activeWorkspaceChanged: function(wm, from, to, direction) {
@ -305,70 +270,12 @@ const WorkspacesView = new Lang.Class({
}, },
_onDestroy: function() { _onDestroy: function() {
this._destroyExtraWorkspaces(); this.parent();
this.scrollAdjustment.run_dispose(); this.scrollAdjustment.run_dispose();
Main.overview.disconnect(this._overviewShowingId);
Main.overview.disconnect(this._overviewShownId); Main.overview.disconnect(this._overviewShownId);
global.window_manager.disconnect(this._switchWorkspaceNotifyId); global.window_manager.disconnect(this._switchWorkspaceNotifyId);
this._settings.disconnect(this._updateExtraWorkspacesId); global.screen.disconnect(this._updateWorkspacesId);
if (this._inDrag)
this._dragEnd();
if (this._itemDragBeginId > 0) {
Main.overview.disconnect(this._itemDragBeginId);
this._itemDragBeginId = 0;
}
if (this._itemDragEndId > 0) {
Main.overview.disconnect(this._itemDragEndId);
this._itemDragEndId = 0;
}
if (this._windowDragBeginId > 0) {
Main.overview.disconnect(this._windowDragBeginId);
this._windowDragBeginId = 0;
}
if (this._windowDragEndId > 0) {
Main.overview.disconnect(this._windowDragEndId);
this._windowDragEndId = 0;
}
},
_dragBegin: function() {
if (this._scrolling)
return;
this._inDrag = true;
this._firstDragMotion = true;
this._dragMonitor = {
dragMotion: Lang.bind(this, this._onDragMotion)
};
DND.addDragMonitor(this._dragMonitor);
},
_onDragMotion: function(dragEvent) {
if (Main.overview.animationInProgress)
return DND.DragMotionResult.CONTINUE;
if (this._firstDragMotion) {
this._firstDragMotion = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
}
return DND.DragMotionResult.CONTINUE;
},
_dragEnd: function() {
DND.removeDragMonitor(this._dragMonitor);
this._inDrag = false;
for (let i = 0; i < this._workspaces.length; i++)
this._workspaces[i].setReservedSlot(null);
for (let i = 0; i < this._extraWorkspaces.length; i++)
this._extraWorkspaces[i].setReservedSlot(null);
}, },
startSwipeScroll: function() { startSwipeScroll: function() {
@ -427,6 +334,42 @@ const WorkspacesView = new Lang.Class({
}); });
Signals.addSignalMethods(WorkspacesView.prototype); Signals.addSignalMethods(WorkspacesView.prototype);
const ExtraWorkspaceView = new Lang.Class({
Name: 'ExtraWorkspaceView',
Extends: WorkspacesViewBase,
_init: function(monitorIndex) {
this.parent(monitorIndex);
this._workspace = new Workspace.Workspace(null, monitorIndex);
this.actor.add_actor(this._workspace.actor);
},
_setReservedSlot: function(clone) {
this._workspace.setReservedSlot(clone);
},
_syncGeometry: function() {
this._workspace.setFullGeometry(this._fullGeometry);
this._workspace.setActualGeometry(this._actualGeometry);
},
zoomToOverview: function() {
this._workspace.zoomToOverview();
},
zoomFromOverview: function() {
this._workspace.zoomFromOverview();
},
syncStacking: function(stackIndices) {
this._workspace.syncStacking(stackIndices);
},
startSwipeScroll: function() {
},
endSwipeScroll: function() {
},
});
const WorkspacesDisplay = new Lang.Class({ const WorkspacesDisplay = new Lang.Class({
Name: 'WorkspacesDisplay', Name: 'WorkspacesDisplay',
@ -471,7 +414,6 @@ const WorkspacesDisplay = new Lang.Class({
this._primaryIndex = Main.layoutManager.primaryIndex; this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = []; this._workspacesViews = [];
this._workspaces = [];
this._primaryScrollAdjustment = null; this._primaryScrollAdjustment = null;
this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA }); this._settings = new Gio.Settings({ schema: OVERRIDE_SCHEMA });
@ -480,9 +422,6 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesOnlyOnPrimaryChanged)); this._workspacesOnlyOnPrimaryChanged));
this._workspacesOnlyOnPrimaryChanged(); this._workspacesOnlyOnPrimaryChanged();
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
this._switchWorkspaceNotifyId = 0; this._switchWorkspaceNotifyId = 0;
this._notifyOpacityId = 0; this._notifyOpacityId = 0;
@ -500,6 +439,8 @@ const WorkspacesDisplay = new Lang.Class({
show: function() { show: function() {
this._updateWorkspacesViews(); this._updateWorkspacesViews();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomToOverview();
this._restackedNotifyId = this._restackedNotifyId =
Main.overview.connect('windows-restacked', Main.overview.connect('windows-restacked',
@ -509,9 +450,8 @@ const WorkspacesDisplay = new Lang.Class({
}, },
zoomFromOverview: function() { zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++) { for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].hide(); this._workspacesViews[i].zoomFromOverview();
}
}, },
hide: function() { hide: function() {
@ -543,46 +483,38 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews[i].destroy(); this._workspacesViews[i].destroy();
this._workspacesViews = []; this._workspacesViews = [];
this._workspaces = [];
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) { for (let i = 0; i < monitors.length; i++) {
let view;
if (this._workspacesOnlyOnPrimary && i != this._primaryIndex) if (this._workspacesOnlyOnPrimary && i != this._primaryIndex)
continue; // we are only interested in the primary monitor view = new ExtraWorkspaceView(i);
else
view = new WorkspacesView(i);
let monitorWorkspaces = [];
for (let w = 0; w < global.screen.n_workspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
monitorWorkspaces.push(new Workspace.Workspace(metaWorkspace, i));
}
this._workspaces.push(monitorWorkspaces);
let view = new WorkspacesView(monitorWorkspaces);
view.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); view.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
if (this._workspacesOnlyOnPrimary || i == this._primaryIndex) { if (i == this._primaryIndex) {
this._scrollAdjustment = view.scrollAdjustment; this._scrollAdjustment = view.scrollAdjustment;
this._scrollAdjustment.connect('notify::value', this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._scrollValueChanged)); Lang.bind(this, this._scrollValueChanged));
} }
this._workspacesViews.push(view); this._workspacesViews.push(view);
Main.layoutManager.overviewGroup.add_actor(view.actor);
} }
this._updateWorkspacesFullGeometry(); this._updateWorkspacesFullGeometry();
this._updateWorkspacesActualGeometry(); this._updateWorkspacesActualGeometry();
for (let i = 0; i < this._workspacesViews.length; i++)
Main.layoutManager.overviewGroup.add_actor(this._workspacesViews[i].actor);
}, },
_scrollValueChanged: function() { _scrollValueChanged: function() {
if (this._workspacesOnlyOnPrimary)
return;
for (let i = 0; i < this._workspacesViews.length; i++) { for (let i = 0; i < this._workspacesViews.length; i++) {
if (i == this._primaryIndex) if (i == this._primaryIndex)
continue; continue;
let adjustment = this._workspacesViews[i].scrollAdjustment; let adjustment = this._workspacesViews[i].scrollAdjustment;
if (!adjustment)
continue;
// the adjustments work in terms of workspaces, so the // the adjustments work in terms of workspaces, so the
// values map directly // values map directly
adjustment.value = this._scrollAdjustment.value; adjustment.value = this._scrollAdjustment.value;
@ -592,10 +524,7 @@ const WorkspacesDisplay = new Lang.Class({
_getPrimaryView: function() { _getPrimaryView: function() {
if (!this._workspacesViews.length) if (!this._workspacesViews.length)
return null; return null;
if (this._workspacesOnlyOnPrimary) return this._workspacesViews[this._primaryIndex];
return this._workspacesViews[0];
else
return this._workspacesViews[this._primaryIndex];
}, },
activeWorkspaceHasMaximizedWindows: function() { activeWorkspaceHasMaximizedWindows: function() {
@ -641,15 +570,9 @@ const WorkspacesDisplay = new Lang.Class({
return; return;
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) { for (let i = 0; i < monitors.length; i++) {
if (i == this._primaryIndex) { let geometry = (i == this._primaryIndex) ? this._fullGeometry : monitors[i];
this._workspacesViews[m].setFullGeometry(this._fullGeometry); this._workspacesViews[i].setFullGeometry(geometry);
m++;
} else if (!this._workspacesOnlyOnPrimary) {
this._workspacesViews[m].setFullGeometry(monitors[i]);
m++;
}
} }
}, },
@ -660,18 +583,12 @@ const WorkspacesDisplay = new Lang.Class({
let [x, y] = this.actor.get_transformed_position(); let [x, y] = this.actor.get_transformed_position();
let width = this.actor.allocation.x2 - this.actor.allocation.x1; let width = this.actor.allocation.x2 - this.actor.allocation.x1;
let height = this.actor.allocation.y2 - this.actor.allocation.y1; let height = this.actor.allocation.y2 - this.actor.allocation.y1;
let geometry = { x: x, y: y, width: width, height: height }; let primaryGeometry = { x: x, y: y, width: width, height: height };
let monitors = Main.layoutManager.monitors; let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) { for (let i = 0; i < monitors.length; i++) {
if (i == this._primaryIndex) { let geometry = (i == this._primaryIndex) ? primaryGeometry : monitors[i];
this._workspacesViews[m].setActualGeometry(geometry); this._workspacesViews[i].setActualGeometry(geometry);
m++;
} else if (!this._workspacesOnlyOnPrimary) {
this._workspacesViews[m].setActualGeometry(monitors[i]);
m++;
}
} }
}, },
@ -680,60 +597,6 @@ const WorkspacesDisplay = new Lang.Class({
this._workspacesViews[i].syncStacking(stackIndices); this._workspacesViews[i].syncStacking(stackIndices);
}, },
_workspacesChanged: function() {
if (!this._workspacesViews.length)
return;
let oldNumWorkspaces = this._workspaces[0].length;
let newNumWorkspaces = global.screen.n_workspaces;
let active = global.screen.get_active_workspace_index();
let lostWorkspaces = [];
if (newNumWorkspaces > oldNumWorkspaces) {
let monitors = Main.layoutManager.monitors;
let m = 0;
for (let i = 0; i < monitors.length; i++) {
if (this._workspacesOnlyOnPrimary &&
i != this._primaryIndex)
continue;
// Assume workspaces are only added at the end
for (let w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
this._workspaces[m][w] =
new Workspace.Workspace(metaWorkspace, i);
}
m++;
}
} else {
// Assume workspaces are only removed sequentially
// (e.g. 2,3,4 - not 2,4,7)
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let metaWorkspace = global.screen.get_workspace_by_index(w);
if (this._workspaces[0][w].metaWorkspace != metaWorkspace) {
removedIndex = w;
break;
}
}
for (let i = 0; i < this._workspaces.length; i++) {
lostWorkspaces = this._workspaces[i].splice(removedIndex,
removedNum);
for (let l = 0; l < lostWorkspaces.length; l++) {
lostWorkspaces[l].disconnectAll();
lostWorkspaces[l].destroy();
}
}
}
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].updateWorkspaces(oldNumWorkspaces,
newNumWorkspaces);
},
_onScrollEvent: function(actor, event) { _onScrollEvent: function(actor, event) {
if (!this.actor.mapped) if (!this.actor.mapped)
return false; return false;

View File

@ -38,7 +38,7 @@ js/ui/panel.js
js/ui/popupMenu.js js/ui/popupMenu.js
js/ui/runDialog.js js/ui/runDialog.js
js/ui/screenShield.js js/ui/screenShield.js
js/ui/searchDisplay.js js/ui/search.js
js/ui/shellEntry.js js/ui/shellEntry.js
js/ui/shellMountOperation.js js/ui/shellMountOperation.js
js/ui/status/accessibility.js js/ui/status/accessibility.js
@ -52,7 +52,6 @@ js/ui/status/system.js
js/ui/status/volume.js js/ui/status/volume.js
js/ui/unlockDialog.js js/ui/unlockDialog.js
js/ui/viewSelector.js js/ui/viewSelector.js
js/ui/wanda.js
js/ui/windowAttentionHandler.js js/ui/windowAttentionHandler.js
js/ui/windowManager.js js/ui/windowManager.js
src/calendar-server/evolution-calendar.desktop.in.in src/calendar-server/evolution-calendar.desktop.in.in

836
po/de.po

File diff suppressed because it is too large Load Diff

785
po/el.po

File diff suppressed because it is too large Load Diff

452
po/he.po

File diff suppressed because it is too large Load Diff

749
po/nb.po

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,8 @@ msgstr ""
"Project-Id-Version: gnome-shell\n" "Project-Id-Version: gnome-shell\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: 2013-10-10 21:27+0000\n" "POT-Creation-Date: 2013-10-26 13:17+0000\n"
"PO-Revision-Date: 2013-10-11 07:22-0300\n" "PO-Revision-Date: 2013-10-27 15:38-0300\n"
"Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n" "Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n" "Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n" "Language: pt_BR\n"
@ -291,23 +291,23 @@ msgid "Select an extension to configure using the combobox above."
msgstr "" msgstr ""
"Selecione uma extensão para configurar usando a caixa de seleção abaixo." "Selecione uma extensão para configurar usando a caixa de seleção abaixo."
#: ../js/gdm/authPrompt.js:145 ../js/ui/components/networkAgent.js:136 #: ../js/gdm/authPrompt.js:146 ../js/ui/components/networkAgent.js:136
#: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351 #: ../js/ui/components/polkitAgent.js:161 ../js/ui/endSessionDialog.js:351
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399 #: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/network.js:728 #: ../js/ui/status/bluetooth.js:221 ../js/ui/status/network.js:739
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
#: ../js/gdm/authPrompt.js:167 ../js/gdm/authPrompt.js:215 #: ../js/gdm/authPrompt.js:168 ../js/gdm/authPrompt.js:216
msgid "Next" msgid "Next"
msgstr "Próximo" msgstr "Próximo"
#: ../js/gdm/authPrompt.js:211 ../js/ui/shellMountOperation.js:403 #: ../js/gdm/authPrompt.js:212 ../js/ui/shellMountOperation.js:403
#: ../js/ui/unlockDialog.js:59 #: ../js/ui/unlockDialog.js:59
msgid "Unlock" msgid "Unlock"
msgstr "Desbloquear" msgstr "Desbloquear"
#: ../js/gdm/authPrompt.js:213 #: ../js/gdm/authPrompt.js:214
msgctxt "button" msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Entrar" msgstr "Entrar"
@ -334,11 +334,11 @@ msgstr "Nome de usuário: "
msgid "Login Window" msgid "Login Window"
msgstr "Janela de sessão" msgstr "Janela de sessão"
#: ../js/gdm/util.js:306 #: ../js/gdm/util.js:321
msgid "Authentication error" msgid "Authentication error"
msgstr "Erro de autenticação" msgstr "Erro de autenticação"
#: ../js/gdm/util.js:436 #: ../js/gdm/util.js:451
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(ou deslize o dedo)" msgstr "(ou deslize o dedo)"
@ -367,15 +367,15 @@ msgstr "Frequente"
msgid "All" msgid "All"
msgstr "Todos" msgstr "Todos"
#: ../js/ui/appDisplay.js:1514 #: ../js/ui/appDisplay.js:1523
msgid "New Window" msgid "New Window"
msgstr "Nova janela" msgstr "Nova janela"
#: ../js/ui/appDisplay.js:1517 ../js/ui/dash.js:284 #: ../js/ui/appDisplay.js:1526 ../js/ui/dash.js:284
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Remover dos favoritos" msgstr "Remover dos favoritos"
#: ../js/ui/appDisplay.js:1518 #: ../js/ui/appDisplay.js:1527
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Adicionar aos favoritos" msgstr "Adicionar aos favoritos"
@ -389,7 +389,7 @@ msgstr "%s foi adicionado aos seus favoritos."
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s foi removido dos seus favoritos." msgstr "%s foi removido dos seus favoritos."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:808 #: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:806
#: ../js/ui/status/system.js:325 #: ../js/ui/status/system.js:325
msgid "Settings" msgid "Settings"
msgstr "Configurações" msgstr "Configurações"
@ -589,8 +589,8 @@ msgstr "Senha:"
msgid "Type again:" msgid "Type again:"
msgstr "Digite novamente:" msgstr "Digite novamente:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:133 #: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:296 ../js/ui/status/network.js:731 #: ../js/ui/status/network.js:295 ../js/ui/status/network.js:742
msgid "Connect" msgid "Connect"
msgstr "Conectar" msgstr "Conectar"
@ -684,60 +684,60 @@ msgstr "Autenticação"
msgid "Sorry, that didn't work. Please try again." msgid "Sorry, that didn't work. Please try again."
msgstr "Desculpe, isto não funcionou. Por favor, tente novamente." msgstr "Desculpe, isto não funcionou. Por favor, tente novamente."
#: ../js/ui/components/telepathyClient.js:238 #: ../js/ui/components/telepathyClient.js:237
msgid "Invitation" msgid "Invitation"
msgstr "Convite" msgstr "Convite"
#: ../js/ui/components/telepathyClient.js:298 #: ../js/ui/components/telepathyClient.js:297
msgid "Call" msgid "Call"
msgstr "Chamada" msgstr "Chamada"
#: ../js/ui/components/telepathyClient.js:314 #: ../js/ui/components/telepathyClient.js:313
msgid "File Transfer" msgid "File Transfer"
msgstr "Transferência de arquivo" msgstr "Transferência de arquivo"
#: ../js/ui/components/telepathyClient.js:418 #: ../js/ui/components/telepathyClient.js:417
msgid "Chat" msgid "Chat"
msgstr "Conversar" msgstr "Conversar"
#: ../js/ui/components/telepathyClient.js:480 #: ../js/ui/components/telepathyClient.js:479
msgid "Unmute" msgid "Unmute"
msgstr "Ativar áudio" msgstr "Ativar áudio"
#: ../js/ui/components/telepathyClient.js:480 #: ../js/ui/components/telepathyClient.js:479
msgid "Mute" msgid "Mute"
msgstr "Sem áudio" msgstr "Sem áudio"
#. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/ #. Translators: this is the word "Yesterday" followed by a time string. i.e. "Yesterday, 14:30"*/
#: ../js/ui/components/telepathyClient.js:942 #: ../js/ui/components/telepathyClient.js:941
msgid "<b>Yesterday</b>, <b>%H:%M</b>" msgid "<b>Yesterday</b>, <b>%H:%M</b>"
msgstr "<b>Ontem</b>, <b>%H:%M</b>" msgstr "<b>Ontem</b>, <b>%H:%M</b>"
#. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/ #. Translators: this is the week day name followed by a time string. i.e. "Monday, 14:30*/
#: ../js/ui/components/telepathyClient.js:948 #: ../js/ui/components/telepathyClient.js:947
msgid "<b>%A</b>, <b>%H:%M</b>" msgid "<b>%A</b>, <b>%H:%M</b>"
msgstr "<b>%A</b>, <b>%H:%M</b>" msgstr "<b>%A</b>, <b>%H:%M</b>"
#. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/ #. Translators: this is the month name and day number followed by a time string. i.e. "May 25, 14:30"*/
#: ../js/ui/components/telepathyClient.js:953 #: ../js/ui/components/telepathyClient.js:952
msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>" msgid "<b>%B</b> <b>%d</b>, <b>%H:%M</b>"
msgstr "<b>%d</b> de <b>%B</b>, às <b>%H:%M</b>" msgstr "<b>%d</b> de <b>%B</b>, às <b>%H:%M</b>"
#. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/ #. Translators: this is the month name, day number, year number followed by a time string. i.e. "May 25 2012, 14:30"*/
#: ../js/ui/components/telepathyClient.js:957 #: ../js/ui/components/telepathyClient.js:956
msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> " msgid "<b>%B</b> <b>%d</b> <b>%Y</b>, <b>%H:%M</b> "
msgstr "<b>%d</b> de <b>%B</b> de <b>%Y</b>, às <b>%H:%M</b> " msgstr "<b>%d</b> de <b>%B</b> de <b>%Y</b>, às <b>%H:%M</b> "
#. 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/components/telepathyClient.js:986 #: ../js/ui/components/telepathyClient.js:985
#, javascript-format #, javascript-format
msgid "%s is now known as %s" msgid "%s is now known as %s"
msgstr "%s agora é conhecido como %s" msgstr "%s agora é conhecido como %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/components/telepathyClient.js:1089 #: ../js/ui/components/telepathyClient.js:1088
#, javascript-format #, javascript-format
msgid "Invitation to %s" msgid "Invitation to %s"
msgstr "Convite para %s" msgstr "Convite para %s"
@ -745,38 +745,38 @@ msgstr "Convite para %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/components/telepathyClient.js:1097 #: ../js/ui/components/telepathyClient.js:1096
#, javascript-format #, javascript-format
msgid "%s is inviting you to join %s" msgid "%s is inviting you to join %s"
msgstr "%s está convidando você para participar de %s" msgstr "%s está convidando você para participar de %s"
#: ../js/ui/components/telepathyClient.js:1099 #: ../js/ui/components/telepathyClient.js:1098
#: ../js/ui/components/telepathyClient.js:1140 #: ../js/ui/components/telepathyClient.js:1139
#: ../js/ui/components/telepathyClient.js:1180 #: ../js/ui/components/telepathyClient.js:1179
#: ../js/ui/components/telepathyClient.js:1243 #: ../js/ui/components/telepathyClient.js:1242
msgid "Decline" msgid "Decline"
msgstr "Recusar" msgstr "Recusar"
#: ../js/ui/components/telepathyClient.js:1100 #: ../js/ui/components/telepathyClient.js:1099
#: ../js/ui/components/telepathyClient.js:1181 #: ../js/ui/components/telepathyClient.js:1180
#: ../js/ui/components/telepathyClient.js:1244 #: ../js/ui/components/telepathyClient.js:1243
msgid "Accept" msgid "Accept"
msgstr "Aceitar" msgstr "Aceitar"
#. translators: argument is a contact name like Alice for example. */ #. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1130 #: ../js/ui/components/telepathyClient.js:1129
#, javascript-format #, javascript-format
msgid "Video call from %s" msgid "Video call from %s"
msgstr "Chamada de vídeo para %s" msgstr "Chamada de vídeo para %s"
#. translators: argument is a contact name like Alice for example. */ #. translators: argument is a contact name like Alice for example. */
#: ../js/ui/components/telepathyClient.js:1133 #: ../js/ui/components/telepathyClient.js:1132
#, javascript-format #, javascript-format
msgid "Call from %s" msgid "Call from %s"
msgstr "Chamada de %s" msgstr "Chamada de %s"
#. translators: this is a button label (verb), not a noun */ #. translators: this is a button label (verb), not a noun */
#: ../js/ui/components/telepathyClient.js:1142 #: ../js/ui/components/telepathyClient.js:1141
msgid "Answer" msgid "Answer"
msgstr "Atender" msgstr "Atender"
@ -785,110 +785,110 @@ msgstr "Atender"
#. * 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/components/telepathyClient.js:1174 #: ../js/ui/components/telepathyClient.js:1173
#, javascript-format #, javascript-format
msgid "%s is sending you %s" msgid "%s is sending you %s"
msgstr "%s está enviando %s" msgstr "%s está enviando %s"
#. To translators: The parameter is the contact's alias */ #. To translators: The parameter is the contact's alias */
#: ../js/ui/components/telepathyClient.js:1209 #: ../js/ui/components/telepathyClient.js:1208
#, javascript-format #, javascript-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 quer permissão para vê-lo quando conectado" msgstr "%s quer permissão para vê-lo quando conectado"
#: ../js/ui/components/telepathyClient.js:1301 #: ../js/ui/components/telepathyClient.js:1300
msgid "Network error" msgid "Network error"
msgstr "Erro de rede" msgstr "Erro de rede"
#: ../js/ui/components/telepathyClient.js:1303 #: ../js/ui/components/telepathyClient.js:1302
msgid "Authentication failed" msgid "Authentication failed"
msgstr "Falha de autenticação" msgstr "Falha de autenticação"
#: ../js/ui/components/telepathyClient.js:1305 #: ../js/ui/components/telepathyClient.js:1304
msgid "Encryption error" msgid "Encryption error"
msgstr "Erro de criptografia" msgstr "Erro de criptografia"
#: ../js/ui/components/telepathyClient.js:1307 #: ../js/ui/components/telepathyClient.js:1306
msgid "Certificate not provided" msgid "Certificate not provided"
msgstr "Certificado não fornecido" msgstr "Certificado não fornecido"
#: ../js/ui/components/telepathyClient.js:1309 #: ../js/ui/components/telepathyClient.js:1308
msgid "Certificate untrusted" msgid "Certificate untrusted"
msgstr "Certificado não confiável" msgstr "Certificado não confiável"
#: ../js/ui/components/telepathyClient.js:1311 #: ../js/ui/components/telepathyClient.js:1310
msgid "Certificate expired" msgid "Certificate expired"
msgstr "Certificado expirado" msgstr "Certificado expirado"
#: ../js/ui/components/telepathyClient.js:1313 #: ../js/ui/components/telepathyClient.js:1312
msgid "Certificate not activated" msgid "Certificate not activated"
msgstr "Certificado não ativado" msgstr "Certificado não ativado"
#: ../js/ui/components/telepathyClient.js:1315 #: ../js/ui/components/telepathyClient.js:1314
msgid "Certificate hostname mismatch" msgid "Certificate hostname mismatch"
msgstr "Máquina do certificado não confere" msgstr "Máquina do certificado não confere"
#: ../js/ui/components/telepathyClient.js:1317 #: ../js/ui/components/telepathyClient.js:1316
msgid "Certificate fingerprint mismatch" msgid "Certificate fingerprint mismatch"
msgstr "Impressão digital do certificado não confere" msgstr "Impressão digital do certificado não confere"
#: ../js/ui/components/telepathyClient.js:1319 #: ../js/ui/components/telepathyClient.js:1318
msgid "Certificate self-signed" msgid "Certificate self-signed"
msgstr "Certificado auto-assinado" msgstr "Certificado auto-assinado"
#: ../js/ui/components/telepathyClient.js:1321 #: ../js/ui/components/telepathyClient.js:1320
msgid "Status is set to offline" msgid "Status is set to offline"
msgstr "O status está definido como desconectado." msgstr "O status está definido como desconectado."
#: ../js/ui/components/telepathyClient.js:1323 #: ../js/ui/components/telepathyClient.js:1322
msgid "Encryption is not available" msgid "Encryption is not available"
msgstr "Criptografia não disponível" msgstr "Criptografia não disponível"
#: ../js/ui/components/telepathyClient.js:1325 #: ../js/ui/components/telepathyClient.js:1324
msgid "Certificate is invalid" msgid "Certificate is invalid"
msgstr "O certificado é inválido" msgstr "O certificado é inválido"
#: ../js/ui/components/telepathyClient.js:1327 #: ../js/ui/components/telepathyClient.js:1326
msgid "Connection has been refused" msgid "Connection has been refused"
msgstr "A conexão foi recusada" msgstr "A conexão foi recusada"
#: ../js/ui/components/telepathyClient.js:1329 #: ../js/ui/components/telepathyClient.js:1328
msgid "Connection can't be established" msgid "Connection can't be established"
msgstr "A conexão não pode ser estabelecida" msgstr "A conexão não pode ser estabelecida"
#: ../js/ui/components/telepathyClient.js:1331 #: ../js/ui/components/telepathyClient.js:1330
msgid "Connection has been lost" msgid "Connection has been lost"
msgstr "Conexão perdida" msgstr "Conexão perdida"
#: ../js/ui/components/telepathyClient.js:1333 #: ../js/ui/components/telepathyClient.js:1332
msgid "This account is already connected to the server" msgid "This account is already connected to the server"
msgstr "Esta conta já está conectada ao servidor" msgstr "Esta conta já está conectada ao servidor"
#: ../js/ui/components/telepathyClient.js:1335 #: ../js/ui/components/telepathyClient.js:1334
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 "A conexão foi substituída por uma nova conexão usando o mesmo recurso" msgstr "A conexão foi substituída por uma nova conexão usando o mesmo recurso"
#: ../js/ui/components/telepathyClient.js:1337 #: ../js/ui/components/telepathyClient.js:1336
msgid "The account already exists on the server" msgid "The account already exists on the server"
msgstr "A conta já existe no servidor" msgstr "A conta já existe no servidor"
#: ../js/ui/components/telepathyClient.js:1339 #: ../js/ui/components/telepathyClient.js:1338
msgid "Server is currently too busy to handle the connection" msgid "Server is currently too busy to handle the connection"
msgstr "O servidor está atualmente muito ocupado para controlar a conexão" msgstr "O servidor está atualmente muito ocupado para controlar a conexão"
#: ../js/ui/components/telepathyClient.js:1341 #: ../js/ui/components/telepathyClient.js:1340
msgid "Certificate has been revoked" msgid "Certificate has been revoked"
msgstr "O certificado foi revogado" msgstr "O certificado foi revogado"
#: ../js/ui/components/telepathyClient.js:1343 #: ../js/ui/components/telepathyClient.js:1342
msgid "" msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak" "Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "" msgstr ""
"O certificado usa um algoritmo de cifragem inseguro ou é criptograficamente " "O certificado usa um algoritmo de cifragem inseguro ou é criptograficamente "
"fraco" "fraco"
#: ../js/ui/components/telepathyClient.js:1345 #: ../js/ui/components/telepathyClient.js:1344
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"
@ -896,22 +896,22 @@ msgstr ""
"O comprimento do certificado do servidor, ou a profundidade da cadeia do " "O comprimento do certificado do servidor, ou a profundidade da cadeia do "
"certificado excedeu os limites impostos pela biblioteca de criptografia" "certificado excedeu os limites impostos pela biblioteca de criptografia"
#: ../js/ui/components/telepathyClient.js:1347 #: ../js/ui/components/telepathyClient.js:1346
msgid "Internal error" msgid "Internal error"
msgstr "Erro interno" msgstr "Erro 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/components/telepathyClient.js:1357 #: ../js/ui/components/telepathyClient.js:1356
#, javascript-format #, javascript-format
msgid "Unable to connect to %s" msgid "Unable to connect to %s"
msgstr "Não foi possível conectar-se a %s" msgstr "Não foi possível conectar-se a %s"
#: ../js/ui/components/telepathyClient.js:1362 #: ../js/ui/components/telepathyClient.js:1361
msgid "View account" msgid "View account"
msgstr "Visualizar conta" msgstr "Visualizar conta"
#: ../js/ui/components/telepathyClient.js:1401 #: ../js/ui/components/telepathyClient.js:1400
msgid "Unknown reason" msgid "Unknown reason"
msgstr "Razão desconhecida" msgstr "Razão desconhecida"
@ -1092,7 +1092,7 @@ msgstr "Habilitado"
#. because it's disabled by rfkill (airplane mode) */ #. because it's disabled by rfkill (airplane mode) */
#. translators: #. translators:
#. * The device has been disabled #. * The device has been disabled
#: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:473 #: ../js/ui/lookingGlass.js:765 ../js/ui/status/network.js:472
#: ../src/gvc/gvc-mixer-control.c:1830 #: ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled" msgid "Disabled"
msgstr "Desabilitado" msgstr "Desabilitado"
@ -1117,49 +1117,48 @@ msgstr "Ver fonte"
msgid "Web Page" msgid "Web Page"
msgstr "Página web" msgstr "Página web"
#: ../js/ui/messageTray.js:1222 #: ../js/ui/messageTray.js:1347
msgid "Open" msgid "Open"
msgstr "Abrir" msgstr "Abrir"
#: ../js/ui/messageTray.js:1229 #: ../js/ui/messageTray.js:1354
msgid "Remove" msgid "Remove"
msgstr "Remover" msgstr "Remover"
#: ../js/ui/messageTray.js:1530 #: ../js/ui/messageTray.js:1657
#| msgid "Notification Settings"
msgid "Notifications" msgid "Notifications"
msgstr "Notificações" msgstr "Notificações"
#: ../js/ui/messageTray.js:1537 #: ../js/ui/messageTray.js:1664
msgid "Clear Messages" msgid "Clear Messages"
msgstr "Sem mensagens" msgstr "Sem mensagens"
#: ../js/ui/messageTray.js:1564 #: ../js/ui/messageTray.js:1683
msgid "Notification Settings" msgid "Notification Settings"
msgstr "Configurações de notificação" msgstr "Configurações de notificação"
#: ../js/ui/messageTray.js:1617 #: ../js/ui/messageTray.js:1736
msgid "Tray Menu" msgid "Tray Menu"
msgstr "Menu de notificação" msgstr "Menu de notificação"
#: ../js/ui/messageTray.js:1833 #: ../js/ui/messageTray.js:1952
msgid "No Messages" msgid "No Messages"
msgstr "Sem mensagens" msgstr "Sem mensagens"
#: ../js/ui/messageTray.js:1871 #: ../js/ui/messageTray.js:1990
msgid "Message Tray" msgid "Message Tray"
msgstr "Área de notificação" msgstr "Área de notificação"
#: ../js/ui/messageTray.js:2846 #: ../js/ui/messageTray.js:2965
msgid "System Information" msgid "System Information"
msgstr "Informações do sistema" msgstr "Informações do sistema"
#: ../js/ui/notificationDaemon.js:629 ../src/shell-app.c:396 #: ../js/ui/notificationDaemon.js:510 ../src/shell-app.c:396
msgctxt "program" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Desconhecido" msgstr "Desconhecido"
#: ../js/ui/overviewControls.js:491 ../js/ui/screenShield.js:152 #: ../js/ui/overviewControls.js:488 ../js/ui/screenShield.js:153
#, javascript-format #, javascript-format
msgid "%d new message" msgid "%d new message"
msgid_plural "%d new messages" msgid_plural "%d new messages"
@ -1182,21 +1181,21 @@ msgstr "Panorama"
msgid "Type to search…" msgid "Type to search…"
msgstr "Digite para pesquisar…" msgstr "Digite para pesquisar…"
#: ../js/ui/panel.js:518 #: ../js/ui/panel.js:516
msgid "Quit" msgid "Quit"
msgstr "Sair" msgstr "Sair"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". */ #. in your language, you can use the word for "Overview". */
#: ../js/ui/panel.js:570 #: ../js/ui/panel.js:568
msgid "Activities" msgid "Activities"
msgstr "Atividades" msgstr "Atividades"
#: ../js/ui/panel.js:904 #: ../js/ui/panel.js:900
msgid "Top Bar" msgid "Top Bar"
msgstr "Barra superior" msgstr "Barra superior"
#: ../js/ui/popupMenu.js:233 #: ../js/ui/popupMenu.js:260
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-intl"
@ -1210,30 +1209,30 @@ msgstr "Fechar"
#. Translators: This is a time format for a date in #. Translators: This is a time format for a date in
#. long format */ #. long format */
#: ../js/ui/screenShield.js:88 #: ../js/ui/screenShield.js:89
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%A, %d de %B" msgstr "%A, %d de %B"
#: ../js/ui/screenShield.js:154 #: ../js/ui/screenShield.js:155
#, javascript-format #, javascript-format
msgid "%d new notification" msgid "%d new notification"
msgid_plural "%d new notifications" msgid_plural "%d new notifications"
msgstr[0] "%d nova notificação" msgstr[0] "%d nova notificação"
msgstr[1] "%d novas notificações" msgstr[1] "%d novas notificações"
#: ../js/ui/screenShield.js:477 ../js/ui/status/system.js:333 #: ../js/ui/screenShield.js:478 ../js/ui/status/system.js:333
msgid "Lock" msgid "Lock"
msgstr "Bloquear" msgstr "Bloquear"
#: ../js/ui/screenShield.js:704 #: ../js/ui/screenShield.js:712
msgid "GNOME needs to lock the screen" msgid "GNOME needs to lock the screen"
msgstr "GNOME precisa bloquear a tela" msgstr "GNOME precisa bloquear a tela"
#: ../js/ui/screenShield.js:831 ../js/ui/screenShield.js:1297 #: ../js/ui/screenShield.js:839 ../js/ui/screenShield.js:1305
msgid "Unable to lock" msgid "Unable to lock"
msgstr "Não foi possível bloquear" msgstr "Não foi possível bloquear"
#: ../js/ui/screenShield.js:832 ../js/ui/screenShield.js:1298 #: ../js/ui/screenShield.js:840 ../js/ui/screenShield.js:1306
msgid "Lock was blocked by an application" msgid "Lock was blocked by an application"
msgstr "O bloqueio foi impedido por um aplicativo" msgstr "O bloqueio foi impedido por um aplicativo"
@ -1273,111 +1272,111 @@ msgstr "Lembrar senha"
msgid "Accessibility" msgid "Accessibility"
msgstr "Acessibilidade" msgstr "Acessibilidade"
#: ../js/ui/status/accessibility.js:58 #: ../js/ui/status/accessibility.js:56
msgid "Zoom" msgid "Zoom"
msgstr "Ampliador" msgstr "Ampliador"
#: ../js/ui/status/accessibility.js:65 #: ../js/ui/status/accessibility.js:63
msgid "Screen Reader" msgid "Screen Reader"
msgstr "Leitor de tela" msgstr "Leitor de tela"
#: ../js/ui/status/accessibility.js:69 #: ../js/ui/status/accessibility.js:67
msgid "Screen Keyboard" msgid "Screen Keyboard"
msgstr "Teclado de tela" msgstr "Teclado de tela"
#: ../js/ui/status/accessibility.js:73 #: ../js/ui/status/accessibility.js:71
msgid "Visual Alerts" msgid "Visual Alerts"
msgstr "Alertas visuais" msgstr "Alertas visuais"
#: ../js/ui/status/accessibility.js:76 #: ../js/ui/status/accessibility.js:74
msgid "Sticky Keys" msgid "Sticky Keys"
msgstr "Teclas de aderência" msgstr "Teclas de aderência"
#: ../js/ui/status/accessibility.js:79 #: ../js/ui/status/accessibility.js:77
msgid "Slow Keys" msgid "Slow Keys"
msgstr "Teclas lentas" msgstr "Teclas lentas"
#: ../js/ui/status/accessibility.js:82 #: ../js/ui/status/accessibility.js:80
msgid "Bounce Keys" msgid "Bounce Keys"
msgstr "Teclas de repercussão" msgstr "Teclas de repercussão"
#: ../js/ui/status/accessibility.js:85 #: ../js/ui/status/accessibility.js:83
msgid "Mouse Keys" msgid "Mouse Keys"
msgstr "Teclas do mouse" msgstr "Teclas do mouse"
#: ../js/ui/status/accessibility.js:144 #: ../js/ui/status/accessibility.js:142
msgid "High Contrast" msgid "High Contrast"
msgstr "Alto contraste" msgstr "Alto contraste"
#: ../js/ui/status/accessibility.js:193 #: ../js/ui/status/accessibility.js:191
msgid "Large Text" msgid "Large Text"
msgstr "Texto grande" msgstr "Texto grande"
#: ../js/ui/status/bluetooth.js:28 ../js/ui/status/bluetooth.js:63 #: ../js/ui/status/bluetooth.js:27 ../js/ui/status/bluetooth.js:62
#: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128 #: ../js/ui/status/bluetooth.js:99 ../js/ui/status/bluetooth.js:127
#: ../js/ui/status/bluetooth.js:164 ../js/ui/status/bluetooth.js:195 #: ../js/ui/status/bluetooth.js:163 ../js/ui/status/bluetooth.js:194
msgid "Bluetooth" msgid "Bluetooth"
msgstr "Bluetooth" msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:30 ../js/ui/status/network.js:133 #: ../js/ui/status/bluetooth.js:29 ../js/ui/status/network.js:132
#: ../js/ui/status/network.js:1085 ../js/ui/status/rfkill.js:46 #: ../js/ui/status/network.js:1099 ../js/ui/status/rfkill.js:46
msgid "Turn Off" msgid "Turn Off"
msgstr "Desligar" msgstr "Desligar"
#: ../js/ui/status/bluetooth.js:33 #: ../js/ui/status/bluetooth.js:32
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "Configurações de Bluetooth" msgstr "Configurações de Bluetooth"
#: ../js/ui/status/bluetooth.js:58 #: ../js/ui/status/bluetooth.js:57
#, javascript-format #, javascript-format
msgid "%d Connected Device" msgid "%d Connected Device"
msgid_plural "%d Connected Devices" msgid_plural "%d Connected Devices"
msgstr[0] "%d dispositivo conectado" msgstr[0] "%d dispositivo conectado"
msgstr[1] "%d dispositivos conectados" msgstr[1] "%d dispositivos conectados"
#: ../js/ui/status/bluetooth.js:101 ../js/ui/status/bluetooth.js:129 #: ../js/ui/status/bluetooth.js:100 ../js/ui/status/bluetooth.js:128
#, javascript-format #, javascript-format
msgid "Authorization request from %s" msgid "Authorization request from %s"
msgstr "Autorização requisitada de %s" msgstr "Autorização requisitada de %s"
#: ../js/ui/status/bluetooth.js:107 ../js/ui/status/bluetooth.js:172 #: ../js/ui/status/bluetooth.js:106 ../js/ui/status/bluetooth.js:171
#: ../js/ui/status/bluetooth.js:203 #: ../js/ui/status/bluetooth.js:202
#, javascript-format #, javascript-format
msgid "Device %s wants to pair with this computer" msgid "Device %s wants to pair with this computer"
msgstr "O dispositivo %s deseja parear com este computador" msgstr "O dispositivo %s deseja parear com este computador"
#: ../js/ui/status/bluetooth.js:109 #: ../js/ui/status/bluetooth.js:108
msgid "Allow" msgid "Allow"
msgstr "Permitir" msgstr "Permitir"
#: ../js/ui/status/bluetooth.js:110 #: ../js/ui/status/bluetooth.js:109
msgid "Deny" msgid "Deny"
msgstr "Negar" msgstr "Negar"
#: ../js/ui/status/bluetooth.js:135 #: ../js/ui/status/bluetooth.js:134
#, javascript-format #, javascript-format
msgid "Device %s wants access to the service '%s'" msgid "Device %s wants access to the service '%s'"
msgstr "O dispositivo %s deseja acessar o serviço \"%s\"" msgstr "O dispositivo %s deseja acessar o serviço \"%s\""
#: ../js/ui/status/bluetooth.js:137 #: ../js/ui/status/bluetooth.js:136
msgid "Always grant access" msgid "Always grant access"
msgstr "Sempre permitir acesso" msgstr "Sempre permitir acesso"
#: ../js/ui/status/bluetooth.js:138 #: ../js/ui/status/bluetooth.js:137
msgid "Grant this time only" msgid "Grant this time only"
msgstr "Permitir apenas desta vez" msgstr "Permitir apenas desta vez"
#: ../js/ui/status/bluetooth.js:139 #: ../js/ui/status/bluetooth.js:138
msgid "Reject" msgid "Reject"
msgstr "Rejeitar" msgstr "Rejeitar"
#. Translators: argument is the device short name */ #. Translators: argument is the device short name */
#: ../js/ui/status/bluetooth.js:166 #: ../js/ui/status/bluetooth.js:165
#, javascript-format #, javascript-format
msgid "Pairing confirmation for %s" msgid "Pairing confirmation for %s"
msgstr "Confirmação de pareamento para %s" msgstr "Confirmação de pareamento para %s"
#: ../js/ui/status/bluetooth.js:173 #: ../js/ui/status/bluetooth.js:172
#, javascript-format #, javascript-format
msgid "" msgid ""
"Please confirm whether the Passkey '%06d' matches the one on the device." "Please confirm whether the Passkey '%06d' matches the one on the device."
@ -1386,24 +1385,24 @@ msgstr ""
"dispositivo." "dispositivo."
#. Translators: this is the verb, not the noun */ #. Translators: this is the verb, not the noun */
#: ../js/ui/status/bluetooth.js:176 #: ../js/ui/status/bluetooth.js:175
msgid "Matches" msgid "Matches"
msgstr "Corresponde" msgstr "Corresponde"
#: ../js/ui/status/bluetooth.js:177 #: ../js/ui/status/bluetooth.js:176
msgid "Does not match" msgid "Does not match"
msgstr "Não corresponde" msgstr "Não corresponde"
#: ../js/ui/status/bluetooth.js:196 #: ../js/ui/status/bluetooth.js:195
#, javascript-format #, javascript-format
msgid "Pairing request for %s" msgid "Pairing request for %s"
msgstr "Requisição de pareamento para %s" msgstr "Requisição de pareamento para %s"
#: ../js/ui/status/bluetooth.js:204 #: ../js/ui/status/bluetooth.js:203
msgid "Please enter the PIN mentioned on the device." msgid "Please enter the PIN mentioned on the device."
msgstr "Por favor, informe o PIN mencionado no dispositivo." msgstr "Por favor, informe o PIN mencionado no dispositivo."
#: ../js/ui/status/bluetooth.js:221 #: ../js/ui/status/bluetooth.js:220
msgid "OK" msgid "OK"
msgstr "OK" msgstr "OK"
@ -1411,99 +1410,100 @@ msgstr "OK"
msgid "Brightness" msgid "Brightness"
msgstr "Brilho" msgstr "Brilho"
#: ../js/ui/status/network.js:72 #: ../js/ui/status/network.js:71
msgid "<unknown>" msgid "<unknown>"
msgstr "<desconhecido>" msgstr "<desconhecido>"
#: ../js/ui/status/network.js:223 ../js/ui/status/network.js:380 # Referente ao estado "desligado" da rede.
#: ../js/ui/status/network.js:1106 #: ../js/ui/status/network.js:222 ../js/ui/status/network.js:379
#: ../js/ui/status/network.js:1120
msgid "Off" msgid "Off"
msgstr "Desligar" msgstr "Desligado"
#. Translators: this is for network devices that are physically present but are not #. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu) */ #. under NetworkManager's control (and thus cannot be used in the menu) */
#: ../js/ui/status/network.js:386 #: ../js/ui/status/network.js:385
msgid "unmanaged" msgid "unmanaged"
msgstr "não gerenciado" msgstr "não gerenciado"
#: ../js/ui/status/network.js:388 #: ../js/ui/status/network.js:387
msgid "disconnecting..." msgid "disconnecting..."
msgstr "desconectando..." msgstr "desconectando..."
#: ../js/ui/status/network.js:394 ../js/ui/status/network.js:1160 #: ../js/ui/status/network.js:393 ../js/ui/status/network.js:1174
msgid "connecting..." msgid "connecting..."
msgstr "conectando..." msgstr "conectando..."
#. Translators: this is for network connections that require some kind of key or password */ #. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:397 ../js/ui/status/network.js:1163 #: ../js/ui/status/network.js:396 ../js/ui/status/network.js:1177
msgid "authentication required" msgid "authentication required"
msgstr "autenticação necessária" msgstr "autenticação necessária"
#. Translators: this is for devices that require some kind of firmware or kernel #. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */ #. module, which is missing */
#: ../js/ui/status/network.js:405 #: ../js/ui/status/network.js:404
msgid "firmware missing" msgid "firmware missing"
msgstr "firmware faltando" msgstr "firmware faltando"
#. Translators: this is for a network device that cannot be activated (for example it #. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage */ #. is disabled by rfkill, or it has no coverage */
#: ../js/ui/status/network.js:409 #: ../js/ui/status/network.js:408
msgid "unavailable" msgid "unavailable"
msgstr "indisponível" msgstr "indisponível"
#: ../js/ui/status/network.js:411 ../js/ui/status/network.js:1165 #: ../js/ui/status/network.js:410 ../js/ui/status/network.js:1179
msgid "connection failed" msgid "connection failed"
msgstr "conexão falhou" msgstr "conexão falhou"
#: ../js/ui/status/network.js:427 ../js/ui/status/network.js:513 #: ../js/ui/status/network.js:426 ../js/ui/status/network.js:512
msgid "Mobile Broadband Settings" msgid "Mobile Broadband Settings"
msgstr "Configurações de banda larga móvel" msgstr "Configurações de banda larga móvel"
#: ../js/ui/status/network.js:469 ../js/ui/status/network.js:1104 #: ../js/ui/status/network.js:468 ../js/ui/status/network.js:1118
msgid "Hardware Disabled" msgid "Hardware Disabled"
msgstr "Hardware desabilitado" msgstr "Hardware desabilitado"
#: ../js/ui/status/network.js:696 #: ../js/ui/status/network.js:707
msgid "Wi-Fi Networks" msgid "Wi-Fi Networks"
msgstr "Redes Wi-Fi" msgstr "Redes Wi-Fi"
#: ../js/ui/status/network.js:698 #: ../js/ui/status/network.js:709
msgid "Select a network" msgid "Select a network"
msgstr "Selecione uma rede" msgstr "Selecione uma rede"
#: ../js/ui/status/network.js:722 #: ../js/ui/status/network.js:733
msgid "No Networks" msgid "No Networks"
msgstr "Nenhuma rede" msgstr "Nenhuma rede"
#: ../js/ui/status/network.js:991 #: ../js/ui/status/network.js:1005
msgid "Select Network" msgid "Select Network"
msgstr "Selecione a rede" msgstr "Selecione a rede"
#: ../js/ui/status/network.js:997 #: ../js/ui/status/network.js:1011
msgid "Wi-Fi Settings" msgid "Wi-Fi Settings"
msgstr "Configurações de Wi-Fi" msgstr "Configurações de Wi-Fi"
#: ../js/ui/status/network.js:1085 #: ../js/ui/status/network.js:1099
msgid "Turn On" msgid "Turn On"
msgstr "Ligar" msgstr "Ligar"
#: ../js/ui/status/network.js:1108 #: ../js/ui/status/network.js:1122
msgid "Not Connected" msgid "Not Connected"
msgstr "Não conectado" msgstr "Não conectado"
#: ../js/ui/status/network.js:1228 #: ../js/ui/status/network.js:1242
msgid "VPN" msgid "VPN"
msgstr "VPN" msgstr "VPN"
#: ../js/ui/status/network.js:1368 #: ../js/ui/status/network.js:1382
msgid "Network Manager" msgid "Network Manager"
msgstr "Gerenciador de rede" msgstr "Gerenciador de rede"
#: ../js/ui/status/network.js:1407 #: ../js/ui/status/network.js:1421
msgid "Connection failed" msgid "Connection failed"
msgstr "Falha de conexão" msgstr "Falha de conexão"
#: ../js/ui/status/network.js:1408 #: ../js/ui/status/network.js:1422
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "Falha ao ativar a conexão da rede" msgstr "Falha ao ativar a conexão da rede"

909
po/ru.po

File diff suppressed because it is too large Load Diff

1967
po/ta.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -156,8 +156,10 @@ libst_1_0_la_SOURCES = \
$(st_source_private_h) \ $(st_source_private_h) \
$(st_source_private_c) \ $(st_source_private_c) \
$(st_source_h) \ $(st_source_h) \
st.h \ $(NULL)
nodist_libst_1_0_la_SOURCES = \
$(st_built_sources) \ $(st_built_sources) \
st.h \
$(NULL) $(NULL)
libst_1_0_la_CPPFLAGS = $(st_cflags) libst_1_0_la_CPPFLAGS = $(st_cflags)
libst_1_0_la_LDFLAGS = $(LDADD) libst_1_0_la_LDFLAGS = $(LDADD)

View File

@ -4,8 +4,6 @@ tray_cflags = \
$(TRAY_CFLAGS) \ $(TRAY_CFLAGS) \
$(NULL) $(NULL)
BUILT_SOURCES += $(tray_built_sources)
# please, keep this sorted alphabetically # please, keep this sorted alphabetically
tray_source = \ tray_source = \
tray/na-tray-child.c \ tray/na-tray-child.c \
@ -19,7 +17,6 @@ noinst_LTLIBRARIES += libtray.la
libtray_la_LIBADD = $(TRAY_LIBS) libtray_la_LIBADD = $(TRAY_LIBS)
libtray_la_SOURCES = \ libtray_la_SOURCES = \
$(tray_source) \ $(tray_source) \
$(tray_built_sources) \
$(NULL) $(NULL)
libtray_la_CPPFLAGS = $(tray_cflags) libtray_la_CPPFLAGS = $(tray_cflags)
libtray_la_LDFLAGS = $(LDADD) libtray_la_LDFLAGS = $(LDADD)

View File

@ -75,8 +75,7 @@ gnome_shell_cflags = \
-DDATADIR=\"$(datadir)\" \ -DDATADIR=\"$(datadir)\" \
-DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \ -DGNOME_SHELL_LIBEXECDIR=\"$(libexecdir)\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \ -DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \ -DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\"
-DJSDIR=\"$(pkgdatadir)/js\"
privlibdir = $(pkglibdir) privlibdir = $(pkglibdir)
privlib_LTLIBRARIES = libgnome-shell-js.la libgnome-shell-menu.la libgnome-shell.la privlib_LTLIBRARIES = libgnome-shell-js.la libgnome-shell-menu.la libgnome-shell.la
@ -152,7 +151,6 @@ libgnome_shell_base_la_SOURCES = \
$(NULL) $(NULL)
libgnome_shell_sources = \ libgnome_shell_sources = \
$(shell_built_sources) \
$(shell_public_headers_h) \ $(shell_public_headers_h) \
shell-app-private.h \ shell-app-private.h \
shell-app-system-private.h \ shell-app-system-private.h \
@ -173,10 +171,17 @@ libgnome_shell_sources = \
shell-wm.c \ shell-wm.c \
$(NULL) $(NULL)
libgnome_shell_built_sources = \
$(shell_built_sources) \
$(top_builddir)/js/js-resources.c \
$(top_builddir)/js/js-resources.h \
$(NULL)
libgnome_shell_la_SOURCES = $(libgnome_shell_sources) libgnome_shell_la_SOURCES = $(libgnome_shell_sources)
nodist_libgnome_shell_la_SOURCES = $(libgnome_shell_built_sources)
libgnome_shell_la_gir_sources = \ libgnome_shell_la_gir_sources = \
$(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_base_la_SOURCES) $(libgnome_shell_sources)) $(filter-out %-private.h $(shell_private_sources), $(shell_public_headers_h) $(libgnome_shell_base_la_SOURCES) $(libgnome_shell_sources) $(libgnome_shell_built_sources))
gnome_shell_SOURCES = main.c gnome_shell_SOURCES = main.c
gnome_shell_CPPFLAGS = \ gnome_shell_CPPFLAGS = \
@ -191,6 +196,7 @@ gnome_shell_DEPENDENCIES = libgnome-shell.la
if HAVE_MUTTER_WAYLAND if HAVE_MUTTER_WAYLAND
libgnome_shell_wayland_la_SOURCES = $(libgnome_shell_sources) libgnome_shell_wayland_la_SOURCES = $(libgnome_shell_sources)
nodist_libgnome_shell_wayland_la_SOURCES = $(libgnome_shell_built_sources)
gnome_shell_wayland_SOURCES = main.c gnome_shell_wayland_SOURCES = main.c
gnome_shell_wayland_CPPFLAGS = \ gnome_shell_wayland_CPPFLAGS = \
@ -207,7 +213,7 @@ endif HAVE_MUTTER_WAYLAND
libgnome_shell_js_la_SOURCES = \ libgnome_shell_js_la_SOURCES = \
shell-js.h \ shell-js.h \
shell-js.c \ shell-js.cpp \
$(NULL) $(NULL)
libgnome_shell_js_la_LIBADD = \ libgnome_shell_js_la_LIBADD = \

View File

@ -29,8 +29,6 @@
#include "shell-perf-log.h" #include "shell-perf-log.h"
#include "st.h" #include "st.h"
#include <jsapi.h>
extern GType gnome_shell_plugin_get_type (void); extern GType gnome_shell_plugin_get_type (void);
#define SHELL_DBUS_SERVICE "org.gnome.Shell" #define SHELL_DBUS_SERVICE "org.gnome.Shell"

View File

@ -12,9 +12,9 @@ G_BEGIN_DECLS
ShellApp* _shell_app_new_for_window (MetaWindow *window); ShellApp* _shell_app_new_for_window (MetaWindow *window);
ShellApp* _shell_app_new (GMenuTreeEntry *entry); ShellApp* _shell_app_new (GDesktopAppInfo *info);
void _shell_app_set_entry (ShellApp *app, GMenuTreeEntry *entry); void _shell_app_set_app_info (ShellApp *app, GDesktopAppInfo *info);
void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence); void _shell_app_handle_startup_sequence (ShellApp *app, SnStartupSequence *sequence);

View File

@ -38,18 +38,12 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
struct _ShellAppSystemPrivate { struct _ShellAppSystemPrivate {
GMenuTree *apps_tree;
GHashTable *running_apps; GHashTable *running_apps;
GHashTable *visible_id_to_app;
GHashTable *id_to_app; GHashTable *id_to_app;
GHashTable *startup_wm_class_to_app; GHashTable *startup_wm_class_to_id;
GSList *known_vendor_prefixes;
}; };
static void shell_app_system_finalize (GObject *object); static void shell_app_system_finalize (GObject *object);
static void on_apps_tree_changed_cb (GMenuTree *tree, gpointer user_data);
G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT); G_DEFINE_TYPE(ShellAppSystem, shell_app_system, G_TYPE_OBJECT);
@ -77,10 +71,45 @@ static void shell_app_system_class_init(ShellAppSystemClass *klass)
g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate)); g_type_class_add_private (gobject_class, sizeof (ShellAppSystemPrivate));
} }
static void
scan_startup_wm_class_to_id (ShellAppSystem *self)
{
ShellAppSystemPrivate *priv = self->priv;
GList *apps, *l;
g_hash_table_remove_all (priv->startup_wm_class_to_id);
apps = g_app_info_get_all ();
for (l = apps; l != NULL; l = l->next)
{
GAppInfo *info = l->data;
const char *startup_wm_class, *id;
id = g_app_info_get_id (info);
startup_wm_class = g_desktop_app_info_get_startup_wm_class (G_DESKTOP_APP_INFO (info));
if (startup_wm_class != NULL)
g_hash_table_insert (priv->startup_wm_class_to_id, (char *) startup_wm_class, (char *) id);
}
g_list_free_full (apps, g_object_unref);
}
static void
installed_changed (GAppInfoMonitor *monitor,
gpointer user_data)
{
ShellAppSystem *self = user_data;
scan_startup_wm_class_to_id (self);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0, NULL);
}
static void static void
shell_app_system_init (ShellAppSystem *self) shell_app_system_init (ShellAppSystem *self)
{ {
ShellAppSystemPrivate *priv; ShellAppSystemPrivate *priv;
GAppInfoMonitor *monitor;
self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self, self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
SHELL_TYPE_APP_SYSTEM, SHELL_TYPE_APP_SYSTEM,
@ -91,19 +120,11 @@ shell_app_system_init (ShellAppSystem *self)
NULL, NULL,
(GDestroyNotify)g_object_unref); (GDestroyNotify)g_object_unref);
/* All the objects in this hash table are owned by id_to_app */ priv->startup_wm_class_to_id = g_hash_table_new (g_str_hash, g_str_equal);
priv->visible_id_to_app = g_hash_table_new (g_str_hash, g_str_equal);
priv->startup_wm_class_to_app = g_hash_table_new_full (g_str_hash, g_str_equal, monitor = g_app_info_monitor_get ();
NULL, g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
(GDestroyNotify)g_object_unref); installed_changed (monitor, self);
/* We want to track NoDisplay apps, so we add INCLUDE_NODISPLAY. We'll
* filter NoDisplay apps out when showing them to the user. */
priv->apps_tree = gmenu_tree_new ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
g_signal_connect (priv->apps_tree, "changed", G_CALLBACK (on_apps_tree_changed_cb), self);
on_apps_tree_changed_cb (priv->apps_tree, self);
} }
static void static void
@ -112,313 +133,13 @@ shell_app_system_finalize (GObject *object)
ShellAppSystem *self = SHELL_APP_SYSTEM (object); ShellAppSystem *self = SHELL_APP_SYSTEM (object);
ShellAppSystemPrivate *priv = self->priv; ShellAppSystemPrivate *priv = self->priv;
g_object_unref (priv->apps_tree);
g_hash_table_destroy (priv->running_apps); g_hash_table_destroy (priv->running_apps);
g_hash_table_destroy (priv->id_to_app); g_hash_table_destroy (priv->id_to_app);
g_hash_table_destroy (priv->visible_id_to_app); g_hash_table_destroy (priv->startup_wm_class_to_id);
g_hash_table_destroy (priv->startup_wm_class_to_app);
g_slist_free_full (priv->known_vendor_prefixes, g_free);
priv->known_vendor_prefixes = NULL;
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object); G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
} }
static char *
get_prefix_for_entry (GMenuTreeEntry *entry)
{
char *prefix = NULL, *file_prefix = NULL;
const char *id;
GFile *file;
char *name;
int i = 0;
id = gmenu_tree_entry_get_desktop_file_id (entry);
file = g_file_new_for_path (gmenu_tree_entry_get_desktop_file_path (entry));
name = g_file_get_basename (file);
if (!name)
{
g_object_unref (file);
return NULL;
}
for (i = 0; vendor_prefixes[i]; i++)
{
if (g_str_has_prefix (name, vendor_prefixes[i]))
{
file_prefix = g_strdup (vendor_prefixes[i]);
break;
}
}
while (strcmp (name, id) != 0)
{
char *t;
char *pname;
GFile *parent = g_file_get_parent (file);
if (!parent)
{
g_warn_if_reached ();
break;
}
pname = g_file_get_basename (parent);
if (!pname)
{
g_object_unref (parent);
break;
}
if (!g_strstr_len (id, -1, pname))
{
/* handle <LegacyDir prefix="..."> */
char *t;
size_t name_len = strlen (name);
size_t id_len = strlen (id);
char *t_id = g_strdup (id);
t_id[id_len - name_len] = '\0';
t = g_strdup(t_id);
g_free (prefix);
g_free (t_id);
g_free (name);
name = g_strdup (id);
prefix = t;
g_object_unref (file);
file = parent;
g_free (pname);
g_free (file_prefix);
file_prefix = NULL;
break;
}
t = g_strconcat (pname, "-", name, NULL);
g_free (name);
name = t;
t = g_strconcat (pname, "-", prefix, NULL);
g_free (prefix);
prefix = t;
g_object_unref (file);
file = parent;
g_free (pname);
}
if (file)
g_object_unref (file);
if (strcmp (name, id) == 0)
{
g_free (name);
if (file_prefix && !prefix)
return file_prefix;
if (file_prefix)
{
char *t = g_strconcat (prefix, "-", file_prefix, NULL);
g_free (prefix);
g_free (file_prefix);
prefix = t;
}
return prefix;
}
g_free (name);
g_free (prefix);
g_free (file_prefix);
g_return_val_if_reached (NULL);
}
static void
get_flattened_entries_recurse (GMenuTreeDirectory *dir,
GHashTable *entry_set)
{
GMenuTreeIter *iter = gmenu_tree_directory_iter (dir);
GMenuTreeItemType next_type;
while ((next_type = gmenu_tree_iter_next (iter)) != GMENU_TREE_ITEM_INVALID)
{
gpointer item = NULL;
switch (next_type)
{
case GMENU_TREE_ITEM_ENTRY:
{
GMenuTreeEntry *entry;
item = entry = gmenu_tree_iter_get_entry (iter);
/* Key is owned by entry */
g_hash_table_replace (entry_set,
(char*)gmenu_tree_entry_get_desktop_file_id (entry),
gmenu_tree_item_ref (entry));
}
break;
case GMENU_TREE_ITEM_DIRECTORY:
{
item = gmenu_tree_iter_get_directory (iter);
get_flattened_entries_recurse ((GMenuTreeDirectory*)item, entry_set);
}
break;
default:
break;
}
if (item != NULL)
gmenu_tree_item_unref (item);
}
gmenu_tree_iter_unref (iter);
}
static GHashTable *
get_flattened_entries_from_tree (GMenuTree *tree)
{
GHashTable *table;
GMenuTreeDirectory *root;
table = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) NULL,
(GDestroyNotify) gmenu_tree_item_unref);
root = gmenu_tree_get_root_directory (tree);
if (root != NULL)
get_flattened_entries_recurse (root, table);
gmenu_tree_item_unref (root);
return table;
}
static void
on_apps_tree_changed_cb (GMenuTree *tree,
gpointer user_data)
{
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
GError *error = NULL;
GHashTable *new_apps;
GHashTableIter iter;
gpointer key, value;
g_assert (tree == self->priv->apps_tree);
g_hash_table_remove_all (self->priv->visible_id_to_app);
g_slist_free_full (self->priv->known_vendor_prefixes, g_free);
self->priv->known_vendor_prefixes = NULL;
if (!gmenu_tree_load_sync (self->priv->apps_tree, &error))
{
if (error)
{
g_warning ("Failed to load apps: %s", error->message);
g_error_free (error);
}
else
{
g_warning ("Failed to load apps");
}
return;
}
new_apps = get_flattened_entries_from_tree (self->priv->apps_tree);
g_hash_table_iter_init (&iter, new_apps);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *id = key;
GMenuTreeEntry *entry = value;
GMenuTreeEntry *old_entry;
char *prefix;
ShellApp *app;
GDesktopAppInfo *info;
const char *startup_wm_class;
prefix = get_prefix_for_entry (entry);
if (prefix != NULL
&& !g_slist_find_custom (self->priv->known_vendor_prefixes, prefix,
(GCompareFunc)g_strcmp0))
self->priv->known_vendor_prefixes = g_slist_append (self->priv->known_vendor_prefixes,
prefix);
else
g_free (prefix);
app = g_hash_table_lookup (self->priv->id_to_app, id);
if (app != NULL)
{
/* We hold a reference to the original entry temporarily,
* because otherwise the hash table would be referencing
* potentially free'd memory until we replace it below with
* the new data.
*/
old_entry = shell_app_get_tree_entry (app);
gmenu_tree_item_ref (old_entry);
_shell_app_set_entry (app, entry);
g_object_ref (app); /* Extra ref, removed in _replace below */
}
else
{
old_entry = NULL;
app = _shell_app_new (entry);
}
/* Note that "id" is owned by app->entry. Since we're always
* setting a new entry, even if the app already exists in the
* hash table we need to replace the key so that the new id
* string is pointed to.
*/
g_hash_table_replace (self->priv->id_to_app, (char*)id, app);
if (!gmenu_tree_entry_get_is_nodisplay_recurse (entry))
g_hash_table_replace (self->priv->visible_id_to_app, (char*)id, app);
if (old_entry)
{
GDesktopAppInfo *old_info;
const gchar *old_startup_wm_class;
old_info = gmenu_tree_entry_get_app_info (old_entry);
old_startup_wm_class = g_desktop_app_info_get_startup_wm_class (old_info);
if (old_startup_wm_class)
g_hash_table_remove (self->priv->startup_wm_class_to_app, old_startup_wm_class);
}
info = gmenu_tree_entry_get_app_info (entry);
startup_wm_class = g_desktop_app_info_get_startup_wm_class (info);
if (startup_wm_class)
g_hash_table_replace (self->priv->startup_wm_class_to_app,
(char*)startup_wm_class, g_object_ref (app));
if (old_entry)
gmenu_tree_item_unref (old_entry);
}
/* Now iterate over the apps again; we need to unreference any apps
* which have been removed. The JS code may still be holding a
* reference; that's fine.
*/
g_hash_table_iter_init (&iter, self->priv->id_to_app);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *id = key;
if (!g_hash_table_lookup (new_apps, id))
g_hash_table_iter_remove (&iter);
}
g_hash_table_destroy (new_apps);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
}
/**
* shell_app_system_get_tree:
*
* Return Value: (transfer none): The #GMenuTree for apps
*/
GMenuTree *
shell_app_system_get_tree (ShellAppSystem *self)
{
return self->priv->apps_tree;
}
/** /**
* shell_app_system_get_default: * shell_app_system_get_default:
* *
@ -446,61 +167,21 @@ ShellApp *
shell_app_system_lookup_app (ShellAppSystem *self, shell_app_system_lookup_app (ShellAppSystem *self,
const char *id) const char *id)
{ {
return g_hash_table_lookup (self->priv->id_to_app, id); ShellAppSystemPrivate *priv = self->priv;
}
/**
* shell_app_system_lookup_app_by_tree_entry:
* @system: a #ShellAppSystem
* @entry: a #GMenuTreeEntry
*
* Find a #ShellApp corresponding to a #GMenuTreeEntry.
*
* Return value: (transfer none): The #ShellApp for @entry, or %NULL if none
*/
ShellApp *
shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *self,
GMenuTreeEntry *entry)
{
/* If we looked up directly in ->entry_to_app, we'd lose the
* override of running apps. Thus, indirect through the id.
*/
return shell_app_system_lookup_app (self, gmenu_tree_entry_get_desktop_file_id (entry));
}
/**
* shell_app_system_lookup_app_for_path:
* @system: a #ShellAppSystem
* @desktop_path: (type utf8): UTF-8 encoded absolute file name
*
* Find or create a #ShellApp corresponding to a given absolute file
* name which must be in the standard paths (XDG_DATA_DIRS). For
* files outside the datadirs, this function returns %NULL.
*
* Return value: (transfer none): The #ShellApp for id, or %NULL if none
*/
ShellApp *
shell_app_system_lookup_app_for_path (ShellAppSystem *system,
const char *desktop_path)
{
const char *basename;
const char *app_path;
ShellApp *app; ShellApp *app;
GDesktopAppInfo *info;
basename = g_strrstr (desktop_path, "/"); app = g_hash_table_lookup (priv->id_to_app, id);
if (basename) if (app)
basename += 1; return app;
else
basename = desktop_path;
app = shell_app_system_lookup_app (system, basename); info = g_desktop_app_info_new (id);
if (!app) if (!info)
return NULL;
app_path = g_desktop_app_info_get_filename (shell_app_get_app_info (app));
if (strcmp (desktop_path, app_path) != 0)
return NULL; return NULL;
app = _shell_app_new (info);
g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
g_object_unref (info);
return app; return app;
} }
@ -520,15 +201,15 @@ shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
const char *name) const char *name)
{ {
ShellApp *result; ShellApp *result;
GSList *prefix; const char *const *prefix;
result = shell_app_system_lookup_app (system, name); result = shell_app_system_lookup_app (system, name);
if (result != NULL) if (result != NULL)
return result; return result;
for (prefix = system->priv->known_vendor_prefixes; prefix; prefix = g_slist_next (prefix)) for (prefix = vendor_prefixes; *prefix != NULL; prefix++)
{ {
char *tmpid = g_strconcat ((char*)prefix->data, name, NULL); char *tmpid = g_strconcat (*prefix, name, NULL);
result = shell_app_system_lookup_app (system, tmpid); result = shell_app_system_lookup_app (system, tmpid);
g_free (tmpid); g_free (tmpid);
if (result != NULL) if (result != NULL)
@ -603,10 +284,16 @@ ShellApp *
shell_app_system_lookup_startup_wmclass (ShellAppSystem *system, shell_app_system_lookup_startup_wmclass (ShellAppSystem *system,
const char *wmclass) const char *wmclass)
{ {
const char *id;
if (wmclass == NULL) if (wmclass == NULL)
return NULL; return NULL;
return g_hash_table_lookup (system->priv->startup_wm_class_to_app, wmclass); id = g_hash_table_lookup (system->priv->startup_wm_class_to_id, wmclass);
if (id == NULL)
return NULL;
return shell_app_system_lookup_app (system, id);
} }
void void
@ -681,13 +368,22 @@ sort_and_concat_results (ShellAppSystem *system,
GSList *prefix_matches, GSList *prefix_matches,
GSList *substring_matches) GSList *substring_matches)
{ {
GSList *matches = NULL;
GSList *l;
prefix_matches = g_slist_sort_with_data (prefix_matches, prefix_matches = g_slist_sort_with_data (prefix_matches,
compare_apps_by_usage, compare_apps_by_usage,
system); system);
substring_matches = g_slist_sort_with_data (substring_matches, substring_matches = g_slist_sort_with_data (substring_matches,
compare_apps_by_usage, compare_apps_by_usage,
system); system);
return g_slist_concat (prefix_matches, substring_matches);
for (l = substring_matches; l != NULL; l = l->next)
matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data)));
for (l = prefix_matches; l != NULL; l = l->next)
matches = g_slist_prepend (matches, (char *) shell_app_get_id (SHELL_APP (l->data)));
return g_slist_reverse (matches);
} }
/** /**
@ -734,7 +430,6 @@ search_tree (ShellAppSystem *self,
g_slist_free_full (normalized_terms, g_free); g_slist_free_full (normalized_terms, g_free);
return sort_and_concat_results (self, prefix_results, substring_results); return sort_and_concat_results (self, prefix_results, substring_results);
} }
/** /**
@ -744,26 +439,26 @@ search_tree (ShellAppSystem *self,
* *
* Search through applications for the given search terms. * Search through applications for the given search terms.
* *
* Returns: (transfer container) (element-type ShellApp): List of applications * Returns: (transfer container) (element-type utf8): List of applications
*/ */
GSList * GSList *
shell_app_system_initial_search (ShellAppSystem *self, shell_app_system_initial_search (ShellAppSystem *self,
GSList *terms) GSList *terms)
{ {
return search_tree (self, terms, self->priv->visible_id_to_app); return search_tree (self, terms, self->priv->id_to_app);
} }
/** /**
* shell_app_system_subsearch: * shell_app_system_subsearch:
* @system: A #ShellAppSystem * @system: A #ShellAppSystem
* @previous_results: (element-type ShellApp): List of previous results * @previous_results: (element-type utf8): List of previous results
* @terms: (element-type utf8): List of terms, logical AND * @terms: (element-type utf8): List of terms, logical AND
* *
* Search through a previous result set; for more information, see * Search through a previous result set; for more information, see
* js/ui/search.js. Note that returned strings are only valid until * js/ui/search.js. Note that returned strings are only valid until
* a return to the main loop. * a return to the main loop.
* *
* Returns: (transfer container) (element-type ShellApp): List of application identifiers * Returns: (transfer container) (element-type utf8): List of application identifiers
*/ */
GSList * GSList *
shell_app_system_subsearch (ShellAppSystem *system, shell_app_system_subsearch (ShellAppSystem *system,
@ -779,8 +474,8 @@ shell_app_system_subsearch (ShellAppSystem *system,
for (iter = previous_results; iter; iter = iter->next) for (iter = previous_results; iter; iter = iter->next)
{ {
ShellApp *app = iter->data; ShellApp *app = shell_app_system_lookup_app (system, iter->data);
_shell_app_do_match (app, normalized_terms, _shell_app_do_match (app, normalized_terms,
&prefix_results, &prefix_results,
&substring_results); &substring_results);

View File

@ -5,8 +5,6 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <meta/window.h> #include <meta/window.h>
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
#include <gmenu-tree.h>
#include "shell-app.h" #include "shell-app.h"
@ -39,14 +37,8 @@ struct _ShellAppSystemClass
GType shell_app_system_get_type (void) G_GNUC_CONST; GType shell_app_system_get_type (void) G_GNUC_CONST;
ShellAppSystem *shell_app_system_get_default (void); ShellAppSystem *shell_app_system_get_default (void);
GMenuTree *shell_app_system_get_tree (ShellAppSystem *system);
ShellApp *shell_app_system_lookup_app (ShellAppSystem *system, ShellApp *shell_app_system_lookup_app (ShellAppSystem *system,
const char *id); const char *id);
ShellApp *shell_app_system_lookup_app_by_tree_entry (ShellAppSystem *system,
GMenuTreeEntry *entry);
ShellApp *shell_app_system_lookup_app_for_path (ShellAppSystem *system,
const char *desktop_path);
ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system, ShellApp *shell_app_system_lookup_heuristic_basename (ShellAppSystem *system,
const char *id); const char *id);

View File

@ -17,6 +17,12 @@
#include "st.h" #include "st.h"
#include "gtkactionmuxer.h" #include "gtkactionmuxer.h"
#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
#include <errno.h>
#include <unistd.h>
#endif
typedef enum { typedef enum {
MATCH_NONE, MATCH_NONE,
MATCH_SUBSTRING, /* Not prefix, substring */ MATCH_SUBSTRING, /* Not prefix, substring */
@ -37,7 +43,7 @@ typedef struct {
GSList *windows; GSList *windows;
/* Whether or not we need to resort the windows; this is done on demand */ /* Whether or not we need to resort the windows; this is done on demand */
gboolean window_sort_stale : 1; guint window_sort_stale : 1;
/* DBus property notification subscription */ /* DBus property notification subscription */
guint properties_changed_id : 1; guint properties_changed_id : 1;
@ -53,7 +59,7 @@ typedef struct {
* SECTION:shell-app * SECTION:shell-app
* @short_description: Object representing an application * @short_description: Object representing an application
* *
* This object wraps a #GMenuTreeEntry, providing methods and signals * This object wraps a #GDesktopAppInfo, providing methods and signals
* primarily useful for running applications. * primarily useful for running applications.
*/ */
struct _ShellApp struct _ShellApp
@ -64,7 +70,7 @@ struct _ShellApp
ShellAppState state; ShellAppState state;
GMenuTreeEntry *entry; /* If NULL, this app is backed by one or more GDesktopAppInfo *info; /* If NULL, this app is backed by one or more
* MetaWindow. For purposes of app title * MetaWindow. For purposes of app title
* etc., we use the first window added, * etc., we use the first window added,
* because it's most likely to be what we * because it's most likely to be what we
@ -137,15 +143,15 @@ shell_app_get_property (GObject *gobject,
const char * const char *
shell_app_get_id (ShellApp *app) shell_app_get_id (ShellApp *app)
{ {
if (app->entry) if (app->info)
return gmenu_tree_entry_get_desktop_file_id (app->entry); return g_app_info_get_id (G_APP_INFO (app->info));
return app->window_id_string; return app->window_id_string;
} }
static MetaWindow * static MetaWindow *
window_backed_app_get_window (ShellApp *app) window_backed_app_get_window (ShellApp *app)
{ {
g_assert (app->entry == NULL); g_assert (app->info == NULL);
g_assert (app->running_state); g_assert (app->running_state);
g_assert (app->running_state->windows); g_assert (app->running_state->windows);
return app->running_state->windows->data; return app->running_state->windows->data;
@ -194,10 +200,10 @@ shell_app_create_icon_texture (ShellApp *app,
ret = NULL; ret = NULL;
if (app->entry == NULL) if (app->info == NULL)
return window_backed_app_get_icon (app, size); return window_backed_app_get_icon (app, size);
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry))); icon = g_app_info_get_icon (G_APP_INFO (app->info));
if (icon != NULL) if (icon != NULL)
ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size); ret = st_texture_cache_load_gicon (st_texture_cache_get_default (), NULL, icon, size);
@ -245,7 +251,7 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
info = NULL; info = NULL;
icon = g_app_info_get_icon (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry))); icon = g_app_info_get_icon (G_APP_INFO (app->info));
if (icon != NULL) if (icon != NULL)
{ {
info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (), info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
@ -347,7 +353,7 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
* property tracking bits, and this helps us visually distinguish * property tracking bits, and this helps us visually distinguish
* app-tracked from not. * app-tracked from not.
*/ */
if (!app->entry) if (!app->info)
return window_backed_app_get_icon (app, size); return window_backed_app_get_icon (app, size);
/* Use icon: prefix so that we get evicted from the cache on /* Use icon: prefix so that we get evicted from the cache on
@ -384,8 +390,8 @@ shell_app_get_faded_icon (ShellApp *app, int size, ClutterTextDirection directio
const char * const char *
shell_app_get_name (ShellApp *app) shell_app_get_name (ShellApp *app)
{ {
if (app->entry) if (app->info)
return g_app_info_get_name (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry))); return g_app_info_get_name (G_APP_INFO (app->info));
else else
{ {
MetaWindow *window = window_backed_app_get_window (app); MetaWindow *window = window_backed_app_get_window (app);
@ -401,8 +407,8 @@ shell_app_get_name (ShellApp *app)
const char * const char *
shell_app_get_description (ShellApp *app) shell_app_get_description (ShellApp *app)
{ {
if (app->entry) if (app->info)
return g_app_info_get_description (G_APP_INFO (gmenu_tree_entry_get_app_info (app->entry))); return g_app_info_get_description (G_APP_INFO (app->info));
else else
return NULL; return NULL;
} }
@ -417,7 +423,7 @@ shell_app_get_description (ShellApp *app)
gboolean gboolean
shell_app_is_window_backed (ShellApp *app) shell_app_is_window_backed (ShellApp *app)
{ {
return app->entry == NULL; return app->info == NULL;
} }
typedef struct { typedef struct {
@ -633,12 +639,7 @@ shell_app_activate_full (ShellApp *app,
case SHELL_APP_STATE_STOPPED: case SHELL_APP_STATE_STOPPED:
{ {
GError *error = NULL; GError *error = NULL;
if (!shell_app_launch (app, if (!shell_app_launch (app, timestamp, workspace, &error))
timestamp,
NULL,
workspace,
NULL,
&error))
{ {
char *msg; char *msg;
msg = g_strdup_printf (_("Failed to launch '%s'"), shell_app_get_name (app)); msg = g_strdup_printf (_("Failed to launch '%s'"), shell_app_get_name (app));
@ -670,7 +671,7 @@ void
shell_app_open_new_window (ShellApp *app, shell_app_open_new_window (ShellApp *app,
int workspace) int workspace)
{ {
g_return_if_fail (app->entry != NULL); g_return_if_fail (app->info != NULL);
/* Here we just always launch the application again, even if we know /* Here we just always launch the application again, even if we know
* it was already running. For most applications this * it was already running. For most applications this
@ -680,12 +681,7 @@ shell_app_open_new_window (ShellApp *app,
* as say Pidgin. Ideally, we have the application express to us * as say Pidgin. Ideally, we have the application express to us
* that it supports an explicit new-window action. * that it supports an explicit new-window action.
*/ */
shell_app_launch (app, shell_app_launch (app, 0, workspace, NULL);
0,
NULL,
workspace,
NULL,
NULL);
} }
/** /**
@ -865,25 +861,24 @@ _shell_app_new_for_window (MetaWindow *window)
} }
ShellApp * ShellApp *
_shell_app_new (GMenuTreeEntry *info) _shell_app_new (GDesktopAppInfo *info)
{ {
ShellApp *app; ShellApp *app;
app = g_object_new (SHELL_TYPE_APP, NULL); app = g_object_new (SHELL_TYPE_APP, NULL);
_shell_app_set_entry (app, info); _shell_app_set_app_info (app, info);
return app; return app;
} }
void void
_shell_app_set_entry (ShellApp *app, _shell_app_set_app_info (ShellApp *app,
GMenuTreeEntry *entry) GDesktopAppInfo *info)
{ {
if (app->entry != NULL) g_clear_object (&app->info);
gmenu_tree_item_unref (app->entry); app->info = g_object_ref (info);
app->entry = gmenu_tree_item_ref (entry);
if (app->name_collation_key != NULL) if (app->name_collation_key != NULL)
g_free (app->name_collation_key); g_free (app->name_collation_key);
app->name_collation_key = g_utf8_collate_key (shell_app_get_name (app), -1); app->name_collation_key = g_utf8_collate_key (shell_app_get_name (app), -1);
@ -1172,40 +1167,50 @@ _gather_pid_callback (GDesktopAppInfo *gapp,
app); app);
} }
#ifdef HAVE_SYSTEMD
/* This sets up the launched application to log to the journal
* using its own identifier, instead of just "gnome-session".
*/
static void
app_child_setup (gpointer user_data)
{
const char *appid = user_data;
int res;
int journalfd = sd_journal_stream_fd (appid, LOG_INFO, FALSE);
if (journalfd >= 0)
{
do
res = dup2 (journalfd, 1);
while (G_UNLIKELY (res == -1 && errno == EINTR));
do
res = dup2 (journalfd, 2);
while (G_UNLIKELY (res == -1 && errno == EINTR));
(void) close (journalfd);
}
}
#endif
/** /**
* shell_app_launch: * shell_app_launch:
* @timestamp: Event timestamp, or 0 for current event timestamp * @timestamp: Event timestamp, or 0 for current event timestamp
* @uris: (element-type utf8): List of uris to pass to application
* @workspace: Start on this workspace, or -1 for default * @workspace: Start on this workspace, or -1 for default
* @startup_id: (out): Returned startup notification ID, or %NULL if none
* @error: A #GError * @error: A #GError
*/ */
gboolean gboolean
shell_app_launch (ShellApp *app, shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
GList *uris,
int workspace, int workspace,
char **startup_id,
GError **error) GError **error)
{ {
GDesktopAppInfo *gapp;
GdkAppLaunchContext *context; GdkAppLaunchContext *context;
gboolean ret; gboolean ret;
ShellGlobal *global; ShellGlobal *global;
MetaScreen *screen; MetaScreen *screen;
GdkDisplay *gdisplay; GdkDisplay *gdisplay;
if (startup_id) if (app->info == NULL)
*startup_id = NULL;
if (app->entry == NULL)
{ {
MetaWindow *window = window_backed_app_get_window (app); MetaWindow *window = window_backed_app_get_window (app);
/* We can't pass URIs into a window; shouldn't hit this
* code path. If we do, fix the caller to disallow it.
*/
g_return_val_if_fail (uris == NULL, TRUE);
meta_window_activate (window, timestamp); meta_window_activate (window, timestamp);
return TRUE; return TRUE;
} }
@ -1224,11 +1229,14 @@ shell_app_launch (ShellApp *app,
gdk_app_launch_context_set_timestamp (context, timestamp); gdk_app_launch_context_set_timestamp (context, timestamp);
gdk_app_launch_context_set_desktop (context, workspace); gdk_app_launch_context_set_desktop (context, workspace);
gapp = gmenu_tree_entry_get_app_info (app->entry); ret = g_desktop_app_info_launch_uris_as_manager (app->info, NULL,
ret = g_desktop_app_info_launch_uris_as_manager (gapp, uris,
G_APP_LAUNCH_CONTEXT (context), G_APP_LAUNCH_CONTEXT (context),
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
#ifdef HAVE_SYSTEMD
app_child_setup, (gpointer)shell_app_get_id (app),
#else
NULL, NULL, NULL, NULL,
#endif
_gather_pid_callback, app, _gather_pid_callback, app,
error); error);
g_object_unref (context); g_object_unref (context);
@ -1245,21 +1253,7 @@ shell_app_launch (ShellApp *app,
GDesktopAppInfo * GDesktopAppInfo *
shell_app_get_app_info (ShellApp *app) shell_app_get_app_info (ShellApp *app)
{ {
if (app->entry) return app->info;
return gmenu_tree_entry_get_app_info (app->entry);
return NULL;
}
/**
* shell_app_get_tree_entry:
* @app: a #ShellApp
*
* Returns: (transfer none): The #GMenuTreeEntry for this app, or %NULL if backed by a window
*/
GMenuTreeEntry *
shell_app_get_tree_entry (ShellApp *app)
{
return app->entry;
} }
static void static void
@ -1374,24 +1368,22 @@ shell_app_init_search_data (ShellApp *app)
const char *exec; const char *exec;
const char * const *keywords; const char * const *keywords;
char *normalized_exec; char *normalized_exec;
GDesktopAppInfo *appinfo;
appinfo = gmenu_tree_entry_get_app_info (app->entry); name = g_app_info_get_name (G_APP_INFO (app->info));
name = g_app_info_get_name (G_APP_INFO (appinfo));
app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name); app->casefolded_name = shell_util_normalize_casefold_and_unaccent (name);
generic_name = g_desktop_app_info_get_generic_name (appinfo); generic_name = g_desktop_app_info_get_generic_name (app->info);
if (generic_name) if (generic_name)
app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name); app->casefolded_generic_name = shell_util_normalize_casefold_and_unaccent (generic_name);
else else
app->casefolded_generic_name = NULL; app->casefolded_generic_name = NULL;
exec = g_app_info_get_executable (G_APP_INFO (appinfo)); exec = g_app_info_get_executable (G_APP_INFO (app->info));
normalized_exec = shell_util_normalize_casefold_and_unaccent (exec); normalized_exec = shell_util_normalize_casefold_and_unaccent (exec);
app->casefolded_exec = trim_exec_line (normalized_exec); app->casefolded_exec = trim_exec_line (normalized_exec);
g_free (normalized_exec); g_free (normalized_exec);
keywords = g_desktop_app_info_get_keywords (appinfo); keywords = g_desktop_app_info_get_keywords (app->info);
if (keywords) if (keywords)
{ {
@ -1512,16 +1504,14 @@ _shell_app_do_match (ShellApp *app,
GSList **substring_results) GSList **substring_results)
{ {
ShellAppSearchMatch match; ShellAppSearchMatch match;
GAppInfo *appinfo;
g_assert (app != NULL); g_assert (app != NULL);
/* Skip window-backed apps */ /* Skip window-backed apps */
appinfo = (GAppInfo*)shell_app_get_app_info (app); if (app->info == NULL)
if (appinfo == NULL)
return; return;
/* Skip not-visible apps */ /* Skip not-visible apps */
if (!g_app_info_should_show (appinfo)) if (!g_app_info_should_show (G_APP_INFO (app->info)))
return; return;
match = _shell_app_match_search_terms (app, terms); match = _shell_app_match_search_terms (app, terms);
@ -1550,11 +1540,7 @@ shell_app_dispose (GObject *object)
{ {
ShellApp *app = SHELL_APP (object); ShellApp *app = SHELL_APP (object);
if (app->entry) g_clear_object (&app->info);
{
gmenu_tree_item_unref (app->entry);
app->entry = NULL;
}
if (app->running_state) if (app->running_state)
{ {

View File

@ -4,9 +4,8 @@
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <gio/gdesktopappinfo.h>
#include <meta/window.h> #include <meta/window.h>
#define GMENU_I_KNOW_THIS_IS_UNSTABLE
#include <gmenu-tree.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -39,7 +38,6 @@ GType shell_app_get_type (void) G_GNUC_CONST;
const char *shell_app_get_id (ShellApp *app); const char *shell_app_get_id (ShellApp *app);
GMenuTreeEntry *shell_app_get_tree_entry (ShellApp *app);
GDesktopAppInfo *shell_app_get_app_info (ShellApp *app); GDesktopAppInfo *shell_app_get_app_info (ShellApp *app);
ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size); ClutterActor *shell_app_create_icon_texture (ShellApp *app, int size);
@ -73,9 +71,7 @@ gboolean shell_app_is_on_workspace (ShellApp *app, MetaWorkspace *workspace);
gboolean shell_app_launch (ShellApp *app, gboolean shell_app_launch (ShellApp *app,
guint timestamp, guint timestamp,
GList *uris,
int workspace, int workspace,
char **startup_id,
GError **error); GError **error);
int shell_app_compare_by_name (ShellApp *app, ShellApp *other); int shell_app_compare_by_name (ShellApp *app, ShellApp *other);

View File

@ -22,7 +22,6 @@
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
#include <gdk/gdkx.h> #include <gdk/gdkx.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <gjs/gjs-module.h>
#include <girepository.h> #include <girepository.h>
#include <meta/display.h> #include <meta/display.h>
#include <meta/util.h> #include <meta/util.h>
@ -34,6 +33,11 @@
#include <malloc.h> #include <malloc.h>
#endif #endif
#ifdef __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#include "shell-enum-types.h" #include "shell-enum-types.h"
#include "shell-global-private.h" #include "shell-global-private.h"
#include "shell-perf-log.h" #include "shell-perf-log.h"
@ -80,10 +84,11 @@ struct _ShellGlobal {
const char *datadir; const char *datadir;
const char *imagedir; const char *imagedir;
const char *userdatadir; const char *userdatadir;
StFocusManager *focus_manager; GFile *userdatadir_path;
GFile *runtime_state_path; GFile *runtime_state_path;
StFocusManager *focus_manager;
guint work_count; guint work_count;
GSList *leisure_closures; GSList *leisure_closures;
guint leisure_function_id; guint leisure_function_id;
@ -252,6 +257,7 @@ shell_global_init (ShellGlobal *global)
/* Ensure config dir exists for later use */ /* Ensure config dir exists for later use */
global->userdatadir = g_build_filename (g_get_user_data_dir (), "gnome-shell", NULL); global->userdatadir = g_build_filename (g_get_user_data_dir (), "gnome-shell", NULL);
g_mkdir_with_parents (global->userdatadir, 0700); g_mkdir_with_parents (global->userdatadir, 0700);
global->userdatadir_path = g_file_new_for_path (global->userdatadir);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN #if G_BYTE_ORDER == G_LITTLE_ENDIAN
byteorder_string = "LE"; byteorder_string = "LE";
@ -282,9 +288,16 @@ shell_global_init (ShellGlobal *global)
NULL); NULL);
ca_context_open (global->sound_context); ca_context_open (global->sound_context);
if (!shell_js) if (shell_js)
shell_js = JSDIR; {
search_path = g_strsplit (shell_js, ":", -1); search_path = g_strsplit (shell_js, ":", -1);
}
else
{
search_path = g_malloc0 (2 * sizeof (char *));
search_path[0] = g_strdup ("resource:///org/gnome/shell");
}
global->js_context = g_object_new (GJS_TYPE_CONTEXT, global->js_context = g_object_new (GJS_TYPE_CONTEXT,
"search-path", search_path, "search-path", search_path,
"js-version", "1.8", "js-version", "1.8",
@ -306,6 +319,7 @@ shell_global_finalize (GObject *object)
the_object = NULL; the_object = NULL;
g_clear_object (&global->userdatadir_path);
g_clear_object (&global->runtime_state_path); g_clear_object (&global->runtime_state_path);
G_OBJECT_CLASS(shell_global_parent_class)->finalize (object); G_OBJECT_CLASS(shell_global_parent_class)->finalize (object);
@ -1100,20 +1114,30 @@ shell_global_reexec_self (ShellGlobal *global)
char *buf_p; char *buf_p;
char *buf_end; char *buf_end;
GError *error = NULL; GError *error = NULL;
/* Linux specific (I think, anyways). */ #if defined __linux__
if (!g_file_get_contents ("/proc/self/cmdline", &buf, &len, &error)) if (!g_file_get_contents ("/proc/self/cmdline", &buf, &len, &error))
{ {
g_warning ("failed to get /proc/self/cmdline: %s", error->message); g_warning ("failed to get /proc/self/cmdline: %s", error->message);
return; return;
} }
#elif defined __OpenBSD__
int pid = getpid();
int mib[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV };
if (sysctl(mib, G_N_ELEMENTS (mib), &buf, &len, NULL, 0) == -1) {
g_warning ("failed to get command line args: %d", errno);
return;
}
#else
return;
#endif
buf_end = buf+len; buf_end = buf+len;
arr = g_ptr_array_new (); arr = g_ptr_array_new ();
/* The cmdline file is NUL-separated */ /* The cmdline file is NUL-separated */
for (buf_p = buf; buf_p < buf_end; buf_p = buf_p + strlen (buf_p) + 1) for (buf_p = buf; buf_p < buf_end; buf_p = buf_p + strlen (buf_p) + 1)
g_ptr_array_add (arr, buf_p); g_ptr_array_add (arr, buf_p);
g_ptr_array_add (arr, NULL); g_ptr_array_add (arr, NULL);
/* Close all file descriptors other than stdin/stdout/stderr, otherwise /* Close all file descriptors other than stdin/stdout/stderr, otherwise
@ -1139,44 +1163,6 @@ shell_global_on_gc (GjsContext *context,
global->last_gc_end_time = g_get_monotonic_time (); global->last_gc_end_time = g_get_monotonic_time ();
} }
/**
* shell_global_get_memory_info:
* @global:
* @meminfo: (out caller-allocates): Output location for memory information
*
* Load process-global data about memory usage.
*/
void
shell_global_get_memory_info (ShellGlobal *global,
ShellMemoryInfo *meminfo)
{
JSContext *context;
gint64 now;
#ifdef HAVE_MALLINFO
{
struct mallinfo info = mallinfo ();
meminfo->glibc_uordblks = info.uordblks;
}
#else
meminfo->glibc_uordblks = 0;
#endif
context = gjs_context_get_native_context (global->js_context);
meminfo->js_bytes = JS_GetGCParameter (JS_GetRuntime (context), JSGC_BYTES);
meminfo->gjs_boxed = (unsigned int) gjs_counter_boxed.value;
meminfo->gjs_gobject = (unsigned int) gjs_counter_object.value;
meminfo->gjs_function = (unsigned int) gjs_counter_function.value;
meminfo->gjs_closure = (unsigned int) gjs_counter_closure.value;
now = g_get_monotonic_time ();
meminfo->last_gc_seconds_ago = (now - global->last_gc_end_time) / G_TIME_SPAN_SECOND;
}
/** /**
* shell_global_notify_error: * shell_global_notify_error:
* @global: a #ShellGlobal * @global: a #ShellGlobal
@ -1746,31 +1732,14 @@ shell_global_get_session_mode (ShellGlobal *global)
return global->session_mode; return global->session_mode;
} }
static GFile * static void
get_runtime_state_path (ShellGlobal *global, save_variant (GFile *dir,
const char *property_name) const char *property_name,
GVariant *variant)
{ {
return g_file_get_child (global->runtime_state_path, property_name); GFile *path = g_file_get_child (dir, property_name);
}
/** if (variant == NULL || g_variant_get_data (variant) == NULL)
* shell_global_set_runtime_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized runtime state.
*/
void
shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
GFile *path;
path = get_runtime_state_path (global, property_name);
if (variant == NULL)
(void) g_file_delete (path, NULL, NULL); (void) g_file_delete (path, NULL, NULL);
else else
{ {
@ -1783,29 +1752,17 @@ shell_global_set_runtime_state (ShellGlobal *global,
g_object_unref (path); g_object_unref (path);
} }
/** static GVariant *
* shell_global_get_runtime_state: load_variant (GFile *dir,
* @global: a #ShellGlobal const char *property_type,
* @property_type: Expected data type const char *property_name)
* @property_name: Name of the property
*
* The shell maintains "runtime" state which does not persist across
* logout or reboot.
*
* Returns: (transfer floating): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{ {
GVariant *res = NULL; GVariant *res = NULL;
GMappedFile *mfile; GMappedFile *mfile;
GFile *path; GFile *path = g_file_get_child (dir, property_name);
char *pathstr; char *pathstr;
GError *local_error = NULL; GError *local_error = NULL;
path = get_runtime_state_path (global, property_name);
pathstr = g_file_get_path (path); pathstr = g_file_get_path (path);
mfile = g_mapped_file_new (pathstr, FALSE, &local_error); mfile = g_mapped_file_new (pathstr, FALSE, &local_error);
if (!mfile) if (!mfile)
@ -1829,3 +1786,73 @@ shell_global_get_runtime_state (ShellGlobal *global,
return res; return res;
} }
/**
* shell_global_set_runtime_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized runtime state.
*/
void
shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
save_variant (global->runtime_state_path, property_name, variant);
}
/**
* shell_global_get_runtime_state:
* @global: a #ShellGlobal
* @property_type: Expected data type
* @property_name: Name of the property
*
* The shell maintains "runtime" state which does not persist across
* logout or reboot.
*
* Returns: (transfer floating): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{
return load_variant (global->runtime_state_path, property_type, property_name);
}
/**
* shell_global_set_persistent_state:
* @global: a #ShellGlobal
* @property_name: Name of the property
* @variant: (allow-none): A #GVariant, or %NULL to unset
*
* Change the value of serialized persistent state.
*/
void
shell_global_set_persistent_state (ShellGlobal *global,
const char *property_name,
GVariant *variant)
{
save_variant (global->userdatadir_path, property_name, variant);
}
/**
* shell_global_get_persistent_state:
* @global: a #ShellGlobal
* @property_type: Expected data type
* @property_name: Name of the property
*
* The shell maintains "persistent" state which will persist after
* logout or reboot.
*
* Returns: (transfer none): The value of a serialized property, or %NULL if none stored
*/
GVariant *
shell_global_get_persistent_state (ShellGlobal *global,
const char *property_type,
const char *property_name)
{
return load_variant (global->userdatadir_path, property_type, property_name);
}

View File

@ -69,10 +69,6 @@ typedef struct {
guint last_gc_seconds_ago; guint last_gc_seconds_ago;
} ShellMemoryInfo; } ShellMemoryInfo;
void shell_global_get_memory_info (ShellGlobal *global,
ShellMemoryInfo *meminfo);
/* Run-at-leisure API */ /* Run-at-leisure API */
void shell_global_begin_work (ShellGlobal *global); void shell_global_begin_work (ShellGlobal *global);
void shell_global_end_work (ShellGlobal *global); void shell_global_end_work (ShellGlobal *global);
@ -129,13 +125,19 @@ void shell_global_reexec_self (ShellGlobal *global);
const char * shell_global_get_session_mode (ShellGlobal *global); const char * shell_global_get_session_mode (ShellGlobal *global);
void shell_global_set_runtime_state (ShellGlobal *global, void shell_global_set_runtime_state (ShellGlobal *global,
const char *property_name, const char *property_name,
GVariant *variant); GVariant *variant);
GVariant * shell_global_get_runtime_state (ShellGlobal *global, GVariant * shell_global_get_runtime_state (ShellGlobal *global,
const char *property_type, const char *property_type,
const char *property_name); const char *property_name);
void shell_global_set_persistent_state (ShellGlobal *global,
const char *property_name,
GVariant *variant);
GVariant * shell_global_get_persistent_state (ShellGlobal *global,
const char *property_type,
const char *property_name);
G_END_DECLS G_END_DECLS

View File

@ -38,7 +38,7 @@ shell_js_add_extension_importer (const char *target_object_script,
* we should only ever have one context, so this * we should only ever have one context, so this
* should be alright. */ * should be alright. */
contexts = gjs_context_get_all (); contexts = gjs_context_get_all ();
context = gjs_context_get_native_context (contexts->data); context = (JSContext*) gjs_context_get_native_context ((GjsContext*)contexts->data);
g_list_free_full (contexts, g_object_unref); g_list_free_full (contexts, g_object_unref);
JS_BeginRequest (context); JS_BeginRequest (context);

View File

@ -844,6 +844,7 @@ ShellApp *
shell_startup_sequence_get_app (ShellStartupSequence *sequence) shell_startup_sequence_get_app (ShellStartupSequence *sequence)
{ {
const char *appid; const char *appid;
char *basename;
ShellAppSystem *appsys; ShellAppSystem *appsys;
ShellApp *app; ShellApp *app;
@ -851,8 +852,10 @@ shell_startup_sequence_get_app (ShellStartupSequence *sequence)
if (!appid) if (!appid)
return NULL; return NULL;
basename = g_path_get_basename (appid);
appsys = shell_app_system_get_default (); appsys = shell_app_system_get_default ();
app = shell_app_system_lookup_app_for_path (appsys, appid); app = shell_app_system_lookup_app (appsys, basename);
g_free (basename);
return app; return app;
} }

View File

@ -45,7 +45,7 @@ struct _StAdjustmentPrivate
{ {
/* Do not sanity-check values while constructing, /* Do not sanity-check values while constructing,
* not all properties may be set yet. */ * not all properties may be set yet. */
gboolean is_constructing : 1; guint is_constructing : 1;
gdouble lower; gdouble lower;
gdouble upper; gdouble upper;

View File

@ -98,8 +98,8 @@ struct _StScrollViewPrivate
StScrollViewFade *fade_effect; StScrollViewFade *fade_effect;
gboolean row_size_set : 1; guint row_size_set : 1;
gboolean column_size_set : 1; guint column_size_set : 1;
guint mouse_scroll : 1; guint mouse_scroll : 1;
guint overlay_scrollbars : 1; guint overlay_scrollbars : 1;
guint hscrollbar_visible : 1; guint hscrollbar_visible : 1;

View File

@ -45,10 +45,7 @@
#include "st-theme-node.h" #include "st-theme-node.h"
#include "st-theme-private.h" #include "st-theme-private.h"
static GObject *st_theme_constructor (GType type, static void st_theme_constructed (GObject *object);
guint n_construct_properties,
GObjectConstructParam *construct_properties);
static void st_theme_finalize (GObject *object); static void st_theme_finalize (GObject *object);
static void st_theme_set_property (GObject *object, static void st_theme_set_property (GObject *object,
guint prop_id, guint prop_id,
@ -114,7 +111,7 @@ st_theme_class_init (StThemeClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructor = st_theme_constructor; object_class->constructed = st_theme_constructed;
object_class->finalize = st_theme_finalize; object_class->finalize = st_theme_finalize;
object_class->set_property = st_theme_set_property; object_class->set_property = st_theme_set_property;
object_class->get_property = st_theme_get_property; object_class->get_property = st_theme_get_property;
@ -302,21 +299,15 @@ st_theme_get_custom_stylesheets (StTheme *theme)
return result; return result;
} }
static GObject * static void
st_theme_constructor (GType type, st_theme_constructed (GObject *object)
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{ {
GObject *object; StTheme *theme = ST_THEME (object);
StTheme *theme;
CRStyleSheet *application_stylesheet; CRStyleSheet *application_stylesheet;
CRStyleSheet *theme_stylesheet; CRStyleSheet *theme_stylesheet;
CRStyleSheet *default_stylesheet; CRStyleSheet *default_stylesheet;
object = (*G_OBJECT_CLASS (st_theme_parent_class)->constructor) (type, G_OBJECT_CLASS (st_theme_parent_class)->constructed (object);
n_construct_properties,
construct_properties);
theme = ST_THEME (object);
application_stylesheet = parse_stylesheet_nofail (theme->application_stylesheet); application_stylesheet = parse_stylesheet_nofail (theme->application_stylesheet);
theme_stylesheet = parse_stylesheet_nofail (theme->theme_stylesheet); theme_stylesheet = parse_stylesheet_nofail (theme->theme_stylesheet);
@ -332,8 +323,6 @@ st_theme_constructor (GType type,
insert_stylesheet (theme, theme->application_stylesheet, application_stylesheet); insert_stylesheet (theme, theme->application_stylesheet, application_stylesheet);
insert_stylesheet (theme, theme->theme_stylesheet, theme_stylesheet); insert_stylesheet (theme, theme->theme_stylesheet, theme_stylesheet);
insert_stylesheet (theme, theme->default_stylesheet, default_stylesheet); insert_stylesheet (theme, theme->default_stylesheet, default_stylesheet);
return object;
} }
static void static void

View File

@ -59,13 +59,12 @@ struct _StWidgetPrivate
StThemeNodeTransition *transition_animation; StThemeNodeTransition *transition_animation;
gboolean is_stylable : 1; guint is_style_dirty : 1;
gboolean is_style_dirty : 1; guint draw_bg_color : 1;
gboolean draw_bg_color : 1; guint draw_border_internal : 1;
gboolean draw_border_internal : 1; guint track_hover : 1;
gboolean track_hover : 1; guint hover : 1;
gboolean hover : 1; guint can_focus : 1;
gboolean can_focus : 1;
gulong texture_file_changed_id; gulong texture_file_changed_id;
@ -105,7 +104,6 @@ enum
PROP_PSEUDO_CLASS, PROP_PSEUDO_CLASS,
PROP_STYLE_CLASS, PROP_STYLE_CLASS,
PROP_STYLE, PROP_STYLE,
PROP_STYLABLE,
PROP_TRACK_HOVER, PROP_TRACK_HOVER,
PROP_HOVER, PROP_HOVER,
PROP_CAN_FOCUS, PROP_CAN_FOCUS,
@ -164,14 +162,6 @@ st_widget_set_property (GObject *gobject,
st_widget_set_style (actor, g_value_get_string (value)); st_widget_set_style (actor, g_value_get_string (value));
break; break;
case PROP_STYLABLE:
if (actor->priv->is_stylable != g_value_get_boolean (value))
{
actor->priv->is_stylable = g_value_get_boolean (value);
clutter_actor_queue_relayout ((ClutterActor *) gobject);
}
break;
case PROP_TRACK_HOVER: case PROP_TRACK_HOVER:
st_widget_set_track_hover (actor, g_value_get_boolean (value)); st_widget_set_track_hover (actor, g_value_get_boolean (value));
break; break;
@ -229,10 +219,6 @@ st_widget_get_property (GObject *gobject,
g_value_set_string (value, priv->inline_style); g_value_set_string (value, priv->inline_style);
break; break;
case PROP_STYLABLE:
g_value_set_boolean (value, priv->is_stylable);
break;
case PROP_TRACK_HOVER: case PROP_TRACK_HOVER:
g_value_set_boolean (value, priv->track_hover); g_value_set_boolean (value, priv->track_hover);
break; break;
@ -338,17 +324,8 @@ st_widget_dispose (GObject *gobject)
StWidget *actor = ST_WIDGET (gobject); StWidget *actor = ST_WIDGET (gobject);
StWidgetPrivate *priv = ST_WIDGET (actor)->priv; StWidgetPrivate *priv = ST_WIDGET (actor)->priv;
if (priv->theme) g_clear_pointer (&priv->theme, g_object_unref);
{ g_clear_pointer (&priv->theme_node, g_object_unref);
g_object_unref (priv->theme);
priv->theme = NULL;
}
if (priv->theme_node)
{
g_object_unref (priv->theme_node);
priv->theme_node = NULL;
}
st_widget_remove_transition (actor); st_widget_remove_transition (actor);
@ -358,11 +335,7 @@ st_widget_dispose (GObject *gobject)
if (priv->accessible) if (priv->accessible)
priv->accessible = NULL; priv->accessible = NULL;
if (priv->label_actor) g_clear_pointer (&priv->label_actor, g_object_unref);
{
g_object_unref (priv->label_actor);
priv->label_actor = NULL;
}
if (priv->texture_file_changed_id != 0) if (priv->texture_file_changed_id != 0)
{ {
@ -551,12 +524,6 @@ notify_children_of_style_change (ClutterActor *self)
static void static void
st_widget_real_style_changed (StWidget *self) st_widget_real_style_changed (StWidget *self)
{ {
StWidgetPrivate *priv = ST_WIDGET (self)->priv;
/* application has request this widget is not stylable */
if (!priv->is_stylable)
return;
clutter_actor_queue_redraw ((ClutterActor *) self); clutter_actor_queue_redraw ((ClutterActor *) self);
notify_children_of_style_change ((ClutterActor *) self); notify_children_of_style_change ((ClutterActor *) self);
} }
@ -942,20 +909,6 @@ st_widget_class_init (StWidgetClass *klass)
ST_TYPE_THEME, ST_TYPE_THEME,
ST_PARAM_READWRITE)); ST_PARAM_READWRITE));
/**
* StWidget:stylable:
*
* Enable or disable styling of the widget
*/
pspec = g_param_spec_boolean ("stylable",
"Stylable",
"Whether the table should be styled",
TRUE,
ST_PARAM_READWRITE);
g_object_class_install_property (gobject_class,
PROP_STYLABLE,
pspec);
/** /**
* StWidget:track-hover: * StWidget:track-hover:
* *
@ -1546,7 +1499,6 @@ st_widget_init (StWidget *actor)
int i; int i;
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor); actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
priv->is_stylable = TRUE;
priv->transition_animation = NULL; priv->transition_animation = NULL;
priv->local_state_set = atk_state_set_new (); priv->local_state_set = atk_state_set_new ();