Compare commits

...

513 Commits

Author SHA1 Message Date
16bdff4f48 Bump version to 2.29.0 2010-02-22 22:09:50 -05:00
565cdf502c Distribute manual page
Switch from man_MANS to dist_man_MANS so gnome-shell.1 is distributed.
2010-02-22 22:09:50 -05:00
2dc8d9b462 Fix include path when building Shell-1.0.gir
Since shell-slicer.h includes st.h, and that includes
<st/*.h>, we need to add -I $(srcdir) to the command line when
running g-ir-scanner to generate Shell-1.0.gir.
2010-02-22 22:07:52 -05:00
ce6dd21cd3 Don't generate st.h in a subdir
For srcdir != builddir, in the builddir, the st/ subdirectory doesn't
exist, so we can't generate st.h there. Just switch to building st.h
directly in the current directory. (The other option would be to
create a st/ subdirectory in the builddir if necessary; might be a
little cleaner, but this works for now and gets things distchecking.)
2010-02-22 19:37:49 -05:00
e7066d12cf Convert the check-for-missing files check to a python script
'git ls-files --exclude=<pattern>' was changed (intentionally!)
not to exclude anything files that are actually in the index.
Since git ls-files by default simply lists the files in the
index, this is a problem. Emulating this in shell went past
the limits of what made sense, so move it to a simple external
python script.
2010-02-22 19:37:49 -05:00
09df6a3818 Clean up unnecessary changes to configure.ac
Remove unnecessary checks for headers and functions, revert
changes to internationalization that introduced duplication.

(Based on a patch by Javier Jardón)

https://bugzilla.gnome.org/show_bug.cgi?id=609205
2010-02-22 19:37:49 -05:00
17d1e06c7c Remove check-news from AM_INIT_AUTOMAKE
Duplicating information from release announcements in NEWS
will quickly result in a huge NEWS file.
2010-02-22 19:37:48 -05:00
e6b80927ad Fix demands attention to work with new messagetray api 2010-02-22 23:43:02 +01:00
f9c5202dd1 Always make notifications with '\n' in bannerText expandable
Right now notifications are expandable if the length of bannerText
exceeds the notification's width - however, if bannerText contains
newlines, it should be expandable regardless of the length.

https://bugzilla.gnome.org/show_bug.cgi?id=610549
2010-02-22 23:41:09 +01:00
a21ba292eb Cancel zoom of non-focused windows when leaving overview
When leaving the overview by hitting escape or super, all windows animate
to their original positions. Zoomed windows are kept above others until
the animation ends, then the focused window is brought to the front; as
this looks odd if the zoomed window does not have focus, cancel the zoom
in that case before leaving the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=609243
2010-02-22 23:41:09 +01:00
5429104f04 Fix problems when leaving the overview with a zoomed window
While zooming, a window clone is reparented to the stage and thus cannot
be destroyed automatically by the "parent" container. To prevent the clone
and the corresponding overlay from leaking, we enforce destroying the clone
with the workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=609243
2010-02-22 23:41:09 +01:00
bb0a977edc Special-handle Empathy to have multiple sources and to queue notifications
We are planning to add Empathy-specific features in the message tray, but in the
meantime we handle Empathy notifications received through the notification daemon
so that their behavior is closer to the eventual design, which is how it was before
we started associating applications with a single source and enabled notification
replacement.
2010-02-22 17:27:23 -05:00
77ed621c74 Associate sources with applications
Use the "appName" parameter in notifications to identify the source
rather than the id - use the latter to enable update and removal of
individual notifications as laid out in the desktop notification spec.

This is a rebase of the patch by Florian Müllner.
2010-02-22 17:21:00 -05:00
fc39919856 Add top and bottom shadows to app browser
Add a 'vshadow' property to StScrollView, which, when turned on,
overlays gradient shadows on the top and bottom of the StScrollView.

Turn this on for the StScrollView used for the app browser.
https://bugzilla.gnome.org/show_bug.cgi?id=609604
2010-02-23 01:12:13 +03:00
d8800c095a NotificationDaemon: add rewriteRules infrastructure, use it for xchat
Changes notifications like:

    XChat: Private message from: danw (GimpNet) blah...

to

    danw: blah blah blah blah

(the "XChat" being unnecessary since there's already an xchat icon
there anyway.)

https://bugzilla.gnome.org/show_bug.cgi?id=608915
2010-02-22 17:09:13 -05:00
e5ba414f2d Add the workspaces view key to the gconf schema
Also rename the key to make it less ambiguous, and change its value
from an int to a string.

https://bugzilla.gnome.org/show_bug.cgi?id=609871
2010-02-22 17:01:47 -05:00
b8a9eec14f Make width of workspace switcher popup dynamic
Make the width of the workspace switcher dynamic in order to make it have the same proportions as the actual screen.

Call redraw after adding indicator to stage to avoid warning.

https://bugzilla.gnome.org/show_bug.cgi?id=610049

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
2010-02-22 20:29:49 +01:00
059504ca70 Add demands attention support to the messagetray
Inform the user about demands attention events using the messagetray.

Clicking on the notification icon moves the user to the window.

It differentiates between newly started apps and windows of already running apps, by showing different banners for this cases.

It is based on Jon Nettleton's "window attention" extension.

https://bugzilla.gnome.org/show_bug.cgi?id=610594
2010-02-22 20:09:43 +01:00
b2db95380b [MessageTray] Clear bannerText before re-adding on updates
Currently only the old title/summary line is removed from
notifications before setting the updated values - do the
same for bannerText if applicable.
2010-02-22 20:14:44 +01:00
b6bb26e9ae Add additional padding to the view specific workspace controls
In the latest mockup, there is more spacing around the scroll bar than
between the other controls.

https://bugzilla.gnome.org/show_bug.cgi?id=610189
2010-02-22 18:47:04 +01:00
126d02ae90 Fix invalid call to st_widget_get_theme_node() in WindowOverlay
WindowOverlay has two actors, both with custom style properties, which
share a common _onStyleChanged() handler. This is not a problem when
entering the overview, because the actors' parent (the workspaces group)
is hidden while the actors are added. However, when windows are added to
the workspace while in the overview (e.g. when opening a new window or
dragging a window from one workspace to another), adding the first actor
to the workspaces group triggers a style-changed signal - the handler
then calls st_widget_get_theme_node() on both actors, which triggers a
warning as the second actor has not been parented yet.

https://bugzilla.gnome.org/show_bug.cgi?id=610279
2010-02-22 18:33:58 +01:00
8d76e362a0 _computeWindowMotion calculate difference between relative positions
https://bugzilla.gnome.org/show_bug.cgi?id=607826
2010-02-22 20:14:13 +03:00
004cf3da5c [appDisplay] Use AUTOMATIC for apps-more, not ALWAYS
No need to display a scrollbar if we don't need to, and ALWAYS
isn't yet implemented anyways.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-22 12:07:23 -05:00
fb9fd6925a [StScrollView] Fix incorrect assertion, defaults, and test case
The type we don't currently handle is _ALWAYS, my original use
of g_return_if_fail was wrong.

Also the default should be AUTOMATIC in the properties, not ALWAYS.

Finally the test case was still using the incorrect St.ScrollPolicy.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-22 12:06:56 -05:00
ec725cc6d4 [Notification] Replace all newlines in body with spaces
Accidentally we only replaced the first newline of the body text with
spaces - replace all occurrences instead.

https://bugzilla.gnome.org/show_bug.cgi?id=610549
2010-02-21 03:54:13 +01:00
79fe60e6fb [messageTray] Fix text with ampersands not being displayed
If the notification body contains '&' it ends up empty and a warning
about an invalid entity is printed on stderr, so our escape code must
handle ampersands as well.

https://bugzilla.gnome.org/show_bug.cgi?id=607375
2010-02-21 03:54:06 +01:00
c793d7d0a4 get_app_for_window_direct search ShellApp by window, before create.
https://bugzilla.gnome.org/show_bug.cgi?id=610324
2010-02-21 03:19:24 +03:00
1b7c3580e6 Show/hide the summary during the overview transition
Right now, the summary starts popping up when the overview has been
shown and starts to disappear when the overview is hidden. Instead,
animate the summary during the overview transition.

https://bugzilla.gnome.org/show_bug.cgi?id=610520
2010-02-20 20:05:50 +01:00
3c3e0b6f20 Updated Bulgarian translation 2010-02-20 14:30:00 +02:00
fd6863dda4 Add missing section-more-open file from previous commit 2010-02-19 15:52:56 -05:00
690be611ee Implement newer design for "more apps" view
Replace the old GenericDisplay-based system with one which reuses
the WellGrid class and uses a new scrolling container.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-19 15:39:26 -05:00
18c5405b79 [StScrollView] Add support for GtkPolicyType for scrollbars
Previously we were hacking out the vertical scrollbar, this patch
allow us to sanely say in which directions we want to scroll.

Note this patch intentionally changes St to depend on GTK+ in the
API.  I believe this is a correct long term change where we should
view St as co-evolving with GTK+ rather than replacing or paralleling.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-19 15:37:40 -05:00
cfd63c7d4c fix selection of all-workspace windows
all-workspace windows can be active on every workspace.
https://bugzilla.gnome.org/show_bug.cgi?id=603078
2010-02-19 21:29:46 +03:00
49a9335f68 fix sizing of all-workspace windows in the overview
Window can have more then one clones on different workspaces.
https://bugzilla.gnome.org/show_bug.cgi?id=603078
2010-02-19 21:29:35 +03:00
5b1d52c5e7 Fix build problem with mutter 2.29
Query mutter's version more or equal 2.29.0
2010-02-19 20:54:47 +03:00
9f43ed3f95 Use _onDestroy() handlers for cleanup in delegates
Unify the style of <delegate>.destroy() methods to only contain a
call to <delegate>.actor.destroy() and handle additional cleanup
in a _onDestroy() signal handler.

https://bugzilla.gnome.org/show_bug.cgi?id=609454
2010-02-18 22:50:34 +01:00
0770fd5be5 Use St.Button for preview close buttons
Originally, we used St.Bin for the preview close buttons - using
St.Button instead adds support for pseudo classes to style different
button states.
2010-02-18 19:25:28 +01:00
3c8ba348c2 Slide out removed workspaces in linear view
Instead of deleting workspaces immediately, animate the removal - it may
be useless eye-candy, but it's pretty sexy nonetheless ...
More seriously, the animation improves consistency with both workspace
additions and the mosaic view.

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:37:05 +01:00
b84a7042f1 Make spacing between workspaces stylable
Currently the width of the gaps between workspaces in both linear
and mosaic view are defined as constants. Move these to the theme's
CSS instead.

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:37:05 +01:00
8ef75524ea [Workspaces] Clean up scrolling in linear view
Reorganize the code to break up positioning into:

1) updating workspace object's scale and position
2) applying the updated parameters to the workspace actor
3) scrolling the view to a particular workspace
4) handling dragging of the scroll bar

With these cleanups, it becomes much easier to fix
the following issues:

- use animations consistantly instead of doing hard breaks
  for some actions and smooth transitions for others
- snap to the closest workspace when scrolling stops
  (https://bugzilla.gnome.org/show_bug.cgi?id=607823)
- fix the regression of the zoomFromOverlay animation when
  the selected app is on another workspace
  (https://bugzilla.gnome.org/show_bug.cgi?id=609081)

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:36:58 +01:00
cec62a7ca5 Main.activateWindow: always exit the overview if it's currently open
This way, clicking a message tray icon while the overview is open will
close the overview when activating its window.

Remove some other overview-related activation code which is now
redundant.

Also, remove calls to "global.get_current_time()" when calling
Main.activateWindow, since it's unnecessary (activateWindow will call
it itself if you don't pass in that arg).

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:08:28 -05:00
77fe0db623 [MessageTray] Show the message tray in the overview
Also, make the summary area always visible when in the overview

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:08:24 -05:00
e86c821878 [MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.

By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.

Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:06:17 -05:00
02f67af464 [MessageTray] Fix summary to be initially-hidden
Some recent change broke it so that the first time a notification pops
up, the summary will be visible alongside it.

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 14:45:59 -05:00
fd310bc7b9 Correct position of window previews.
align the bottoms of the window previews.
window previews always fit in the slot.
https://bugzilla.gnome.org/show_bug.cgi?id=610070
2010-02-17 19:56:45 +03:00
94d3e27c53 [Overview] Fix tiled background images
Tiled backgrounds are only displayed once in the upper left corner when
in the overview - they should be tiled just like outside the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=610203
2010-02-17 17:34:38 +01:00
6aa02c5edc [AppSwitcher] Make sure that fallback icons have correct box sizes
Fallback icons (i.e icons < requested size) cause the box in the switcher
to be a smaller rectangular item instead of the normal sized square one.

Fix that by putting the icons in a St.Bin with the correct size.

https://bugzilla.gnome.org/show_bug.cgi?id=609777
2010-02-17 10:52:11 +01:00
97e19d7d4a Adjust behavior of search results to match app well
Currently, activating a search result always opens a new window. Change
this behavior, so that if an application has open windows, the most
recently used one is activated instead.

Also change the implementation of dnd of search results to allow providers
to treat results activated via dnd differently.

https://bugzilla.gnome.org/show_bug.cgi?id=610027
2010-02-16 23:50:35 +01:00
94f32030e6 [MessageTray] notification size/wrapping fixes
Make the font match the panel.
Make the max width be em-based rather than screen-size-based.
Fix it to break lines mid-word if needed.

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-16 14:08:17 -05:00
721e1ea863 [St] Implement max-width/max-height in the CSS parser
st_theme_node_adjust_preferred_width/height now limit the content area
of an actor to the max, if given. (The requested width/height may be
larger to make room for borders, etc.)

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-16 14:08:17 -05:00
5331d3e360 [St] Make allocation handling more consistent
In StBin, StBoxLayout, and StTable, if a child has a potential
allocation that is larger than its preferred size, we give it its
preferred size instead. However, the corresponding
get_preferred_height/width methods were not making the same
assumption, which meant that if we had more width than the widget
wanted, we would allocate it its preferred width, but with the height
that corresponded to the larger width.

Fix this by defining new helpers _st_actor_get_preferred_width() and
_st_actor_get_preferred_height() and using them everywhere. Also, make
StBin and StTable use _st_allocate_fill() rather than having
nearly-identical duplicate copies of the code.

https://bugzilla.gnome.org/show_bug.cgi?id=609848
2010-02-16 14:06:39 -05:00
f52744cfbc [StTable] fix x-align/y-align properties to be StAlign, not double
This puts it in sync with StBin and StBoxLayout

https://bugzilla.gnome.org/show_bug.cgi?id=609848
2010-02-16 14:06:39 -05:00
4749393ab5 Remove panel-run-dialog/main-menu handling from shell-global
This is handled by the shellwm (takeover_keybinding) nowdays.

https://bugzilla.gnome.org/show_bug.cgi?id=610039
2010-02-16 16:50:40 +01:00
975603d608 Updated Vietnamese translation 2010-02-16 19:36:49 +07:00
99346522e9 Hungarian translation updated 2010-02-16 10:10:45 +01:00
090335ad8b [MessageTray] fix notifications with short banners and action buttons
Previously the banner was only promoted to the body if it got
truncated, but the banner was *always* hidden when expanding the
notification. This meant a message with a short banner, plus
notification buttons, would have no banner text visible when it was
expanded. Fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-15 17:28:23 -05:00
d8af8f7305 [CSS] Update overview style to match latest mockup
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-15 22:14:31 +01:00
2a2b597e09 [Overview] Make background color stylable
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-15 22:14:28 +01:00
da1d43fc61 Updated Spanish translation 2010-02-15 21:46:19 +01:00
03a750176b Fade out desktop icons when showing overview
As desktop icons don't have any purpose in the overview (except for
distracting the user), fade them out when entering the overview.

Unfortunately, the fading effect affects performance, therefore hide
icons directly when there are maximized windows on the desktop.

https://bugzilla.gnome.org/show_bug.cgi?id=600999
2010-02-15 21:49:11 +01:00
1d2bb5c51c Updated Slovenian translation 2010-02-15 19:04:25 +01:00
60046aaa4f Switch to the corresponding app when the notification icon is clicked
This adds some meaningful functionality to the notification icons in the tray
and in the notification pop-up and allows to switch to the application that
sent the notification.

We get the application from the notification context and set it on the source
for the notification.
2010-02-15 12:27:28 -05:00
a6df234528 Make workspace indicators drop targets
Allow dropping on the workspace indicators to open apps on specific workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=609913
2010-02-15 17:24:44 +01:00
5ead0de7ca .gitignore: add po/gnome-shell.pot 2010-02-15 08:35:16 -05:00
229cfd9f80 xgettext only recognizes _("foo"), not _('foo') in .js files. Fix
Noted in https://bugzilla.gnome.org/show_bug.cgi?id=609838
2010-02-15 08:33:35 -05:00
01c267b095 POTFILES.in: add missing files that have translatable strings
https://bugzilla.gnome.org/show_bug.cgi?id=609838
2010-02-15 08:10:28 -05:00
33a6c41810 Updated Spanish translation 2010-02-15 11:26:12 +01:00
7040e9a63b Updated Norwegian bokmål translation 2010-02-14 13:46:32 +01:00
901eabb82d Fix problem with make system.
https://bugzilla.gnome.org/show_bug.cgi?id=609811
2010-02-13 18:41:13 +03:00
b11aa5f676 vi.po: Updated "favourites" translation 2010-02-13 22:01:28 +07:00
ccaa11bb6b Added Vietnamese translation 2010-02-13 21:23:29 +07:00
dd0fba4270 Revert "Add workspaceSwitcherPopup.js to Makefile.am"
This reverts commit 3f6759061d.

Proper fix is in https://bugzilla.gnome.org/show_bug.cgi?id=609811
2010-02-13 15:16:53 +01:00
3f6759061d Add workspaceSwitcherPopup.js to Makefile.am
Re add accidentally omitted change.

https://bugzilla.gnome.org/show_bug.cgi?id=609187
2010-02-13 15:12:39 +01:00
abc7b1ff02 New workspace switcher popup
Replace the current workspace switcher popup (which is still the old metacity popup), with a clutter based one, which fits better into the overall shell design.

https://bugzilla.gnome.org/show_bug.cgi?id=609187
2010-02-12 23:52:15 +01:00
75a677701d .gitignore: add m4/ 2010-02-12 10:19:31 -05:00
11656ebd89 Remove duplicate GETTEXT_PACKAGE 2010-02-11 15:29:58 -05:00
d62b4cf130 Modernize autotools configuration
New requirements:
autoconf >= 2.63
libtool >= 2.2.6
intltool >= 0.40.6
pkg-config >= 0.22

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=609205
2010-02-11 21:02:21 +01:00
c4b3d18e26 Updated Slovenian translation 2010-02-11 20:56:03 +01:00
38b7904f92 Distinguish translator comments for date formats
Don't say 'This is a time format' for both time formats, but
label them as 24-hour and AM/PM.
2010-02-11 14:53:14 -05:00
c89ee2f8f2 [panel] Fix typo in previous clock patch
We shouldn't be displaying hours as 24 in am/pm case
2010-02-11 14:42:12 -05:00
res
c21e692652 [panel] Detect clock AM/PM from locale
Look at whether a localized time string from JS includes am/pm to
determine whether we should show it in the UI.
2010-02-11 14:01:19 -05:00
071efd826c Updated Italian translation 2010-02-10 22:31:39 +01:00
d27f19a561 [MessageTray] Provide more control over Notification layout
This will be used by, eg, the chat notifications

https://bugzilla.gnome.org/show_bug.cgi?id=609453
2010-02-10 16:04:41 -05:00
7642040fc0 [MessageTray] rename some fields
"fooText" suggests it might be a string, but it's actually an St.Label

https://bugzilla.gnome.org/show_bug.cgi?id=609453
2010-02-10 16:02:25 -05:00
67e70df0c9 [dash] Enable DND of search results
Allow dragging search results to a specific workspace to launch them
on that workspace; the drag icon is the icon from the search result.

https://bugzilla.gnome.org/show_bug.cgi?id=609218
2010-02-10 17:11:45 +01:00
fc0acc9e37 Update the look of panel buttons
Change the look of panel buttons to match the running indicators used
in the app well.

https://bugzilla.gnome.org/show_bug.cgi?id=609357
2010-02-10 16:36:22 +01:00
3a7dc32659 Fix up "window-added/removed" callbacks
Currently the window-added and window-removed callbacks in
main.js:_onWorkspaceSwitched access the first parameter as metaWindow object,
but in fact the first one passed is the workspace (metaWorkspace).

Fix it by using the second parameter instead (which is a metaWindow object).

https://bugzilla.gnome.org/show_bug.cgi?id=609521
2010-02-10 15:34:44 +01:00
36e761b7a5 Fix annotation of shell_recorder_set_pipeline()
There are two minor errors here: the documented parameter name does not
match the real one, and there should be an (allow-none) annotation.

https://bugzilla.gnome.org/show_bug.cgi?id=609522
2010-02-10 13:18:24 +01:00
9a1cb9c3db [InfoBar] Make spacing between message and button stylable
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-10 10:16:45 +01:00
32e2ff7573 [StScrollbar] Allocate steppers according to size requests
The forward/backward steppers are always allocated a square region at the
scroll bar's ends. Change the allocation to be based on the steppers' size
requests instead.

https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-10 10:13:00 +01:00
ea4b1c6c29 Add an initial version of a manpage
https://bugzilla.gnome.org/show_bug.cgi?id=605249
2010-02-09 18:19:41 -05:00
2d574047e4 Don't show chrome when a fullscreen window is open
Currently the check in chrome.js checks if a window is on the
primary screen by checking its coordinates, width and height.

This check misses the case where windows just set
_NET_WM_FULLSCREEN without changing their position and
size (examples are Flash and ooimpress's presentation window).

Fix this by separating the check for fullscreen windows from the
override redirect one, and only check whether the window is
anywhere on the primary screen in the fullscreen case.

https://bugzilla.gnome.org/show_bug.cgi?id=597271
2010-02-09 21:35:45 +01:00
8ded91e975 Limit activation to summary area and notifications
Currently the messagetray opens up everytime the user hits the bottom of the screen.

To avoid this "opening by accident" this patch changes the behaviour so that:
1) It only opens when there is a notification showing or
2) When the user hits the summary area (assuming he wants to interact with it)

Includes fixes from https://bugzilla.gnome.org/show_bug.cgi?id=607244#c17

https://bugzilla.gnome.org/show_bug.cgi?id=607244
2010-02-09 19:31:39 +01:00
0b2eeccd4b Add "InfoBar" and undo capability to overview
It allow to show some information to user and Undo his actions.
https://bugzilla.gnome.org/show_bug.cgi?id=608933
2010-02-09 01:59:26 +03:00
fa5b0efdb4 Updated Norwegian bokmål translation 2010-02-08 22:58:10 +01:00
7555915441 [Overview] Update window titles when they change
Have window title captions in the overview window picker update on
window title changes.

https://bugzilla.gnome.org/show_bug.cgi?id=609206
2010-02-08 21:45:01 +01:00
3e1b1d5789 Make parameters configureable
Make the framerate, file extension and gstreamer pipeline used by the
screencast recorder configureable using gconf.

This patch does not change the defaults, it justs provides a way for
the user to override them.

https://bugzilla.gnome.org/show_bug.cgi?id=608995
2010-02-08 21:31:30 +01:00
8e759d7f32 Initialize global->root_pixmap to the stage color
Fixes drawing of the overview in the case where there is no root pixmap
(eg, --xephyr mode).

(And the workaround for not drawing an unintialized ClutterTexture can
be removed now, since the texture will always have been initialized.)

https://bugzilla.gnome.org/show_bug.cgi?id=609339
2010-02-08 14:47:04 -05:00
caaa543385 Draw a ripple when the hot corner is hit
Animate an expanding ripple from the hot corner using multiple
scaling copies of a PNG of a single ripple. The idea here is to
give the user a clue as to what happened.

Based on initial version implemented live at MIT IAP GNOME Shell
intro session; thanks to all the attendees for coming!

https://bugzilla.gnome.org/show_bug.cgi?id=609135
2010-02-08 14:04:45 -05:00
dce4b2f325 Remove C99 use of non-constant initializers
To comply with C89, structure initializers should have
only constant values.

(Not a thorough check for this throughout the codebase, just
StWidget is fixed up in this commit.)

https://bugzilla.gnome.org/show_bug.cgi?id=608746
2010-02-08 14:04:45 -05:00
fb7ed1ee28 [ShellEmbeddedWindow] Set window type in g_object_new
As of 2a78adc5e3, gobject no longer allows for setting construct-only
properties via g_object_set() during object initialization; set the
properties in a custom constructor instead.

https://bugzilla.gnome.org/show_bug.cgi?id=608802
2010-02-08 18:50:05 +01:00
a74cef9d2f [altTab] Position on the currently focused monitor
Show the popup on the currently focused monitor rather than on the primary.

https://bugzilla.gnome.org/show_bug.cgi?id=609257
2010-02-07 19:28:35 +01:00
c88d21d487 Use GL_MESA_pack_invert if available
Use GL_MESA_pack_invert if available to avoid doing flipping in software.

https://bugzilla.gnome.org/show_bug.cgi?id=609053
2010-02-05 22:25:40 +01:00
6f83b39ee4 Consume windows by the Activities button on minimize
The design document states:
"Animate the action as shrinking into or being consumed by the Activities Item"

This makes it clear what happens to the window (i.e it doesn't vanish but can be brought back by going to the overview).

https://bugzilla.gnome.org/show_bug.cgi?id=609079
2010-02-05 17:01:18 +01:00
f5c4e23c9c Fix drag point for application icons
We need to return the "thing that is being dragged" from
getDragActorSource() so that dnd.js can figure out the right
relationship between the dragged object and cursor.

https://bugzilla.gnome.org/show_bug.cgi?id=607351
2010-02-05 10:57:17 -05:00
f1fb0d32c6 [MessageTray] fix ellipsization when the title is too long
The code previously assumed that an StLabel with a 0-width allocation
would not be visible; this is apparently not true.

Part of https://bugzilla.gnome.org/show_bug.cgi?id=608915
2010-02-03 19:21:48 -05:00
ed129b40a3 [ShellWindowTracker] Add shell_window_tracker_app_from_pid
In some situations we might need to look up an application from
a process identifier, such as the notification system where we
will determine application from the message sender.
2010-02-03 19:07:22 -05:00
fd1ce40ee7 Improve handling of gradients
By calling clutter_actor_get_allocation() in st_widget_recompute_style()
to determine whether to redraw gradients, we triggered a complete
reallocation of the stage for each gradient.

As gradients are processed in st_widget_real_style_changed() anyway, the
additional checks in st_widget_recompute_style() are redundant and can
be removed altogether.

https://bugzilla.gnome.org/show_bug.cgi?id=608847
2010-02-03 23:38:42 +01:00
2b15f38730 Pick up change from gradient to solid background
On style changes from gradient to solid backgrounds, the new background
must be drawn unconditionally, not depending on whether old and new
background color differ.

https://bugzilla.gnome.org/show_bug.cgi?id=608914
2010-02-03 21:16:40 +01:00
86515f3943 show background when nautilus isn't drawing the desktop.
If window with type Meta.WindowType.DESKTOP doesn't exist, then draw
background.
https://bugzilla.gnome.org/show_bug.cgi?id=591912
2010-02-03 22:52:25 +03:00
9afb09128b Fix resizing problems with DashDocDisplay
- Handle non-uniform child heights properly - use a constant
  grid size as the maximum of all child heights; with the
  previous code, the children might not line up in the two
  columns and the last item could be lost if the second column
  was taller than the first column.

- Call set_skip_paint(child, false) on children that we do
  want visible to override any previous hiding of that child.

- Correctly handle the DashDocDisplay not being allocated at 0, 0;
  children should be allocated starting at 0, 0, not at origin
  of the allocation box passed in.

- Remove an unused skipPaint variable.

https://bugzilla.gnome.org/show_bug.cgi?id=608801
2010-02-03 13:51:02 -05:00
e40063fc34 [MessageTray] add support for notification actions
https://bugzilla.gnome.org/show_bug.cgi?id=606979
2010-02-03 13:43:17 -05:00
d20d815b45 [MessageTray] Merge Notification and NotificationBox
This will (eventually) give sources more control over the form of
notifications

https://bugzilla.gnome.org/show_bug.cgi?id=606979
2010-02-03 13:43:17 -05:00
ed36517615 [ShellGenericContainer] Simplify tracking of skip-paint children
The current way we keep track of skip-paint children is more
difficult than it needs to be, and can lead to subtle bugs.
(For one, the skip-paint state of a child is remembered
when it is removed then added back again, which is completely
unexpected.)

Instead of using weak references to track children, just remove
items from the skip-paint list by overriding the remove() virtual
function of the ClutterContainer interface.

The 'skip_paint' hash table is then destroyed in finalize rather than
dispose since it doesn't hold references to memory any more but just
passively tracks an attribute of the children that are currently in
the container.

https://bugzilla.gnome.org/show_bug.cgi?id=608848
2010-02-03 12:00:56 -05:00
fa60165764 [MessageTray] do pop-out on hover for long notifications
https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-02 14:00:17 -05:00
3c9d0fbca6 [MessageTray] fix up allocation, ellipsize long notifications
https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-02 14:00:07 -05:00
8d31c2f4dc change a few stray tabs to spaces 2010-02-02 10:31:38 -05:00
eaa1f9a0f4 [MessageTray] Fix positioning for multi-monitor environments
We can't assume that the primary monitor is at position (0, 0);
there may be another monitor configured at the left or at the top.
2010-02-02 14:02:32 +01:00
3e19f41cba [StWidget] Limit gradient redraws to size changes
When moving a widget with a gradient, its allocation changes
continuously, resulting in constant redraws.
Checking for actual size changes before the operation avoids
unnecessary redraws.

https://bugzilla.gnome.org/show_bug.cgi?id=608715
2010-02-02 00:24:35 +01:00
e6902a1f1c "Fix" prelighting of the scroll bar handle
By default buttons fade from the hover to the normal state, by animating
the opacity of a copy of the previous border-image. This works as
expected for opaque and fully transparent pixels, but results in a
flickering effect for others.
Making StButton's fade effect work with partly transparent pixels is
hard, not using images with transparency is easy ...

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 22:50:25 +01:00
b1007ed811 Add shell_global_gc
Primarily useful for debugging.  This was originally a patch against
gjs: https://bugzilla.gnome.org/show_bug.cgi?id=595323

But rather than add a random toplevel module just for this function
effectively, we can easily enough define it here.  Adding toplevel
modules to GScript should have a bit more formal process to it.

https://bugzilla.gnome.org/show_bug.cgi?id=608095
2010-02-01 16:08:43 -05:00
54d385a0a9 [AppSwitcher] tweak the sizing code, which depended on the previous bug 2010-02-01 12:31:26 -05:00
df48e9d1c0 Fix misuse of ShellGenericContainerAllocation in two places 2010-02-01 11:54:47 -05:00
e3be74a31a Fix invalid unreference of CoglTexture
cogl_texture_get_data doesn't increase the refcount, so don't try
to decrement it.

Signed-off-by: Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=608512
2010-02-01 10:15:15 -05:00
a8aa0c085f CSS tweaks to match mockups better
- add some spacing between buttons
- move controls closer to the workspaces view (we'll need that space
  for the message tray)
- fix the look of the scrollbar background
- adjust sizes of theme images
- some general CSS cleanup

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
cd78f1158c Reduce the gap between workspaces in linear view
https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
d9668bd425 Make inactive workspace buttons insensitive
Update sensitivity instead of hiding buttons - hiding the
add workspace button looks especially weird.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
dc3ff10c6f Fix slightly misplaced overlays in single view
Correct the positioning of window captions and close buttons for
non-active workspaces in single view.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
31f9da7b8f Fix transition to zoomed window in single view
Fix messed up transition from overview when activating a zoomed in
window.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
05e3a747d0 Remove images of old workspace buttons 2010-01-30 00:01:35 +01:00
8db212db99 ShellRecorder: Fix interaction of glReadPixels with Cogl
The screen recording wasn't working because of two bad interactions
with Cogl:

 - Buffered primitives weren't being flushed out
 - Cogl changes the pixel store values away from their default values

Thanks for Jon Nettleton for tracking down the source of the
problems with the recorder.

https://bugzilla.gnome.org/show_bug.cgi?id=598390
2010-01-28 13:54:58 -05:00
2494cc1637 Show summary mode briefly after notification
This helps illustrate that expired notifications move to the summary view.

Animate the separate components of the message tray individually
as in http://www.gnome.org/~mccann/shell/mockups/20090630-demo

Based on the patch from Florian Müllner.
2010-01-28 13:39:00 -05:00
ee75355e71 Replace direct call to MessageTray::showNotification() with 'notify' signal in Source::notify()
This decouples Source and MessageTray, so Source doesn't need to know how
MessageTray works.
2010-01-28 13:20:17 -05:00
863f9f285b Updated Bulgarian translation 2010-01-28 05:04:53 +02:00
d7e0051bc6 [StButton] Hold ref to self until animation completes
StButton has an internal animation for the border-image actor, then
it connects to the "completed" signal passing itself as data.  However,
if the button is destroyed, nothing prevents the animation's completed
signal from then causing a reference to freed memory.

Holding a reference to the button is the most straightforward fix here.

https://bugzilla.gnome.org/show_bug.cgi?id=607825
2010-01-26 14:28:57 -05:00
2aa305b51d [StShadowTexture] Fix invalid unref of CoglHandle
This code appeared to treat the return value of clutter_texture_get_cogl_texture
as having a new reference, but in fact it doesn't.

https://bugzilla.gnome.org/show_bug.cgi?id=608119
2010-01-26 13:03:43 -05:00
4006d7d57f Adjust message-tray on resolution changes
https://bugzilla.gnome.org/show_bug.cgi?id=608058
2010-01-25 21:26:47 +01:00
0a566f70b6 [AppIcon] Leave overview when launching apps
There was an unintentional regression at some point where we ceased
leaving the overview when launching applications.  Fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=608062
2010-01-25 14:16:05 -05:00
be2801d1fa Nicer animation of hidden windows when transitioning to/from the overview
Hidden windows used to appear/disappear abruptly in the beginning/end of the transition and the new animation is a lot smoother.

https://bugzilla.gnome.org/show_bug.cgi?id=571109
2010-01-23 11:26:30 -05:00
648126e598 Move 'workspace_relative' definition to workspace.js
'workspace_relative' is used in workspace.js, not in workspacesView.js

Change a couple strings to have single quotes instead of double quotes to indicate that
they don't need to be translated.
2010-01-22 20:04:18 -05:00
8184b2c57b [Overview] Correct scroll directions on indicators
When using the scroll wheel on the workspace indicators in single view,
make them use the same interpretation as the scrollbars: scrolling up
moves to the previous workspace, scrolling down to the next one.

https://bugzilla.gnome.org/show_bug.cgi?id=607824
2010-01-23 01:15:45 +01:00
337eab614e [WorkspaceView] Allow workspace switching using mousewheel + indicators
Allow the user to switch between workspaces by scrolling on the indicators.
Up = next workspace
Down = previous workspace
2010-01-22 20:49:52 +01:00
20abc4cb99 New workspaces view
Matching the 20091114 mockup, the default workspace view
is now a scrollable horizontal list, with a control to
switch between this and the previous grid view.

https://bugzilla.gnome.org/show_bug.cgi?id=593844
2010-01-22 13:47:52 -05:00
5aca0b7704 Updated Hungarian translation 2010-01-22 00:57:46 +01:00
74446ce3e0 [Places] Hide desktop icon when desktop_is_home_dir
With the above preference set to true, the home and desktop entries
both represent the same location. Hide the desktop icon in that case
to avoid redundancy.

https://bugzilla.gnome.org/show_bug.cgi?id=606922
2010-01-20 23:36:14 +01:00
7bb14bd8da calendar.js: switch buttons direction in RTL mode
also don't hang if translation of 'calendar:week_start:0' is incorrect

https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-01-20 17:24:22 -05:00
ed75f0da63 [dnd] revert the change to only allow dropping on reactive actors
Workspace.actor is non-reactive, and there's probably some good reason
for this. So just have the add workspace button check its own reactivity.
2010-01-20 14:01:37 -05:00
d9008054cf Handle resolution changes
Added signal 'screen-size-changed' to ShellGlobal.
Connect to this signal in main.js and run the _relayout() method.
If Overview or calendar are visible when this signal emit, they will be hiding.
https://bugzilla.gnome.org/show_bug.cgi?id=584526
2010-01-19 21:32:36 +03:00
b10d9c9ad7 Added Norwegian to the list 2010-01-19 17:43:35 +01:00
5f855045a2 Added Serbian translation 2010-01-19 00:18:38 +00:00
88737b2083 [dnd] Don't allow dropping on non-reactive actors 2010-01-18 14:58:31 -05:00
a50d64e8e9 [overview] disable the AddWorkspaceButton if there are >= 16 workspaces
https://bugzilla.gnome.org/show_bug.cgi?id=606460
2010-01-18 14:58:26 -05:00
4deef2a9ef [Overview] Allow selecting windows in lightbox mode
Make the event blocking done by Lightbox optional - leave it activated
when displaying the run dialog, but deactivate it when highlighting
windows in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=602774
2010-01-18 13:53:31 +01:00
dd9a29633a Updated Arabic translation 2010-01-17 11:30:43 +02:00
4407f0bd65 Updated Simplified Chinese translation. 2010-01-17 15:30:54 +08:00
73fd896f3c [tests/borders.js]
Shrink stage size to 640x480 to fit on netbook screen.

Make the area scrollable.

Add a few more tests.
2010-01-15 18:33:36 -05:00
f8acd0f6f6 Match on executable names as well
Include matches on desktop entries' exec property in addition to the
name and comment ones.

https://bugzilla.gnome.org/show_bug.cgi?id=606743
2010-01-15 23:03:18 +01:00
ccc6a23f68 Fix missing translations for 'time ago' strings
Replace ngettext with dngettext and set the correct translation
domain, so gnome-shell's domain is searched for translations
rather than mutter's.

https://bugzilla.gnome.org/show_bug.cgi?id=597882
2010-01-15 17:14:03 +01:00
c236c501e7 Updated German translation 2010-01-15 16:56:41 +01:00
2a0e0ae66f Fix crash in runDialog
The run dialog crashes when PATH contains non-existing directories (some
distros seem to do that ...).
Fix by filtering those out before setting up file monitors.

https://bugzilla.gnome.org/show_bug.cgi?id=606418
2010-01-14 13:16:55 -05:00
11276a3505 Initial implementation of the message tray and notification daemon
From the message-tray branch. Most of the UI parts were written by
Marina, and most of the D-Bus parts by me.
2010-01-13 15:13:20 -05:00
c90371d9d5 [ShellTextureCache] add methods for caching raw image data
shell_texture_cache_load_from_data() takes the contents of an image
file, while shell_texture_cache_load_from_raw() takes the actual pixel
data.
2010-01-13 15:13:20 -05:00
038a32330f [St] Add st_box_layout_move_child and st_box_layout_insert_actor 2010-01-13 15:13:20 -05:00
fa1fe4fdd1 Updated Czech translation 2010-01-12 21:58:45 +01:00
59d6029f47 Implement radial gradients for StWidget
Some theme authors have stated interest in radial gradient backgrounds.
The w3c has some draft:

http://dev.w3.org/csswg/css3-images/#radial-gradients

As this is rather complex, we add only some very basic support, which
extends our syntax for linear gradients:

background-gradient-direction: [vertical|horizontal|radial]

Gradients are centered circles, whose size is determined by the closest
side.

https://bugzilla.gnome.org/show_bug.cgi?id=604945
2010-01-11 23:38:34 +01:00
33b3d05039 Update running app indicator to match latest mockup
https://bugzilla.gnome.org/show_bug.cgi?id=606257
2010-01-11 23:38:34 +01:00
7486c09fbb Change handling of gradients
Some changes to the way we handle CSS gradients:

 * draw without padding, thus interpreting gradients as part of the
   background rather than as content

 * clip to (rounded) border area

 * draw the border along the gradient instead of trying to align the
   gradient layer with the background/border layer

 * use the border_image actor instead of the background_image one

https://bugzilla.gnome.org/show_bug.cgi?id=606257
2010-01-11 23:38:34 +01:00
3f750a5637 Updated Slovenian translation 2010-01-11 15:29:12 +01:00
e54fe59723 Updated Spanish translation 2010-01-09 09:16:56 +01:00
38b20ca0a4 autohide sidebar in compact mode (v3)
https://bugzilla.gnome.org/show_bug.cgi?id=604118
2010-01-08 16:32:51 -05:00
8c178378ae [appIcon] Delete; this file is obsolete
Was moved into appDisplay.js.
2010-01-08 15:58:44 -05:00
341b9a80c5 Do not reset window zoom when leaving the overview
https://bugzilla.gnome.org/show_bug.cgi?id=598319
2010-01-08 18:43:34 +01:00
45e89bf34a [main] Print a starting message to stdout
This helps developers delineate error streams between "Alt-f2 r",
among other things.
2010-01-08 11:39:02 -05:00
c17e1249d5 [panel] Scale up, center and fade application icon in app menu
Per 20091114 design.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:01 -05:00
262f92e0be [ShellSlicer] New class to display center of child
A #StBin that has 0 minimum size, and will clip its child
in the middle.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
da797dff35 [Makefile-st.am] Generate st/st.h
All of the st-$foo.h files say to include st.h, but we didn't have
one.  Therefore, generate it.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
7043215f5e Misc. style changes
Matching 20091114 mockup.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
5202dd5157 [dash] Change section titles to match 20091114 mockup
Documents is changed to Items, and add "& Devices" to Places.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
7c4765d053 Updated Slovenian translation 2010-01-07 18:51:30 +01:00
69c8aef6c2 Show "No matching results" if that's the case
This also fixes backtracking from no matching results.

https://bugzilla.gnome.org/show_bug.cgi?id=606209
2010-01-06 16:20:01 -05:00
71786e50cf [build setup] Add -L to curl invocations
To follow redirects, otherwise we might be downloading 301 HTML pages
instead of the data we want.
2010-01-06 13:56:47 -05:00
e5647c4f83 [build setup] Add gcc-c++ on Fedora 2010-01-06 13:54:12 -05:00
98a8dd682d [ShellAppUsage] Fix use-after-free
We were holding on to UsageData structure pointers in previously_running,
but those can be purged by the unused app cleanup.  Instead just hold
onto dup'd copies of the application id strings.
2010-01-06 13:34:11 -05:00
af3b965e00 [Overview] Add drop shadows to close buttons
https://bugzilla.gnome.org/show_bug.cgi?id=603691
2010-01-05 21:48:10 +01:00
2dfe113a42 Implement -st-shadow for StWidget
Add support for a new -st-shadow property, which is based loosely
on the CSS3 box-shadow property:
http://www.css3.info/preview/box-shadow/

It defers from the specification as follows:

 * no multiple shadows
 * the optional color argument may be placed anywhere
 * the shape is not determined by the widget's bounding box,
   but by the background-image property

https://bugzilla.gnome.org/show_bug.cgi?id=603691
2010-01-05 21:48:09 +01:00
a2cae50e0e Updated Slovenian translation 2010-01-05 16:56:33 +01:00
9423cc7fae Fix application thumbnail sizing when the height is greater than the width of a window.
This bug happened because the thumbnail box was only maxed, not set to 256x256.
Standard window thumbnails would max out only the width to 256. Having a window with
its height greater than its width meant that the height would max out, but not the
width, causing thumbnails to look uneven.

https://bugzilla.gnome.org/show_bug.cgi?id=604963
2010-01-04 20:21:28 -05:00
767fe0ebc2 [St] Don't leak the font family name
A copy of the string is made by pango_font_description_set_family()
and we don't need the string anymore, so we should free it

https://bugzilla.gnome.org/show_bug.cgi?id=605035
2010-01-04 13:49:47 -05:00
edce0e8feb Updated Italian translation 2009-12-28 21:59:19 +01:00
554549338a Updated Galician Translation 2009-12-28 17:07:26 +01:00
350e958383 position sidebar centerd on the left side of the primary monitor
https://bugzilla.gnome.org/show_bug.cgi?id=604177
2009-12-21 12:12:44 -05:00
0e5c83bd2a Fix URLs pointing to git.gnome.org/cgit
git.gnome.org/cgit was relocated to git.gnome.org/browse; adjust
URLs in our build script to match.
2009-12-20 11:36:10 -05:00
6e1a791273 Allow clicking on any part of section header to browse
This is more intuitive, though we need to make the whole thing feel more like a button.

https://bugzilla.gnome.org/show_bug.cgi?id=596985
2009-12-20 01:06:24 +01:00
2435c603ec Updated Spanish translation 2009-12-19 14:55:33 +01:00
44cc42484f [appDisplay] Switch to using global.get_current_time()
Main.currentTime() moved into ShellGlobal.
2009-12-18 17:35:48 -05:00
44712c274e Change event handling so Escape always works
Until now LookingGlass could only be closed using the Escape
key when the Evaluator class was active, as the relevant code
was associated to the text input field; this moves it into a
global event handler instead which works everywhere in LG.
2009-12-18 21:53:25 +01:00
1c4c3afb27 Add eject buttons in places menu for places which support it
https://bugzilla.gnome.org/show_bug.cgi?id=602976
2009-12-18 15:12:53 -05:00
e326202477 Use the preferred text editor when opening an extension's .js file
Change "./src/gnome-shell --create-extension" to use "gnome-open"
when opening the newly created .js file, so that it is launched
with the user's preferred text editor, instead of hardcoding gedit.
2009-12-18 20:26:41 +01:00
45f4292259 Make "gnome-shell --create-extension" compatible with Python 2.5
Fallback to using the json-py module on systems with a Python
version older than 2.6 (which introduced native JSON support).
2009-12-18 20:22:51 +01:00
288eae91e2 [ShellAppSystem] Initialize collation keys for info on-demand
In case of duplicate infos structures with the same id, the
info structures we get from looking up the id in app_id_to_info
aren't necessarily the same as those we used to match, so we
can't rely on matching to implicitly initialize info->casefolded_name.

Since the name collation key isn't used in matching results,
just in sorting, init it on-demand in the sorting which is also more
efficient.
2009-12-18 12:36:16 -05:00
f4c05deb2d Completion in alt+F2
Bind <Tab> for command's completion and path's completion.
https://bugzilla.gnome.org/show_bug.cgi?id=597677
2009-12-18 11:31:17 -05:00
1cd9a15ac0 [js/ui/Makefile.am] Install extensionSystem.js 2009-12-18 11:28:39 -05:00
d1edefdc39 Reposition items at start of fade in
We need to set the positions after the animation ends (and
fadeIn starts), not before when allocation is changed.

As the window may still be in motion when the overlay is
repositioned, it is safer to pass the calculated values
as parameters.

https://bugzilla.gnome.org/show_bug.cgi?id=602598
2009-12-18 11:27:21 -05:00
2cb4dfb4a4 [lookingGlass] Add primitive extensions list
In the future this should be more like the Firefox Addons UI
probably with enable/disable/update checking, but stub it out
here for now.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
c0ff0066e6 Make link.js into a St.Button, delete unused link imports
It's actually totally unused at the moment, but a future patch will use it.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
55fbb9d0af [St] Implement text-decoration: [underline|strikethrough]
Move CSS handling of StLabel and StButton for their underlying
ClutterText objects into st_private, and implement support for
the underline and strikethrough St text-decoration properties.

Overline isn't implemented for lack of a corresponding Pango
attribute, and blink, well...

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
c4a49b4de2 Port more to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
aa9d3515a1 Add extensionSystem
Consumer documentation will live at http://live.gnome.org/GnomeShell/Extensions

In terms of implementation; basically we load extensions from the well-known
directories.  Add a GConf key to disable extensions by uuid.  There is a new
option --create-extension for the gnome-shell script which takes a bit of
interactive input, sets up some sample files, and launches gedit.

No extensions UI in this patch; that will come later.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:19:59 -05:00
4394bc3e40 [dash] Avoid infinite recursion in keynav 2009-12-18 10:39:02 -05:00
6b1c3d323b [js/ui/Makefile.am] Install search.js 2009-12-18 10:25:06 -05:00
b7646d18ae Add search.js, rebase search system on top
The high level goal is to separate the concern of searching for
things with display of those things; for example in newer mockups,
applications are displayed exactly the same as they look in the
AppWell.

Another goal was optimizing for speed; for example,
application search was pushed mostly down into C, and we avoid
lowercasing and normalizing every item over and over.

https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:07:22 -05:00
f5f92b2e79 [appDisplay] Unify Inactive/RunningWellItem, split into AppIcon, AppWellIcon
The distinction between the inactive and running was silly; just
have one class which can handle both running states.  However for
a future search patch, we do want a separation between an icon which
just has icon + name + glow, and a well icon which does the menu
integration.

https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:02:19 -05:00
14df7cd62c [StOverflowBox] Vertical box which skips painting underallocated children
https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:01:36 -05:00
c2fe9e57b1 Added Hebrew translation 2009-12-18 00:36:50 +02:00
5a3c3efbeb [ShellDocSystem] Check GTK+ version for constness of argument 2009-12-15 16:29:21 -05:00
a8d18ac18a Limit dash docs to 50
We has poor performance if we try to allocate hundreds of actors;
a bit more ideally, we'd keep pulling as much as we can, but really
no one should have more than 50 in the list as is now except on
unreasonably large screen sizes.

In the future we should change this to be pull-on-demand thing
in a chunked fashion.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 16:08:15 -05:00
949f67469c Rebase recent documents on top of ShellDocSystem
Rather of calling .exists() synchronously for all documents, use
ShellDocSystem's async API to only stat docs we're showing.

Use the doc opening functionality in ShellDocSystem.

Also, more intelligently do redisplay(); don't recreate actors
for recent docs if we already have one for that URI.  We may
need more intelligent caching here; if e.g. just the associated
application changes, we should probably reread the info.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 16:08:12 -05:00
a442dfea14 Add class for handling recent docs
Push some of the JS docInfo down into C; crucially, this lets us
use the GIO async API.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:54:42 -05:00
42757a0c87 Move Main.currentTime() and Main.createAppLaunchContext() into ShellGlobal
Primarily motivated by wanting these functions accessible from C.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:54:38 -05:00
81b7c0170d Add set_skip_paint method
Ideally we'd be able to override _paint, but given that we can't
at the moment, this method gives a way to implement containers
which don't happen to paint all of their children.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:53:08 -05:00
d624db18c5 Add deferred work system
Previously we had various things watching for notify::mapped so
we could be more lazy about updating non-visible actors, but it
was fairly ad-hoc.

The deferred work system unifies these callbacks, and also adds
a timeout so that we don't delay changes arbitrarily; this way we
avoid a storm of work if you stay out of the overview for a while,
then go in.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:53:05 -05:00
b03fa1ebf7 Add missing "fi" to po/LINGUAS 2009-12-11 18:52:17 +01:00
478dba8502 Remove non-existing src/shell-status-menu.c from POTFILES.in 2009-12-11 18:50:44 +01:00
20294f2c92 Updated French translation
Contributed by Pablo Martin-Gomez
2009-12-05 16:44:19 +01:00
34003a1f6b Updated Swedish translation 2009-12-01 23:54:05 +01:00
a4405be71c Add global.log, global.logError functions
These log to a display in lookingGlass; rough equivalent of
the Firebug "console.log".

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-01 15:15:12 -05:00
b6cc9c7ff6 Add functions to dynamically load/unload stylesheets
For implementing extensions, we want the ability to add a stylesheet
dynamically, and unload it as well.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-01 15:00:56 -05:00
368d484dee Avoid variable redeclaration
https://bugzilla.gnome.org/show_bug.cgi?id=603327
2009-12-01 14:54:25 -05:00
7b0526dc5c [chrome] only hide chrome if fullscreen window is on the same monitor
https://bugzilla.gnome.org/show_bug.cgi?id=599926
2009-12-01 12:26:41 -05:00
236a9b184f Updated Brazilian Portuguese translation 2009-11-25 17:25:50 -02:00
6b816fa7dc Replace includes of glib/gi18n.h with glib/gi18n-lib.h
https://bugzilla.gnome.org/show_bug.cgi?id=602802
2009-11-24 15:26:09 -05:00
e2ac769fd1 Bump save timeout to 5 minutes, close output asynchronously
The synchronous close causes us to block in fsync() which has extremely
poor interactivity implications on ext3.

Also, the 5 second timeout was an accidental commit from debugging, 5
minutes is fine.

https://bugzilla.gnome.org/show_bug.cgi?id=602456
2009-11-24 13:22:32 -05:00
dd8f05c81d include "config.h" in all .c files
Also, fix shell-global.c to actually compile with config.h included.

Was supposed to fix bug 602802, but doesn't...
2009-11-24 09:15:35 -05:00
f0e3b87330 Fix disappearing close button
Show the close button after zooming a window in the overview when the
window clone has the pointer focus.

https://bugzilla.gnome.org/show_bug.cgi?id=602772
2009-11-23 19:37:56 -05:00
1d2dc09ede [panel] Port to CSS
With some tweaks from JP St. Pierre to center things in case we ever
have a larger panel.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
73cd9513bd Remove information icon
It wasn't really useful, not obviously in the current mockups, and
depended on button.js.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
907fc2f067 Port AppWell to CSS; delete appIcon.js
The altTab.js and app well code weren't sharing really
any functionality anymore; un-merge the appIcon code back
into appWell, and have a simple icon + text display for
altTab.

Port AppWell to St and CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
2f1ca7bf28 Remove ShellButtonBox, button.js; Use St.Clickable in panel.js
StClickable replaces ShellButtonBox.  Reduce the number of
button-like things by deleting button.js.

To do so, add CSS style for the actitivies button.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
93f3412f70 Import ShellButtonBox as StClickable
Now a StBin, and add hover/active style properties.  Also, add the
event to the CLICKED signal.  Otherwise a straightforward namespace
transformation.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:48 -05:00
f815844eb4 Move ShellDrawingArea to StDrawingArea
It's nicer to have ShellDrawingArea as a St widget so it can
participate more cleanly in CSS styling, such as queuing a redraw
automatically on style changes, and allowing subclasses to use
CSS styling.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:48 -05:00
b0cb8fb85a [Chrome] clean up APIs and remove workarounds
https://bugzilla.gnome.org/show_bug.cgi?id=597044
2009-11-23 13:49:18 -05:00
e9787c0f1e Add params.js, for function param object parsing. 2009-11-23 13:48:59 -05:00
efc291ac5b Switch to confirm dialog when closing
Some applications show a confirm dialog before closing, which the close
button happily ignores.

Detect newly created windows which are transient for the window we try to
close and switch to them.

https://bugzilla.gnome.org/show_bug.cgi?id=602532
2009-11-21 18:18:15 -05:00
1cc78fdf60 Clear text when closing run dialogue
Signed-off-by: Colin Walters <walters@verbum.org>
2009-11-21 15:50:57 -05:00
8c59bc71b0 [dash] Switch to using StWidget gradients
https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-20 19:51:46 -05:00
7b9f5b7643 Implement gradients for StWidget
Rather than having gradients be individually implemented by higher
level JS widgets, move basic gradient functionality into StWidget.
There is prior art in WebKit for CSS gradients:

http://webkit.org/blog/175/introducing-css-gradients/

However, implementing this would be quite a lot of work; all we
need in the Shell design at the moment is basic horizontal/vertical
linear gradients.  So, the syntax now supported is:

background-gradient-type: [vertical|horizontal]
background-gradient-start: color;
background-gradient-end: color;

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-20 19:51:41 -05:00
0bc578230f [workspaces] Add an idle timeout for close button
Add a grace period for the close button so if you happen to move your
mouse outside the target it doesn't vanish and force a Z motion.
2009-11-19 19:39:00 -05:00
bb366f8fbe Window selector refinements
* Remove window icons
 * Add a close button to window previews
 * Position caption underneath the window
 * Port caption from Big.Box to St.Label

https://bugzilla.gnome.org/show_bug.cgi?id=598324
2009-11-19 18:40:44 -05:00
8ac97fe1a0 [StThemeNode] Re-add erroneously deleted (out) annotations
An earlier commit was overzealous in removing (out) annotations;
introspection supports (out) for integral types just fine, we
only need to remove them for (out) types where the caller needs
to allocate a boxed type.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-17 18:43:34 -05:00
2c914374e0 Integer align workspace and pane positioning
We had previously been leaving the scaled workspace at a non-integral
position which didn't look obviously ugly, but now that we're
constraining the popup pane to the workspace size, we really need
to ensure that we're using integral positions here.

https://bugzilla.gnome.org/show_bug.cgi?id=601854
2009-11-16 14:13:14 -05:00
1526500079 [placeDisplay] Fix inverted logic for desktop-is-home case
We only want to hide the Desktop link if it desktopIsHome, not
if it isn't.
2009-11-16 14:13:14 -05:00
9ba5ca0193 environment.js: set default direction for St widgets
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:35 -05:00
3529b8c915 [StTable] now RTL aware
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:29 -05:00
4e8206d60e [StBoxLayout] now RTL aware
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:22 -05:00
a5edc78fac [StWidget] add API support for right-to-left UI
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:09 -05:00
cdd508e12d Darken workspace indicator when doing lightbox effect
Adjust the opacity of the workspace indicator to not having it stand out too badly when in lightbox mode.

https://bugzilla.gnome.org/show_bug.cgi?id=594556
2009-11-16 11:22:46 -05:00
931cbc6ae3 Fix sidebar enable/disable menu item
https://bugzilla.gnome.org/show_bug.cgi?id=601875
2009-11-14 10:31:41 -05:00
ab809faaf0 Updated Slovenian translation 2009-11-14 11:18:02 +01:00
8334b063f1 Deal with title-less windows
https://bugzilla.gnome.org/show_bug.cgi?id=601290
2009-11-13 16:04:17 -05:00
21f15246a6 [genericDisplay] Fix selection not being set correctly
We need to check if the display actor is an instance of Shell.OverflowList
or St.BoxLayout to use the appropriate function for getting its child
with a given index.
2009-11-13 14:49:45 -05:00
050e710770 Use gnome-terminal rather than xterm+xeyes+xlogo in --xephyr mode
https://bugzilla.gnome.org/show_bug.cgi?id=588056
2009-11-13 14:43:10 -05:00
bb63d513fd Add Presence items to the status menu
https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:21:36 -05:00
985d707788 Port ShellStatusMenu to javascript
https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:21:31 -05:00
9ddebf0480 Introspect src/gdmuser
In addition to the Makefile changes, we also change uid_t to gulong in
the public API (which matches how it was already represented in the
gobject properties).

https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:20:45 -05:00
8c05003acf Add gnome-shell --eval-file
Convenience utility function for evaluating an arbitrary
JavaScript file.
2009-11-13 12:45:46 -05:00
7c796b2d2a [shellDBus] Avoid sending undefined over DBus
DBus doesn't have a notion of null/undefined, so do the lame
thing and return the empty string.
2009-11-13 12:45:46 -05:00
48f8e4943d Rename places.js to placeDisplay.js
places.js was renamed in the code
2009-11-12 16:33:03 -05:00
fec2ea5e9c [dash] Convert pane close to St.Button, avoiding release event propagation
The workspaces was handling the release event after closing the pane,
catch it before closing by using St.Button.
2009-11-12 13:09:20 -05:00
4014313910 [dash] Swap More for triangle
In newer mockup.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
06cf6c51f3 [placeDisplay] Port more to CSS, lower spacing
Newer mockups have smaller spacing here.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
426d7bc515 [dash] Port search section headers to CSS
Experimented with moving the (see all) into a tooltip, but
given that we're not emphasizing the drilldown, removed for now.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
bf68f9f0cf [dash] Port section container to CSS, lower spacing
Newer mockup has smaller spacing.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
ce90dda76f [overview] Constrain popup panes, dim workspaces when active
Rather than the popup panes taking up the whole non-panel height,
constrain them to the height of the workspaces, which is also the
"dash content area".

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
66cab3b8ed [genericDisplay+other] Port to CSS, style cleanups
Mostly a straightforward porting of style code to CSS, except
that various bits of other code referenced a few GenericDisplay
constants, so those needed to be ported as well.

Add some padding at the top between the close button and the items.

Center the text and description.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
bc255a525f [overview] Port pane to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
d51384fb86 switch to scrolling GenericDisplay, remove menus from apps
Temporarily removed search-by-menu from apps as well, will readd
later as a ShellApp feature.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
1626e8c09a [StTooltip CSS] Add some style
Not final, but stands out and doesn't look completely wrong, at least.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
263d738ef6 [StTooltip] Fix _get_preferred_width
It was ignoring the label width.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
8040ad61c6 [StBoxLayout] Add missing _queue_relayout in _add_actor
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
057f0effed [StBoxLayout] Add st_box_layout_get_n_children
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
bf7b166237 [StBoxLayout] Add st_box_layout_remove_all, st_box_layout_destroy_children
In a variety of places we're using boxes as data-modeling displays,
and in doing so we often want to either remove the children or
explictly destroy them.

Now ideally Gjs would support callbacks, and this would make using
the for_each functions possible, but even then these functions
are more efficient and shorter to type, at least.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
ae744bf206 Don't require applications to accept URIs for recent files
This should not be required, since glib correctly deals with such
applications by giving them the local gvfs path, and those
applications which do support URIs keep being able to use the URIs in
GFiles.

Based on original work by Guido Günther <agx@sigxcpu.org>.

https://bugzilla.gnome.org/show_bug.cgi?id=601287
2009-11-12 14:25:42 -02:00
af35dea019 [dash] Move BackLink to CSS
The previous commit 626f679947 broke the back links on
search drilldown.

https://bugzilla.gnome.org/show_bug.cgi?id=601413
2009-11-12 11:21:20 -05:00
1b75ae0184 [lookingGlass] Paint border around current result if instanceof Clutter.Actor
It's very convenient to drill down through object properties and
be able to see exactly which portion of the screen those actors
correspond to, without trying to guess with the inspector tool.
2009-11-11 16:36:42 -05:00
07a8d5ed2d When setting a search, do a redisplay immediately
Commit 94bd6f1718 introduced a trick
where we only do the heavy lifting for "redisplay" when we're mapped.

However, the search system wants to get the count of matched items,
and control the visibility of the display based on that.  This introduces
a circularity; avoid it by forcing the search to do a redisplay.

In the future we should avoid this by separating out the "get matched
things for search" from "display list of things".

https://bugzilla.gnome.org/show_bug.cgi?id=600890
2009-11-10 10:19:00 -05:00
2f27f61a1f Remove trailing whitespaces in dash.js
Trailing whitespaces cause warnings.
2009-11-09 17:49:01 -05:00
585bfe5b5a Make places results available in search
Places is one of the dash sections and it should be included in search results.

Factor out the code for getting and updating the information about places from
Places to PlacesManager.

Introduce PlaceInfo class that contains information about the place and can be
used by classes that display it in different ways. Rename classes so that their
names are consistent with corresponding classes in appDisplay.js and
docDisplay.js

https://bugzilla.gnome.org/show_bug.cgi?id=599125
2009-11-09 16:57:49 -05:00
5ee72d807d Updated Arabic translation 2009-11-08 20:56:26 +02:00
fcac7ac0b3 [gnome-shell.css] Remove blue background from scrollbars
This makes it slightly less ugly.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-05 15:39:26 -05:00
dcd7762253 [StThemeNode] Don't give negative width/height for content boxes
If the space we're allocated is too small for our border + padding
constraints, don't give negative allocations to callers.  Squash
to zero.

It isn't really useful for callers to get negative content sizes,
and certainly breaks most allocation code.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-05 15:28:56 -05:00
869e744670 Updated Czech translation 2009-11-05 18:04:36 +01:00
626f679947 Port Dash section headers to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:45 -05:00
4f456b9689 Implement non-uniform borders (when not using corner_radius)
StTheme CSS supports different border widths for different sides.  Implement
it for StWidget by drawing the border internally.  However, we don't support
a nonzero corner-radius with nonuniform borders.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
e2e513ff08 Remove (out) "caller-allocates" annotations
GObject Introspection+gjs doesn't presently support (out) for caller-allocates
scenarios.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
37a948e4eb Add missing allow-none for set_style_pseudo_class
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
b8d9319c32 Add missing allow-none for st_bin_set_child
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
f549269934 [StBoxLayout] Implement raise and lower
Code copied from ClutterGroup.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:11 -05:00
dc232d4631 [AppSwitcher] Add a separator between windows in current and other workspaces.
This make it is easier for the user to figure out on which workspace the
windows are. For instance, terminals related to various activities and put on
different workspaces were previously displayed as an uniform list, with no
visible distinction between the ones from the current workspace and the others.
Now they are physically separated by a thin gray line.

This is also consistent with the way applications are displayed in the
AppSwitcher.

https://bugzilla.gnome.org/show_bug.cgi?id=597944
2009-11-04 19:25:37 +01:00
930a0b52f3 Added Finnish translation. 2009-11-04 11:17:20 +02:00
f14d7f891b Updated Italian translation 2009-11-03 22:29:36 +01:00
01138d55ca Added Romanian translation 2009-10-28 22:39:57 +02:00
2103a4da24 Add shell-global-private.h to Makefile.am
Distribute shell-global-private.h (as a non_gir_sources, since it
includes gjs.h and isn't scannable by gobject-introspection.)
2009-10-28 15:46:46 -04:00
627f86a9dc shell-global-private.h fixes:
- Include private header so shell-global.c compiles
- Move _shell_global_set_plugin to private header
2009-10-28 12:59:01 -04:00
baf823c466 Store GjsContext pointer in ShellGlobal
Future functionality in ShellGlobal needs access to the GjsContext.

https://bugzilla.gnome.org/show_bug.cgi?id=599561
2009-10-28 12:31:58 -04:00
94bd6f1718 Only do redisplay when mapped
If we're not mapped, only queue up a redisplay.  This avoids
e.g. changes in recent documents such as saving a file in GEdit
causing a lot of blocking I/O in the shell (we need to make
recent loading async as well).

https://bugzilla.gnome.org/show_bug.cgi?id=599560
2009-10-28 12:20:02 -04:00
c8b1afbad6 Updated Spanish translation 2009-10-27 23:58:48 +01:00
395f45c570 Updated Spanish translation 2009-10-27 21:37:46 +01:00
3ebb0f149d Removing all favorites makes it impossible to add new ones
Show the placeholder when all favorites are gone.
https://bugzilla.gnome.org/show_bug.cgi?id=591854
2009-10-27 11:32:30 -04:00
6d9aadfa4d Add emacs modelines to all .c and .h files that were missing them 2009-10-27 11:27:45 -04:00
22e26bea8f Updated Slovenian translation 2009-10-26 14:47:54 +01:00
d9ff1f2ec1 [ShellApp] Ignore removal of windows we're not interested in
Previously shell_app_remove_window assumed that it was being
passed a window in its list; rather than having callers check
whether a window is interesting and only if so removing it
from the app, just ignore removal of windows we aren't interested
in, like how we ignore addition of windows we already have.

https://bugzilla.gnome.org/show_bug.cgi?id=598502
2009-10-23 13:19:29 -04:00
10991d363d [ShellWindowTracker] Create fallback apps again
Creating window-based apps got lost in the code refactoring.
2009-10-23 12:26:05 -04:00
0c37a5bd6f [AppIcon] Keep glow up to date directly
AppWell was changed to only do updates on application running state
changes, so we need to update the glow on window count changes.

https://bugzilla.gnome.org/show_bug.cgi?id=599412
2009-10-23 10:59:05 -04:00
369e0c2c6f [ShellApp] Signal windows-changed when removing a window
https://bugzilla.gnome.org/show_bug.cgi?id=599412
2009-10-23 10:59:04 -04:00
17c8173640 Fix minimum height request, handle 0 allocation better
First, fix a problem where though we intended to request a minimum
height of 0 for the docs content, we were actually requesting
spacing for all items.

On low resolution screens, we were still attempting to allocate
an item even when we were given 0 height.

https://bugzilla.gnome.org/show_bug.cgi?id=596984
2009-10-22 22:08:56 -04:00
8fd00ac6cc [AppSwitcher] misc refinements
https://bugzilla.gnome.org/show_bug.cgi?id=597900
2009-10-22 12:14:24 -04:00
4f4e54cbf7 Reset page when doing a FULL redisplay
This fixes an issue where the app display would remember the page
between switching menus.

https://bugzilla.gnome.org/show_bug.cgi?id=597577
2009-10-21 17:50:35 -04:00
16cb878f4e [docInfo] Pass correct object to remove deleted info
We need to pass the actual RecentInfo boxed, not the DocInfo JS Object.
2009-10-21 17:34:52 -04:00
d5adfa6445 Updated Danish translation 2009-10-21 22:51:10 +02:00
8e9549c6f1 [AppSwitcher] Reimplement the separator using St.Bin
This way it can be styled using CSS.
This can help to fix bug 597362.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:19:46 +02:00
7239eb2f90 [StThemeNode] Add support for 'width' and 'height' CSS properties.
The behavior in respect to borders matches CSS - the properties set the size of
the content exclusive of the borders (CSS3 box-sizing property - not implemented
here - changes this).

min-width/min-height correspond very closely to the CSS meanings.

width/height are a little different from the CSS meanings - the CSS meaning is
"exactly this size unless overridden by min/max-width/height" - but within the
realm of our layout algorithm, making them control natural size is pretty
close.

This way we can force elements to have a fixed natural or minimum size.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:18:32 +02:00
5b769138b6 [StThemeNode] round padding values intead of truncating them.
This way, 49.9999 will end up as 50 instead of 49.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:17:28 +02:00
81d579aca0 Disconnect from window signal handlers when removing a window
We need to remove all of our signal handlers attached to a window
when being disposed.

https://bugzilla.gnome.org/show_bug.cgi?id=598502
2009-10-21 11:44:07 -04:00
7548f2d71e [ShellWindowTracker] Don't skip "uninteresting" windows for focus
For the purposes of determining which application is focused, don't
skip "uninteresting" windows.  The old get_focused_window code
was used for usage tracking, but here we want reliable application
association.

Also convert a .text= to .set_text that was missed with the last
patch.

https://bugzilla.gnome.org/show_bug.cgi?id=599206
2009-10-21 11:30:13 -04:00
bda7d3994b [appIcon] Fix reference error when favoriting an app 2009-10-20 18:50:18 -04:00
a336ed79ae [panel] Work around Clutter bug causing missing name
The .text property doesn't queue a resize, see:
http://bugzilla.openedhand.com/show_bug.cgi?id=1851
2009-10-20 16:52:57 -04:00
416fbc775e add appFavorites.js to js/ui/Makefile.am 2009-10-20 15:09:23 -04:00
e941e8088b Split ShellAppMonitor into ShellWindowTracker, ShellAppUsage
The two parts were mapping windows to applications, and
recording application usage statistics.  The latter part
(now called ShellAppUsage) is much more naturally built on top of
the former (now called ShellWindowTracker).

ShellWindowTracker retains the startup-notification handling.

ShellWindowTracker also gains a focus-app property, which is
what most things in the shell UI are interested in (instead of
window focus).

ShellAppSystem moves to exporting ShellApp from more of its
public API, rather than ShellAppInfo.  ShellAppSystem also
ensures that ShellApp instances are unique by holding
a hash on the ids.

ShellApp's private API is split off into a shell-app-private.h,
so shell-app.h can be included in shell-app-system.h.

Favorites handling is removed from ShellAppSystem, now inside
appFavorites.js.

Port all of the JavaScript for these changes.

https://bugzilla.gnome.org/show_bug.cgi?id=598646
2009-10-20 12:55:07 -04:00
77cf9ae077 Added Greek translation 2009-10-20 13:49:40 +03:00
358175e998 Added el to po/LINGUAS 2009-10-20 13:48:21 +03:00
7f5c600133 Use a fixed ordering for well-known icons
Define the ordering for well-known icons; see
the page http://live.gnome.org/Features/StandardIconOrdering

https://bugzilla.gnome.org/show_bug.cgi?id=598313
2009-10-19 14:57:02 -04:00
56bcdd41fd Updated German translation 2009-10-18 11:36:34 +02:00
cd33dc7f22 Annotate list setters
Without these bindings don't know the type of list elements.

https://bugzilla.gnome.org/show_bug.cgi?id=598691
2009-10-16 16:04:46 -04:00
2eef17bcdc [.gitignore] Add *~, .patch 2009-10-16 11:50:29 -04:00
79a614240b [ShellApp] fix app/window sort order
The window lists were not being resorted when user-time changed, and
the app list was mistakenly "penalizing" apps for having *any*
minimized windows, rather than for having *only* minimized windows.

https://bugzilla.gnome.org/show_bug.cgi?id=598389
2009-10-16 11:15:21 -04:00
7c954898a2 Support fixed position children
When doing layout, check for whether x/y have been explicitly
specified, and if so honor those positions.

https://bugzilla.gnome.org/show_bug.cgi?id=598462
2009-10-15 17:40:58 -04:00
497c74f4d8 Minor code cleanup: use child variable consistently
Preparation for a subsequent patch.

https://bugzilla.gnome.org/show_bug.cgi?id=598462
2009-10-15 17:40:58 -04:00
51c41aed90 [workspaces] Don't crash trying to get an icon for untracked app
Use ShellApp directly rather than trying to handle null-safety
with .get_info().
2009-10-15 17:31:57 -04:00
d705c1bb52 [ShellApp] Fix handler signature for workspace switch
This was causing crashes or undefined behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-15 14:05:19 -04:00
d9df7c1b1e [AppWell] Fix D&D for ShellApp
The drag and drop case needed to be updated to use ShellApp
correctly.  Export _is_transient for better compatibility.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-15 13:24:19 -04:00
49eb687713 Updating for Punjabi by A S Alam 2009-10-15 06:20:34 +05:30
7bec02dcb1 [AppWell] Don't duplicate running+favorite
Regression introduced with previous patch.
2009-10-14 15:36:58 -04:00
38c06ca837 Create ShellApp, rebase things on it
Previously, we had ShellAppInfo, which contains fundamental
information about an application, and methods on ShellAppMonitor
to retrieve "live" information like the window list.

AppIcon ended up being used as the "App" class which was painful
for various reasons; among them that we need to handle window
list changes, and some consumers weren't ready for that.

Clean things up a bit by introducing a new ShellApp class in C,
which currently wraps a ShellAppInfo.

AppIcon then is more like the display actor for a ShellApp.  Notably,
the ".windows" property moves out of it.  The altTab code which
won't handle dynamic changes instead is changed to maintain a
cached version.

ShellAppMonitor gains some more methods related to ShellApp now.

In the future, we might consider changing ShellApp to be a GInterface,
which could be implemented by ShellDesktopFileApp, ShellWindowApp.

Then we could axe ShellAppInfo from the "public" API and it would
return to being an internal loss mitigation layer for GMenu.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-14 14:37:34 -04:00
6623ca1287 Bump version to 2.28.1 2009-10-14 17:03:18 +01:00
d1bdd6f11d [search] Finish queued search on Return
If we had a pending search processing, finish it when the user
activates the entry.

This is a small conceptual change; the large diff is simply
moving the search implementation (unedited otherwise) from
an anonymous inline to a named function so it can be called
sanely in _activate.

https://bugzilla.gnome.org/show_bug.cgi?id=598111
2009-10-13 16:57:39 -04:00
39edf54aa9 Scroll to bottom when pushing a result
This makes the evaluator significantly more useful past a few
results.

https://bugzilla.gnome.org/show_bug.cgi?id=597919
2009-10-13 13:10:43 -04:00
aa9c585562 Updated Arabic translation 2009-10-13 15:24:40 +02:00
8b813060f0 Update Catalan translation 2009-10-10 20:25:51 +02:00
ca263dade5 Updated Czech translation 2009-10-10 19:03:47 +02:00
b8ef9cdf4b Updated Italian translation 2009-10-10 12:39:44 +02:00
aa92c6fdf5 Add Russian translation
Based on the initial translation from Sergey V. Kovylov and additional
feedback from Andrey Korzinev.
2009-10-09 18:19:06 -04:00
3af8130fff Add places.js to POTFILES.in
places.js was missing.

Reordered files alphabetically.
2009-10-09 18:09:34 -04:00
ab0460ad59 Use clutter_actor_destroy in dispose, add _dispose where needed
ClutterGroup calls _destroy, but most of St was just calling _unparent.
This caused problems because the DESTROY signal was not emitted
for child elements after destroying a toplevel.  Also, in a GC'd
binding it would cause unpredictable lifetime of children.

Some St widgets simply didn't have _dispose at all; implement it.

Note because of the usage of the background_image in StButton,
we can't cleanly destroy it inside the StWidget.

https://bugzilla.gnome.org/show_bug.cgi?id=597845
2009-10-09 16:19:33 -04:00
a27c29f4fc Improve capitalization
"Add to Favorites" and "Remove from Favorites" menu options should be
capitalized throughout.
2009-10-09 00:33:33 -04:00
212d5c1954 Add missing files to POTFILES.in; add a translation hint
POTFILES.in was missing some files.

"Activities" is not easily translatable into some languages, e.g. Russian,
so suggest using the word for "Overview" instead.
2009-10-09 00:30:10 -04:00
8929f43ad9 [AppSwitcher] Fix hiding the arrow on application change.
The down arrow is shown when an application with more than one
window is selected, but the window list is not always displayed.

This patch fixes the fact that the arrow was not hidden when one
focus an app with a single window when coming from an app with
multiple windows, if the window list was not displayed.

https://bugzilla.gnome.org/show_bug.cgi?id=597791
2009-10-08 13:56:47 +02:00
a26b0b60d1 Fix srcdir != builddir build of St.gir
We need to use st_cflags which has -I$(srcdir) not ST_CFLAGS
when building St.gir.
2009-10-07 19:32:00 -04:00
60dbb19c2d Reference Meta-2.28.gir
Now that Mutter has been bumped to 2.28.0, we need to reference
Meta-2.28.gir not Meta-2.27.gir.
2009-10-07 19:27:17 -04:00
3703a86354 Add run-test.sh to CLEANFILES
Fix distcheck by adding run-test.sh to CLEANFILES
2009-10-07 19:18:43 -04:00
992b43f914 Bump version to 2.28.0 2009-10-07 19:07:05 -04:00
ff39edd1ee Deal with unknown flags from ClutterEvent.get_state()
When we get a ClutterModifierType from Clutter, it might contain
bits not in the enumeration. See bug 59771 for a similar problem
with GdkModifierType.

Add a wrapper Shell.get_event_state() around clutter_event_get_state()
to mask these bits out and only return approved bits.

https://bugzilla.gnome.org/show_bug.cgi?id=597735
2009-10-07 17:22:37 -04:00
a81a16801d Fix overview to show on the correct monitor
When tweening the overview in, tween it to appear on the correct
position of the primary monitor, not at (0,0); position
the 'backOver' actor to cover all monitors properly.

Reported by Rui Matos

https://bugzilla.gnome.org/show_bug.cgi?id=597721
2009-10-07 17:14:56 -04:00
4c6f770dea Fix positioning of the Calendar on multihead
Parens were in the wrong place, resulting in the calendar not
being properly centered on the primary monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=597078
2009-10-07 14:52:49 -04:00
c0b01c0210 Match on menu category during application search
Being able to display all applications in a category based on the search
string with a category name is generaly useful.

Prepare all the applications that match a search term based on their
category name up-front.

Remove unused this._appCategories and a call to non-existing
itemInfo.get_categories()
2009-10-07 14:28:49 -04:00
400326e549 Add docs and (transfer none) to st_widget_get_theme_node()
st_widget_get_theme_node() was missing the (transfer none)
GObject Introspection causing crashes. Add that and document the
function.
2009-10-07 14:26:14 -04:00
d7af6d40e3 [AppSwitcher] Use thumbnails instead of a window menu, and other UI changes
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-07 14:00:43 -04:00
90ebcd32e3 Fix exception when showing menu for not-running app
Need to check windows.length before checking first window.

https://bugzilla.gnome.org/show_bug.cgi?id=597466
2009-10-06 17:19:36 -04:00
53d0581377 Don't process the first click on Activities button for a timeout period after the hot corner was triggered
This avoids opening and closing the overview when the hot corner is triggered
and the activities button is clicked.
2009-10-06 16:58:30 -04:00
439daf828f [AppSwitcher] add a workaround for a gjs problem with GdkModifierType
gdk_display_get_pointer() sometimes returns values for the mask that
aren't part of the GdkModifierType enumeration, which gjs doesn't like
(bug 597292). Work around that by adding a C wrapper that strips out
the extra flags.

https://bugzilla.gnome.org/show_bug.cgi?id=597559
2009-10-06 16:07:37 -04:00
d120d03de9 Workaround being allocated 0x0
Because of a chain of bugs we could end up getting allocated 0x0,
and this would cause the WellGrid allocation code to be unhappy.

See http://bugzilla.openedhand.com/show_bug.cgi?id=1831

Simply treat 0 as "unlimited" i.e. equivalent to -1.

https://bugzilla.gnome.org/show_bug.cgi?id=597586
2009-10-06 15:12:20 -04:00
53fbabe2ca Use GtkIMContext instead of ClutterIMContext
Add StIMText, which is a drop-in replacement for ClutterIMText but
uses GtkIMContext instead of ClutterIMContext.

StIMText doesn't have preedit support (would need ClutterText
changes), so isn't going to be useful for complicated input methods,
but is good enough to get dead keys and similar working.

entry.js: Simple test case of StEntry
gnome-shell.modules: Remove clutter-imcontext module

https://bugzilla.gnome.org/show_bug.cgi?id=597471
2009-10-06 14:48:32 -04:00
4bdd40911f Disconnect from window user time notifications, only sort when mapped
Before we were badly leaking AppIcons by not disconnecting from the
window signal handlers when our actor got destroyed.  This caused
us to repeatedly re-sort the windows for each AppIcon that
had ever been displayed with obvious bad consequences.

Besides simply chaining the signals to the lifetime of the AppIcon
actor, we also only do the sorting if we're mapped.  This decreases
the amount of work to do in the not-mapped case.

https://bugzilla.gnome.org/show_bug.cgi?id=597120
2009-10-06 12:49:43 -04:00
ff4ac0d02e [AppIcon] Improve shell_draw_box_pointer()
Add a new enum type for the pointer direction, rather than abusing
ClutterGravity, and implement the missing directions.

https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-06 09:53:47 -04:00
45dd342cc0 [AppIcon] redo constructor to take a params object, add "size" param
Add a "size" parameter to allow changing the AppIcon size, and then
simplify the constructor by taking an object with parameters like
gobject-introspection constructors do, rather than taking a large
number of miscellaneous arguments.

https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-06 09:53:42 -04:00
e5efecd2bd [AppIcon] compute the sorted window list even if not doing the menu
https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-05 22:35:05 -04:00
3bf88b8988 Run dialog: Make error message translatable
Allow the error message to be translated.

https://bugzilla.gnome.org/show_bug.cgi?id=597422
2009-10-05 23:53:50 +02:00
4ddc1118bb Work around libcroco < 0.6.2 parsing bug for 'rgba'
To work around a problem where libcroco < 0.6.2 can't handle
functions starting with 'r' or 'u', preconvert 'rgba' to 'RGBA'
when parsing stylesheets and then check for rgba()
case-insensitively.

(libcroco is uniformly case-sensitive, though the CSS spec requires
that ASCII should be handled case-insensitively.)

https://bugzilla.gnome.org/show_bug.cgi?id=597054
2009-10-05 16:25:38 -04:00
fd1e7b2a0f Places: Add padding between "Connect to.." and devices section
Add padding after "Connect to.." to make the list look consistent when devices
are connected.

https://bugzilla.gnome.org/show_bug.cgi?id=597423
2009-10-05 22:24:04 +02:00
aed1e67add Check that no new term was introduced before doing a subsearch
We combine search terms with OR, so if a new search term is introduced,
the search results are no longer a subset of the previous search results.
2009-10-05 13:50:58 -04:00
dc99e8ffcd [AppSwitcher] Change separator color
https://bugzilla.gnome.org/show_bug.cgi?id=597362
2009-10-05 13:13:21 -04:00
6a8b50cb00 Don't create multiple copies of the (+) button
Currently we recreate it every time Main.overview.show() is called,
 so destroy it to avoid having multiple copies floating around.

https://bugzilla.gnome.org/show_bug.cgi?id=597309
2009-10-05 18:54:41 +02:00
edb50d5dc7 String formatting: Fix warning
Fix to not trigger a warning like:

JS ERROR: !!!   WARNING: 'anonymous function does not always return a value'

by adding a return ""; at the end of the anonymous function.

https://bugzilla.gnome.org/show_bug.cgi?id=595661
2009-10-05 17:59:33 +02:00
2f6c951997 Avoid doing expensive work when not mapped
For some unknown reason we were connecting to app-added and
app-removed on ShellAppMonitor in the AppDisplay class, which
never made any use of the data.  Simply don't connect to those
signals for now.  In the future we should have AppDisplay
be using the AppIcon class which will more correctly handle
dynamic changes.

In the AppWell, avoid doing the full relayout until we're
actually mapped.

https://bugzilla.gnome.org/show_bug.cgi?id=597169
2009-10-05 11:32:33 -04:00
64cd51667d Add String formatting
Add String formatting by extending the String object with a
format method.

Now we can do stuff like "Text: %s, %d".format(somevar, 5)

This is required for proper translation of some strings.

https://bugzilla.gnome.org/show_bug.cgi?id=595661
2009-10-04 23:37:33 +02:00
caa08f27fa Updated German translation 2009-10-04 18:52:10 +02:00
26015ef16d Select next window from the current app on alt+tab
This slightly changes the behaviour of the alt+tab window, this way:
when using alt-tab on a workspace that contains two or more windows from
the same window, the application selected when hitting alt+tab is the
currently selected application, but the highlighted window is the next
one.

Intended goal is to make it easier to cycle around windows of the same
application while not having to cycle through all the applications first.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-04 12:45:23 -04:00
4798ad5107 Consider workspace when sorting windows in menu.
By sorting the windows in the current workspace first, we ensure that
when using alt+tab to switch windows, we will pick a window on the
active workspace as the default focused window for the application if
the application has at least one window on the current workspace (that
is, if it is on the left of the app switcher separator).

This makes the behaviour of alt+tab more predictable for the user, as
an user will expect alt+tab to switch to the window he/she can see right
now rather than the one on the workspace he just left (presumably to do
something else on the workspace he's currently on).

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-04 12:45:19 -04:00
9b05304c2d Use better fitting color for non ARGB tray icons
Currently we use 0xefefefff as a background color for non ARGB tray icons,
which looks out of place (i.e does not fit the panel's background gradient).

Change it to 0x0b0b0bff to fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=597148
2009-10-04 10:02:37 +02:00
795feca393 Updated Arabic translation 2009-10-03 19:20:25 +02:00
31663dcd83 Updated Norwegian bokmål translation. 2009-10-03 10:48:19 +02:00
2f2df61093 Cache applications for a menu
Rather than recomputing this each time someone asks, have a
cache of the apps for a given menu.

https://bugzilla.gnome.org/show_bug.cgi?id=597167
2009-10-02 19:30:42 -04:00
3b8d53060d Immediately pop up menu on right click
We were actually showing a menu on button 3 before, but only
through a chain of coincidences.  This patch explicitly supports
it and makes sure we show it immediately rather than after
a timeout. Pass the activating button in so that we only pop
down on that button.

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
c5ce405859 Ignore releases of buttons other than the activating button
Before we hardcoded popdowns to only button 1 before. But we need
to actually pop down on the release of the activating button.
(Once the button is released, if the we don't pop-down the menu,
then subsequently we let the user use any button.)

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
b3a5fc72fb Add Add/Remove from favorites menu, unify lists more
Also have inactive applications pop up a menu.

Add/Remove from favorites is now in the menu.

Concatenate the favorites/not-favorites instead of having a gap only
if you happened to have a not-divisible-by-4 number of favorites.

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
8a2cc11cc0 Fix rundialog not closing for internal commands
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=597076
2009-10-02 14:18:51 -04:00
cbb3a3aec8 Fix make dist by including all the private files and the tests in the tarball 2009-10-02 17:02:25 +01:00
e382da9708 [AppSwitcher] Update colors/border
Switch from Big.Box to St.Bin and update styling per latest spec

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 09:04:04 -04:00
ab1fbbde92 add a missing (optional) ";" 2009-10-02 08:49:22 -04:00
5f5266ca60 [AppSwitcher] Display a separator between apps on this workspace and others.
This makes a visible distinction between the apps that only have minimized
windows on the current workspace and the ones that have no window on the
workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 14:17:00 +02:00
68e8b14b8b [AppSwitcher] Use GenericContainer instead of BigBox.
This allows defining some custom policy for size allocation.
Currently, the minimum width is always used, but it can be tweaked
afterwards when a sizing policy has been defined.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 14:15:01 +02:00
abdd8b330c Don't show all sections each time the search is updated
We shouldn't show all sections each time the search is updated because that
breaks viewing search results for a single section and flickers headers for
sections with no results.
2009-10-01 18:21:27 -04:00
eb8176deeb Fix regressions in the item displays
Fix displaying documents in the document browse and refreshing the selection
when the results have changed.

Make sure we are passing the appropriate flag to _redisplay() in GenericDisplay.

Make sure we set this._appsStale to true if there was a change in the
applications set.

Don't call _refreshCache() from the AppDisplay constructor.

Don't short-circuit the call to _refreshCache() from _redisplay() on initial load.

Rename _redisplayFull() to recreateDisplayItems() and remove adding an
actor to the actual result list in _addDisplayItem() because we redo adding the
actors to the list in _redisplayReordering() anyway to ensure that we add
them in the right order.

Based on a patch from Colin Walters.
2009-10-01 17:41:17 -04:00
956f89f377 Add dep of clutter on gir-repository to moduleset
Clutter requires Pango.gir. Until Pango is universally available
in a version that builds its own GIR, Pango.gir is built as part
of gir-repository.

(Found by Adel Gadllah)
2009-10-01 17:34:28 -04:00
1c69380923 [AppSwitcher] Put apps with no window on current workspace at the end.
Following the idea expressed in bug 590563 by mccann ("Minimized or
hidden applications should appear at the end of the list"), we should
also put applications that have no visible window in the active
workspace at the end of the alt-tab window list, after apps which have
minimized windows in the active workspace.
2009-10-01 23:25:15 +02:00
d2bc7b200e Update Catalan translation. 2009-10-01 23:23:54 +02:00
afb3b1e718 Fixes for Calendar widget
Miscellaneous fixes from review:

- Distribute calendar.js and the interactive test
- Make the pointless protection against leap seconds actually work
  by starting in the middle of the day so that forward/back always
  move a day.
- Use a variable instead of an inline '8' to know where to start
  when removing old day actors.
- Remove a stray comment from the test

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 16:48:24 -04:00
061a2cfbfb Add scroll-wheel support to the calendar
Make the calendar reactive and handle scroll events to change the month.
(GtkCalendar and hence the old gnome-panel calendar supported this and
it is apparently a handy way to flip through months.)

The padding is moved from the CalenderPopup to the Calendar so that the
scroll region extends all the way to the edge of the popup.

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 16:48:24 -04:00
243824ab80 Replace "round(x)" with "(int)(0.5 + x)"
round() is a C99 addition, so causes portability problems:
different C library versions require different #defines to
enable it. So simply avoid using it.
2009-10-01 22:39:04 +02:00
90ddad7ba1 Make Connect string translatable
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=597038
2009-10-01 16:11:33 -04:00
20b29ff48f Sync clone stacking order with MetaStackTracker
Previously, we initialized actor stacking order from the return
value of global.get_windows() once, which is defined to be in
stack order.  However it was not updated later.  Furthermore,
the way stackAbove was called from onAnimationComplete in
WindowClone was highly dubious, since there are lots of animations
which apply to the clones, and we want the stacking to be right
all of the time, not when some animation completes.

Fix this by connecting to 'restacked' on the screen and syncing
the clones.

I also snuck in another bugfix here; we weren't disconnecting
from the 'showing' signal handler, which had various bad
consequences.

https://bugzilla.gnome.org/show_bug.cgi?id=596263
2009-10-01 15:59:05 -04:00
96f4d318c5 Add libcroco to gnome-shell-build-setup.sh
Check for the new build dependency "libcroco" when running on any
of the distros supported by the script.
2009-10-01 21:57:53 +02:00
6f7da264ba Support LinuxMint in the build script
LinuxMint is based on Ubuntu, so can be handled with the
same package list as Debian and Ubuntu.

https://bugzilla.gnome.org/show_bug.cgi?id=596447
2009-10-01 15:40:04 -04:00
640e45c12a Make gnome-shell depend on clutter-imcontext
The gnome-shell module requires clutter-imcontext to build.
2009-10-01 15:05:18 -04:00
04e28cd7c4 Add a calendar pop-down to the clock
js/ui/calendar.js: Generic calendar widget
tests/interactive/calendar.js: Basic test of the calendar

js/ui/panel.js: Add a pop-down from the clock that shows a
  calendar widget. The pop-down is not menu-like to allow the user to
  interact with an application while looking at the calendar.
gnome-shell.css: Add theming for calendar, calendar popup, and for
  buttons on the panel

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 15:05:11 -04:00
2cc41c6726 StButton: Fix property enumeration names
Property enumeration names should correspond exactly to the property names;
in particular the ACTIVE vs :checked disparity was confusing reading the
code.

http://bugzilla.moblin.org/show_bug.cgi?id=6504
2009-10-01 14:46:33 -04:00
03a45b665c testcommon.css: Don't theme all buttons
StButton is used for many things - scrollbar steppers, etc. Theming
all buttons to look like push-buttons breaks that. So in testcommon.css
just theme a .push-button class to look vaguely button-like.

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 14:46:33 -04:00
5a42179a96 Port StTable to StThemeNode
Convert the StTable code from StStylable to StThemeNode. The
:row-spacing and :col-spacing GObject properties are converted
into spacing-rows and spacing-columns style properties.

A new interactive test is added for StTable.

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
af3ec56ca1 Handle adding children to StTable from Javascript
Remove the StTable specific methods to add actors:

 st_table_add_actor()
 st_table_add_actor_with_properties()

Since they shadow the generic ClutterContainer add_actor() method,
and patch in our add() convenience function as we do for
StBoxLayout.

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
289b19aa31 Import MxTable as StTable
Import table code from Mx library

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
91eb613d69 Turn StBoxLayout:spacing into a style property
Remove the StBoxLayout:spacing GObject property, and instead make
BoxLayout look up the spacing from the CSS style. This makes it
consistent with padding and will allow the use of units. (The
removal of the GObject property entirely instead of making it an
override is consistent with how we handle color, font, padding, etc.)

https://bugzilla.gnome.org/show_bug.cgi?id=596803
2009-10-01 14:46:32 -04:00
1c7c53d19f lookingGlass: Get font from GConf
Instead of using "Monospace", pick the users configured monospace font
name up from GConf. (This is a nice touch, but is more done here to
demonstrate that we can do it rather than for any great utility.)

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:46:32 -04:00
d4304495c6 Port LookingGlass console to ST widgets
* Style aspects like colors and fonts are moved into gnome-shell.css.
* Scrolling is adding using StScrollView.

Based on a patch from Colin Walters
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:46:32 -04:00
b77b205d37 Add clutter-text properties to StEntry and StLabel
Add clutter-text properties to allow getting access to the underlying
ClutterText actor. This corresponds to the get_clutter_text() methods.

The PROP_LABEL and PROP_ENTRY enum values are renamed to PROP_TEXT to
match the names of the properties that they correspond to, and the
properties of StEntry are reordered into alphabetical order.

Based on a patch from Colin Walters
https://bugzilla.gnome.org/show_bug.cgi?id=591245
http://bugzilla.moblin.org/show_bug.cgi?id=6313
2009-10-01 14:41:20 -04:00
a15205e6c4 Fix interaction of borders/background and scrolling
StBoxLayout: Make consistent that the area scrolled and clipped
to is the content area (excluding borders and padding.) Translate
back appropriately when chaining up so that the parent background
is drawn at the right place and picking on the box (if it's reactive)
picks at the right place on the screen.

clip-to-allocation is removed from StScrollView since it's just
not right - if the child has any non-moving elements, like headers or
borders, it will need to set a narrower clip. And even if the entire
child scrolls, we want to clip to an arrow that excludes the scrollbars.

https://bugzilla.gnome.org/show_bug.cgi?id=595997
2009-10-01 14:41:19 -04:00
28dbf7a06e Allocate children as wide as the scrolled area
When we are scrolling a vertical box horizontally , children should be
allocated horizontally as wide as the full horizontal scrolled area,
not just to the size of the "viewport". Similarly for a horizontal box.

http://bugzilla.moblin.org/show_bug.cgi?id=6312
https://bugzilla.gnome.org/show_bug.cgi?id=595996
2009-10-01 14:41:19 -04:00
1ec8e9eb6b Allow StBoxLayout to shrink down to its minimum size
When a StBoxLayout is allocated a size less than its natural size,
think "shrink" needs to be divided among the children that have
a smaller minimum size than natural size.

This is done by preferentially shrinking the children that are most
expanded from their minimum size and then increasing that set of
children until we've found enough total shrink.

A new method is used of allocating children at integral sizes - instead
of rounding the per-child extra amount to an integer (which causes
cumulative round-off errors), compute the position as we go along in
floats and round individually for each child widget.

Extend the box-layout test to include of a test of a box being set
to various widths, starting quite narrow.

http://bugzilla.moblin.org/show_bug.cgi?id=6311
https://bugzilla.gnome.org/show_bug.cgi?id=595995
2009-10-01 14:41:19 -04:00
fa09f7a6da Don't count not-visible children among expand children
When counting how many children we should divide extra space among,
don't count not-visible children.

http://bugzilla.moblin.org/show_bug.cgi?id=6310
https://bugzilla.gnome.org/show_bug.cgi?id=595995
2009-10-01 14:41:19 -04:00
d67e54d3ee Don't use the default stage when setting up adjustments
If the actor isn't in a stage, then setting up the adjustment
based on the actor's size (which we can't compute) and the
size of the default stage (which isn't relevant), doesn't make
sense. Just use arbitrary default values.

The adjustments will be updated to reasonable values when first
the box is first allocated.

It's not entirely clear to me why we ever want to compute the
adjustment settings this way; perhaps we should always use
default values.

http://bugzilla.moblin.org/show_bug.cgi?id=6307
https://bugzilla.gnome.org/show_bug.cgi?id=595996
2009-10-01 14:41:19 -04:00
d263c12e2e Match CSS for background extents
The CSS specification says that the background extends to the
edge of the border (settable in CSS3 with border-clip), make
BigRectangle match this by computing an "effective border color"
as 'border OVER background'.

(If we don't want this behavior - e.g., to be able to use the
transparent borders as margins, then alternatively transparent
border handling would have to be fixed in st-widget.c, since
prior to this transparent and translucent borders were handled
differently.)

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
4d55ccff39 Rename StThemeImage to StBorderImage
The current CSS3 border-image is close to a superset of what we were
doing for -hippo-background-image. Woot! rename StThemeImage to
StBorderImage and change parsing to look for:

 border-image: <url> <number>...

Rather than

 -st-background-image: <url> <length>...

percentanges for the border sizes are not currently supported, neither
are the keywords for handling of the middle part. We always do 'stretch'
for now.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:19 -04:00
2a0adc0fc8 Add support for colored borders
Use BigRectangle to draw the border and background if there's
a border width or border radius and no border image. (Only
uniform borders are supported for now with some deviations
from the CSS model noted in the comments.)

The background color and image parameters are removed from
StWidget's draw_background() method since they were not used
for StButton (the only current user) and the encapsulation
break that they presented caused some minor problems.

Add a test case for borders, and also use borders to style
the buttons in the 'inline-style' test case.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
076e902b2c Centralize computations of border and padding into StThemeNode
Rather than repeating the computation of borders in many different
widget subclasses, add helper functions:

 st_theme_node_adjust_for_height()
 st_theme_node_adjust_preferred_width()
 st_theme_node_adjust_for_width()
 st_theme_node_adjust_preferred_height()
 st_theme_node_get_content_box()

That are used in get_preferred_width()/get_preferred_height() and
allocate() methods to consistently apply the necessary adjustments.
This allows removing the StPadding type.

Queueing a relayout when the borders/padding change is moved from
st_widget_real_style_changed() to the invoking code to allow access
to the old StThemeNode for comparison. (Should this be added as
a parameter to the signal?)

Borders are included in the geometry adjustments, but borders
are not yet drawn.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
8c72623da3 StThemeNode: Add border-radius support
Add support for parsing and caching the border-radius property.
Different radii for the 4 corners are supported; elliptical corners
are not supported.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:18 -04:00
1fd25573e5 Fix problems with 4-sided padding: specifiers
The test for identifying such a specifier was wrong, and the last
value was assigned to the wrong sides.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
6527dbc8b7 Add support for inline styles
Add support for passing an inline-style string when creating a
StThemeNode.

Hook this up to a new 'style' property of StWidget.

Add a test case that demonstrates using this to update font sizes
on the fly.

https://bugzilla.gnome.org/show_bug.cgi?id=595991
2009-10-01 14:41:18 -04:00
3c646ec516 run-test.sh: support running tests under gdb
As with the 'gnome-shell' -g/--debug can be passed to run under
the debugger.

https://bugzilla.gnome.org/show_bug.cgi?id=595987
2009-10-01 14:41:18 -04:00
a9fd350396 Port our imported parts of Mx to ShellTheme
ShellTheme replaces both StStyle and ccss_stylesheet_t.

The interface StStylable is replaced by usage of ShellThemeNode.
A concrete node class allows some significant optimizations of property
inheritance that would have been much more difficult to achieve with
the highly abstract pair of StStylable and ccss_node_t.

Some operations that were previously on StStylable (like the
::style-changed signal) are directly on NtkWidget.

Custom properties are no longer registered as param-specs; instead you
call directly into shell theme node to look up a length or color:

shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);

The dependency on libccss is dropped, while preserving all existing
functionality and adding proper parsing and inheritance of font properties
and proper inheritance for the 'color' property.

Some more javascript tests for CSS functionality are added; workarounds for
a CSS bug where *.some-class was needed instead of .some-class are removed.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
e91e8e993d Add emacs mode-lines to ST sources
To each .c and .h file, add:

 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

'gnu' is the default anyways for Emacs, but indent-tabs-mode is not,
so this sets things up to correspond to the policy of no-tabs.

http://bugzilla.moblin.org/show_bug.cgi?id=6467
2009-10-01 14:41:18 -04:00
276d9a9302 Import stylesheet code from hippo-canvas
Import:

  HippoCanvasTheme      => StTheme
  HippoCanvasThemeImage => StThemeImage
  HippoCanvasStyle      => StThemeNode

StThemeContext is a new class managing the theme for a stage and
global properties like resolution.

test-theme.c is a newly written test program to do verification of the
style matching and property handling rules.

Various changes are made in the import:

 - Comprehensive reindentation
 - guint32 pixels replaced with ClutterColor
 - General pseudo-class support added
 - Old-fashioned (non-bordered) background image support added, though
   with no support for repeat, etc.
 - Bug fixes for problems revealed by test program

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
6b95864076 Fix installation and distribution of stylesheet data
Install and distribute gnome-shell.css and theme images. They are moved
down from $datadir to $datadir/theme to avoid a weirdness where we have
images in $datadir and then also in $datadir/images.

(Also moved in the source tree to avoid adding another difference between
installed and uninstalled operation.)

https://bugzilla.gnome.org/show_bug.cgi?id=595989
2009-10-01 14:41:18 -04:00
d4c577a299 Remove stale C files
Remove several stale C files that we are no longer using; now
that we have a distcheck hook to catch non-distributed files, these
would otherwise prevent distchecking.

https://bugzilla.gnome.org/show_bug.cgi?id=595988
2009-10-01 14:41:17 -04:00
b90fc1e194 Extend distcheck for files in Git to all files
Instead of just checking that we distribute all Javascript files, check
that we distribute everything that is in Git.

The toplevel Makefile.am has a variable DIST_EXCLUDE that lists patterns
of files that we actually don't want to distribute.

https://bugzilla.gnome.org/show_bug.cgi?id=595988
2009-10-01 14:41:17 -04:00
55497899dd Add some structure for interactive tests of UI components
js/ui/environment.js: Split out initial UI setup (Tweener initialization,
  ClutterContainer monkey-patching) into a separate file we can import from tests.

tests/: Directory for various types of tests
tests/run-test.sh: Shell script that to run tests with an appropriate
  environment set up.

tests/testcommon/: Common modules and data for tests
tests/interactive/: Interactive tests

tests/interactive/box-layout.js: A sample test of StLayout

https://bugzilla.gnome.org/show_bug.cgi?id=595987
2009-10-01 14:41:17 -04:00
e37790fdf9 Monkey-patch in ClutterContainer methods for StBoxLayout
Setting options for children added to StBoxLayout is not convenient
since we are missing the varargs methods of clutter_container.

Patch in:

 child_set() - set properties of a child
 add() - add a child and set properties (this is different from
         clutter_container_add()! I think the deviation is
         with avoiding the awkward name add_with_properties()
         which is what might be expected. ClutterContainer
         currently doesn't have a method like this at all.)

The code is written to allow patching into multiple ClutterContainer
classes but for now only StBoxLayout is patched, since it's the only
container we are using where we need to set options as properties.

https://bugzilla.gnome.org/show_bug.cgi?id=595419
2009-10-01 14:41:17 -04:00
83402957bb Add GObject Introspection annotations
Add GObject Introspection annotations to methods where needed, in
particular adding (transfer none) to return values that don't transfer
ownership.

st_texture_cache_get_actor() and st_texture_cache_get_texture()
are annotated as (transfer none) since they return a newly
created *floating* texture.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
58325fca76 Import MxEntry, MxLabel, MxClipboard
For now this commit introduces an external dependency on clutter-imcontext.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
8b6962f3bf Import MxBoxLayout, MxBoxLayoutChild
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
c1f91def74 Add css for scrolling
Port bits of Mx's default.css into gnome-shell.css, and use some
hand-rolled .pngs with colors from
http://live.gnome.org/GnomeShell/DesignerPlayground/ExpandedViewMockups

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
529f74c0e5 Load gnome-shell.css at startup
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
459a3b18f2 Add a "datadir" property
Will be used to load stylesheets from main.js.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
ac2be7f0d1 Remove hardcoded '28' from StScrollView
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
f6b80d5ed4 Import MxScrollView and dependencies
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
d291e568fd Import Mx core as ST
Import the core MxWidget/MxBin and their dependencies; we use the
namespace "St" (Shell Toolkit) because it is the same length as Mx
so enabling easy sharing of code, but makes it clear that this is
a friendly fork and not a literal import.

Based on a patch by Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
2b78d5bd5d Improve support for multihead setups
Fix panel, app switcher, and looking glass to limit themselves to the
primary monitor, and run dialog to limit itself to the monitor
containing the currently-focused window.

The overview is also limited to the primary monitor now (with the
other monitors being blacked out), although the workspaces within the
overview are shaped like the full "screen" (the bounding box of all
monitors). To be fixed later.

https://bugzilla.gnome.org/show_bug.cgi?id=593060
2009-10-01 13:46:03 -04:00
c9d9846759 Add Desktop in Places
Updated by Colin Walters <walters@verbum.org to monitor gconf
and use g_get_user_special_dir.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=596933
2009-10-01 11:53:30 -04:00
6baafaa530 [places] Fix double spacing between actions and devices
https://bugzilla.gnome.org/show_bug.cgi?id=596991
2009-10-01 10:43:57 -04:00
c2af05f753 [AppSwitcher] Allow use of arrow keys in the popup
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-01 10:35:40 -04:00
97df305a6d [AppSwitcher] Drop the line wrapping code.
Also rename _grid into _appsBox as grid is not an appropriate word
anymore for what this box is.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-30 23:32:36 +02:00
fee385ba35 [AppSwitcher] Do not show the glow for icons in alt+tab dialog.
Unlike icons in the application well, do not show the glow used to
indicate running apps.  It is somewhat redundant here.  These are all
running apps and it is fairly clear from the window list if there are
multiple instances available, according to mccann.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-29 18:43:35 +02:00
373fa3c325 [AppSwitcher] deal with the user releasing Alt before we get the grab
Previously mutter was doing this for us, but now we need to do it
ourselves.

https://bugzilla.gnome.org/show_bug.cgi?id=596695
2009-09-29 10:07:09 -04:00
84a6a6faf0 Updated Spanish translation 2009-09-28 22:00:25 +02:00
9432ddb12e [windowmanager] Remove destroy effect
It slows things down, it's a slightly weird effect, and because the
window is still live while it's animating, you may see subwindows
being destroyed during the animation.

https://bugzilla.gnome.org/show_bug.cgi?id=596441
2009-09-28 09:45:38 -04:00
d4a2f9e604 [AppIcon] Sort minimized windows after normal ones in AppIcon menu
https://bugzilla.gnome.org/show_bug.cgi?id=596389
2009-09-28 09:43:51 -04:00
7f468b36e7 [AppSwitcher] Put apps with only minimized windows at end of list
https://bugzilla.gnome.org/show_bug.cgi?id=596389
2009-09-28 09:43:51 -04:00
349e5b39af Updated Hungarian translation 2009-09-28 13:43:23 +02:00
cad774aca1 Use "More" instead of "Browse"
The text "Browse" used for the buttons on the dash section headers is a
little obscure and tends to translate into something that doesn't fit
well.

Going back to "More" will hopefully be more manageable in translation.

https://bugzilla.gnome.org/show_bug.cgi?id=596433
2009-09-27 17:59:54 +02:00
b25bbf4c0a Small application browse tweaks
- Add spacing after Frequent, reduce it for the other app categories.

   Put a small gap (one line) between Frequent and the other
   categories to make it clear that it is something a little
   different.

 - Remove category icons from the applications menu.

   Remove category icons; they aren't particularly helpful
   (they are gone from the GNOME-2.28 menus too) and having them
   in Applications Browse draws the eye to the wrong thing - the
   category - rather than the right thing - the application icons.

https://bugzilla.gnome.org/show_bug.cgi?id=596435
2009-09-27 15:02:52 +02:00
72dd458c80 [AppSwitcher] Make the background translucent again
The default AppIcon gray border color isn't very visible against a
dark gray background, but a white border looks too bold in the Well. So
allow the caller to override the AppIcon border color, so that the Well
can use gray-on-black and the AppSwitcher can use white-on-gray. (And
then revert the AppSwitcher back to the translucent gray background.)

https://bugzilla.gnome.org/show_bug.cgi?id=596337
2009-09-26 12:08:16 -04:00
79d5d3dba0 Add a missing "let". 2009-09-26 00:50:13 +02:00
c14a4deddf Rename iconButton to IconButton, as it is a class. 2009-09-26 00:50:07 +02:00
4bab511fa5 [Overview] Don't treat 1024x600 as widescreen
This works significantly better on my netbook.

https://bugzilla.gnome.org/show_bug.cgi?id=596375
2009-09-25 17:29:04 -04:00
36b11ee8c7 Do not show "More" next to "Recent Docs" if there are no docs (bug #582037) 2009-09-25 21:17:57 +02:00
3ffc510be7 runDialog.js: really update the enableInternalCommands when the key changes
The run dialog uses the "development_tools" gconf key to determine
whether funcions like "lg" or "restart" should be enabled, but it
failed to notice it on the run when said key changed. This commit
fixes this.
2009-09-25 20:10:45 +02:00
ec92bfba14 Compress multiple load requests
Before, if the texture cache received a request to load say
the themed icon for an application multiple times (as could happen
since we have multiple application displays), it would often create
a thread for each one and in fact, load the pixbuf multiple times.

Avoid this by keeping track of outstanding requests.

https://bugzilla.gnome.org/show_bug.cgi?id=596121
2009-09-25 13:41:52 -04:00
f5f22b3935 [AppSwitcher] Keep track of the selected window for each app
Rather than selecting windows[0] each time the cycle returns to an
app, select whatever window of that app was selected last time around.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-25 13:33:23 -04:00
159081dcfc Optimize searching further
There are now 3 code paths in decreasing speed:

First, optimize subsearching more by just hiding the actors
that didn't match, since we know the ordering has to be right.

For initiating a search (or backspacing an existing one), again
instead of destroying and recreating actors, just temporarily
remove them and re-add them in the desired order.

Finally for when data has changed, use the old code path of
destroying all actors.  (This itself could obviously be optimized
if we had a way to know that just one application changed, but
at the moment we don't).

https://bugzilla.gnome.org/show_bug.cgi?id=596119
2009-09-25 12:09:46 -04:00
1da4837d98 Don't show search results sections until we've actually searched
We queue a 150ms timeout when the user starts typing to avoid searching
for the first keystroke.  However, this caused us to change to the search
mode, but show the leftover state of the search displays from an
earlier search state.

Instead, just hide the results sections until we've actually performed
the current search once.

https://bugzilla.gnome.org/show_bug.cgi?id=596119
2009-09-25 12:08:41 -04:00
0f63ae1869 Only use visible actors for paging/allocation
It's expected that containers skip not-visible actors when
allocating, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=596119
2009-09-25 12:08:29 -04:00
32ef951fe0 Optimize subsearches
This is probably not the biggest optimization that needs to be
made at least for application searching, but we can optimize the
case where we're going from a search of "fi" to "fire" by just
re-searching the list of things we already had that matched "fi"
instead of looping over everything.

https://bugzilla.gnome.org/show_bug.cgi?id=596119
2009-09-25 12:08:15 -04:00
3564d78d30 Use shellwm.takeover_keybinding for Alt-F1 and Alt-F2
This fixes a regression where we weren't using the correct event
timestamps, because for both of these we were sending an XClientMessage
to ourself.

https://bugzilla.gnome.org/show_bug.cgi?id=596262
2009-09-25 11:28:13 -04:00
4bff2675ae Add Arabic translation 2009-09-25 04:23:06 +02:00
2020d15a1a Fall back to fewer than 4 columns if space limited
First eliminate the variable WELL_ITEM_HSPACING since it was 0
and thus effectively was not used.

Add a new variable WELL_ITEM_MIN_HSPACING which is the minimum
space between grid items we allow.  When computing layout, allow
for a number of columns less than 4 by using the minimum item
size.

https://bugzilla.gnome.org/show_bug.cgi?id=595023

Based on a patch from Colin Walters.
2009-09-24 21:40:46 -04:00
64d8d7a91c List shellDBus.js in Makefile.am
Include the new file shellDBus.js with installed and distributed Javascript.
2009-09-24 18:13:23 -04:00
eb025901c8 [AppSwitcher] Implement pointer selection 2009-09-24 16:13:57 -04:00
9fee99bc7a [AppSwitcher] Implement window cycling 2009-09-24 16:13:52 -04:00
67bfbc9b4b [AppSwitcher] Use AppIcon and switch applications rather than windows
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-24 16:13:47 -04:00
11d884d724 [AppSwitcher] Port Alt-Tab switcher to custom_handler interface
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-24 16:13:42 -04:00
24d42adc04 Add Main.activateWindow() to remove some duplication 2009-09-24 11:11:01 -04:00
110ef17e2d Add Main.currentTime(), to get the correct current-event-time
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-24 11:10:55 -04:00
0143512e00 Don't leak when loading an already-cached item
A previous patch fixed a leak when loading items which shouldn't
be cached, but we also had a leak if two requests for the same
item were outstanding.  In that case we load the pixbuf twice,
but should discard subsequent loads when we notice we've already
cached it.

https://bugzilla.gnome.org/show_bug.cgi?id=595321
2009-09-23 17:06:44 -04:00
4876474be3 Add shellDBus.js which implements Eval(str) and an OverviewActive property
For various reasons I'd like a method which allows evaluation; say
log in from another machine and run "gnome-shell --repl" or something.

Also as a possible solution for the screensaver X grab issue, add
a (read/write) property "OverviewActive".

https://bugzilla.gnome.org/show_bug.cgi?id=596102
2009-09-23 16:56:33 -04:00
0e4a86f2e6 [AppIcon] move well menu code from appDisplay.js to appIcon.js
The menu is needed by the app switcher as well as the overview, so
make it slightly more generic and move the code to appIcon. Also add
support for drawing the menu either to the right of or below the icon.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-23 10:02:04 -04:00
18dbc5462f [AppIcon] Make BaseWellItem a subclass of AppIcon
Part of https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-22 18:24:22 -04:00
8f660f563c [AppIcon] Remove redundant window array 2009-09-22 18:24:22 -04:00
fa316ddd3d [AppIcon] Make sure small icons still get full-sized AppIcon actors 2009-09-22 18:24:22 -04:00
7703bee284 [workspaces] Use a stable minimum-motion placement for windows
Rather than having the mapping from window into "slots" (or
possible positions in the workspaces) be dependent on stacking
order, compute the minimum-motion which is a vector from one
top left corner to another.  This order won't change as long
as the window set and their positions stay fixed.

There are two minimum motion algorithims; one simply computes
all possible placements by permuting the window list, up to
a current maximum of 5 windows.  Past that (which also happens
to be the number where we switch to a grid), we use a "greedy"
algorithm which for each slot, finds the window with least motion
for that slot.

To break any ties, we use an internal integer in MetaWindow which
enumerates the order in which windows were created.

https://bugzilla.gnome.org/show_bug.cgi?id=582654
2009-09-22 18:14:32 -04:00
90e6769638 Fix memory leak in getting applications from menu
https://bugzilla.gnome.org/show_bug.cgi?id=595321
2009-09-22 18:13:09 -04:00
0b6d09bbe2 [lightbox] Fix logic; get_children() returns children bottom-to-top 2009-09-22 18:11:25 -04:00
3734479cbd [lightbox] Add lightbox.js and use it in overview, alt-tab, and run dialog
https://bugzilla.gnome.org/show_bug.cgi?id=596000
2009-09-22 17:23:14 -04:00
6cae94edcc Bug 594916 - Allow cancelling DND by hitting Esc
Esc used to close the overview and get the DND actor stuck on the desktop when
it was pressed when dragging.
2009-09-22 16:15:28 -04:00
0918bdd612 [AppWell] Don't add "New Window" item to menus for transient apps 2009-09-22 13:30:24 -04:00
a75b1abc93 Update Czech translation 2009-09-22 13:37:55 +02:00
e6a08cc9fd Added sl for Slovenian language 2009-09-22 12:14:22 +02:00
09c9defbf0 Addeed Slovenian translation 2009-09-22 12:13:49 +02:00
3ba6ff4ca9 Fix shell_hook_paint_red_border
In overriding _paint we're already offset to our allocation
coordinates, don't re-add them.

https://bugzilla.gnome.org/show_bug.cgi?id=595514
2009-09-21 18:34:57 -04:00
19fa0b5d5b Unref GIcon we use internally
https://bugzilla.gnome.org/show_bug.cgi?id=595321
2009-09-21 18:22:40 -04:00
79db50500d Squash small memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=595321
2009-09-21 18:21:04 -04:00
f26c9ab245 Fix memory leaks
Need to free the returned thumbnail path, and in the CachePolicy.NONE
case we also need to unref the cogl handle.

https://bugzilla.gnome.org/show_bug.cgi?id=595321
2009-09-21 18:21:02 -04:00
293adb9bcc Updated Brazilian Portuguese translation 2009-09-21 08:40:41 -03:00
e79b15c645 Remove taskbar-highlighting support from Alt-Tab popup
The "lightbox" effect had support for highlighting a particular
rectangular region on the taskbar when Alt-Tabbing to a minimized
window. Since we no longer use the taskbar, this code is just cruft
now.

Part of https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-18 08:23:01 -04:00
08603c1524 Updated Swedish translation 2009-09-18 13:02:49 +02:00
cee7106cb1 Better handle pushModal failing
Previously we'd leave the focus on the stack, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=595382
2009-09-17 16:36:33 -04:00
2c0661d377 Add "New Window" menu item
Refactor the current menu code to support both window selection
and "normal" menu items.  Add a "New Window" item which does what
you'd expect.

Clean up the way we handle highlighting the window items to be
more direct; rather than looping over all items in most cases,
just directly manipulate one item

https://bugzilla.gnome.org/show_bug.cgi?id=594557
2009-09-17 16:36:18 -04:00
258 changed files with 44879 additions and 9936 deletions

7
.gitignore vendored
View File

@ -22,8 +22,10 @@ intltool-extract.in
intltool-merge.in
intltool-update.in
libtool
m4/
omf.make
po/*.gmo
po/gnome-shell.pot
po/Makefile.in.in
po/POTFILES
po/stamp-it
@ -38,5 +40,10 @@ src/gnomeshell-taskpanel
src/gnome-shell
src/test-recorder
src/test-recorder.ogg
src/test-theme
src/st.h
stamp-h1
tests/run-test.sh
xmldocs.make
*~
*.patch

View File

@ -1,18 +1,21 @@
SUBDIRS = data js src po
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src tests po man
EXTRA_DIST = \
.project \
.settings
.settings \
autogen.sh \
tools/check-for-missing.py
# These are files checked into Git that we don't want to distribute
DIST_EXCLUDE = \
.gitignore \
gnome-shell.doap \
MAINTAINERS \
tools/build/*
distcheck-hook:
@echo "Checking disted javascript against files in git"
@failed=false; \
for f in `cd $(srcdir) && git ls-files js` ; do \
if ! test -e $(distdir)/$$f ; then \
echo File missing from distribution: $$f ; \
failed=true ; \
fi \
done ; \
if $$failed ; then \
exit 1 ; \
fi
@echo "Checking disted files against files in git"
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)

View File

@ -5,7 +5,6 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gnome-shell"
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {
@ -15,7 +14,7 @@ REQUIRED_AUTOMAKE_VERSION=1.10
}
which gnome-autogen.sh || {
echo "You need to install gnome-common from GNOME Subversion (or from"
echo "You need to install gnome-common from GNOME Git (or from"
echo "your OS vendor's package manager)."
exit 1
}

View File

@ -1,30 +1,33 @@
AC_INIT(gnome-shell, 2.27.3)
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[2.29.0],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config])
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS(config.h)
AC_DISABLE_STATIC
# Checks for programs.
AC_PROG_CC
# Needed for per-target cflags, like in gnomeshell-taskpanel
AM_PROG_CC_C_O
AM_PROG_LIBTOOL
# Initialize libtool
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
GETTEXT_PACKAGE=gnome-shell
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
[The prefix for our gettext translation domains.])
PKG_PROG_PKG_CONFIG(0.16)
IT_PROG_INTLTOOL(0.26)
AM_GLIB_GNU_GETTEXT
AC_DEFINE([GETTEXT_PACKAGE], [PACKAGE_TARNAME], [The prefix for our gettext translation domain])
PKG_PROG_PKG_CONFIG([0.22])
# GConf stuff
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
AM_GCONF_SOURCE_2
@ -51,12 +54,13 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins >= 2.29.0
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
gobject-introspection-1.0 >= 0.6.5)
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-2.0 libcroco-0.6)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
@ -93,8 +97,7 @@ AC_SUBST(TYPELIBDIR)
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
[Turn on compiler warnings]),,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
changequote(,)dnl
@ -121,12 +124,15 @@ changequote([,])dnl
AC_PATH_PROG(mutter, [mutter])
AC_SUBST(mutter)
AC_OUTPUT([
AC_CONFIG_FILES([
Makefile
data/Makefile
js/Makefile
js/misc/Makefile
js/ui/Makefile
src/Makefile
tests/Makefile
po/Makefile.in
man/Makefile
])
AC_OUTPUT

View File

@ -12,17 +12,35 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in
gnome-shell.desktop: gnome-shell.desktop.in
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
imagedir = $(pkgdatadir)/images
imagesdir = $(pkgdatadir)/images
dist_images_DATA = \
close-black.svg \
magnifier.svg
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
theme/add-workspace.svg \
theme/close-window.svg \
theme/close.svg \
theme/corner-ripple.png \
theme/gnome-shell.css \
theme/mosaic-view-active.svg \
theme/mosaic-view.svg \
theme/remove-workspace.svg \
theme/scroll-button-down-hover.png \
theme/scroll-button-down.png \
theme/scroll-button-up-hover.png \
theme/scroll-button-up.png \
theme/scroll-hhandle.svg \
theme/scroll-vhandle.svg \
theme/section-back.svg \
theme/section-more.svg \
theme/section-more-open.svg \
theme/single-view-active.svg \
theme/single-view.svg \
theme/ws-switch-arrow-left.svg \
theme/ws-switch-arrow-right.svg
dist_image_DATA = \
add-workspace.svg \
app-well-glow.png \
back.svg \
close.svg \
close-black.svg \
info.svg \
magnifier.svg \
remove-workspace.svg
schemadir = @GCONF_SCHEMA_FILE_DIR@
schema_DATA = gnome-shell.schemas

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="59.995201"
height="59.995102"
id="svg3113"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="add-workspace.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3115">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3121" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="375"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="641"
inkscape:window-height="683"
inkscape:window-x="4"
inkscape:window-y="54" />
<metadata
id="metadata3118">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-498.57383,-439.50749)">
<path
id="path3269"
d="M 528.57143,439.91129 C 512.23433,439.91129 498.97763,453.16795 498.97763,469.50504 C 498.97763,485.84214 512.23433,499.09881 528.57143,499.09879 C 544.90853,499.09879 558.16513,485.84215 558.16523,469.50504 C 558.16523,453.16794 544.90853,439.9113 528.57143,439.91129 z M 525.29023,451.16129 L 531.88393,451.16129 C 533.75363,451.16129 535.25893,452.66659 535.25893,454.53629 L 535.25893,462.84879 L 543.54023,462.84879 C 545.40973,462.84879 546.91523,464.35409 546.91523,466.22379 L 546.91523,472.81754 C 546.91523,474.68728 545.40993,476.19255 543.54023,476.19254 L 535.25893,476.19254 L 535.25893,484.47379 C 535.25893,486.34353 533.75363,487.8488 531.88393,487.84879 L 525.29023,487.84879 C 523.42053,487.84881 521.91523,486.34351 521.91523,484.47379 L 521.91523,476.19254 L 513.60263,476.19254 C 511.73313,476.19257 510.22773,474.68726 510.22763,472.81754 L 510.22763,466.22379 C 510.22763,464.35407 511.73303,462.8488 513.60263,462.84879 L 521.91523,462.84879 L 521.91523,454.53629 C 521.91523,452.66657 523.42043,451.1613 525.29023,451.16129 z"
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -73,6 +73,20 @@
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/autohide</key>
<applyto>/desktop/gnome/shell/sidebar/autohide</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Whether the sidebar should automatically hide itself in compact mode</short>
<long>
Controls the autohide state of the sidebar.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/widgets</key>
<applyto>/desktop/gnome/shell/sidebar/widgets</applyto>
@ -88,6 +102,83 @@
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/disabled_extensions</key>
<applyto>/desktop/gnome/shell/disabled_extensions</applyto>
<owner>gnome-shell</owner>
<type>list</type>
<list_type>string</list_type>
<default>[]</default>
<locale name="C">
<short>Uuids of extensions to disable</short>
<long>
GNOME Shell extensions have a uuid property; this key lists extensions which should not be loaded.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/recorder/framerate</key>
<applyto>/desktop/gnome/shell/recorder/framerate</applyto>
<owner>gnome-shell</owner>
<type>int</type>
<default>15</default>
<locale name="C">
<short>Framerate used for recording screencasts.</short>
<long>
The framerate of the resulting screencast recordered by GNOME Shell's screencast recorder in frames-per-second.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/recorder/pipeline</key>
<applyto>/desktop/gnome/shell/recorder/pipeline</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>The gstreamer pipeline used to encode the screencast</short>
<long>
Sets the GStreamer pipeline used to encode recordings. It follows the syntax used for gst-launch.
The pipeline should have an unconnected sink pad where the recorded video is recorded. It will
normally have a unconnected source pad; output from that pad will be written into the output file.
However the pipeline can also take care of its own output - this might be used to send the output to an icecast server via shout2send or similar.
When unset or set to an empty value, the default pipeline will be used. This is currently 'videorate ! theoraenc ! oggmux' and records to Ogg Theora.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/recorder/file_extension</key>
<applyto>/desktop/gnome/shell/recorder/file_extension</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>ogg</default>
<locale name="C">
<short>File extension used for storing the screencast</short>
<long>
The filename for recorded screencasts will be a unique filename based on the current date, and use this extension.
It should be changed when recording to a different container format.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/overview/workspaces_view</key>
<applyto>/desktop/gnome/shell/overview/workspaces_view</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>single</default>
<locale name="C">
<short>Overview workspace view mode</short>
<long>
The selected workspace view mode in the overview.
Supported values are "single" and "grid".
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Foreground"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="info_16.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
id="metadata2389"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs2387"><linearGradient
id="linearGradient3710"><stop
style="stop-color:#c4c4c4;stop-opacity:1;"
offset="0"
id="stop3712" /><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3714" /></linearGradient><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective2391" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3710"
id="linearGradient3716"
x1="7.9066148"
y1="15.937743"
x2="7.9377432"
y2="0.031128405"
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
inkscape:window-height="713"
inkscape:window-width="722"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
showgrid="false"
inkscape:zoom="32.125"
inkscape:cx="8"
inkscape:cy="8.154146"
inkscape:window-x="20"
inkscape:window-y="20"
inkscape:current-layer="Foreground" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M7,3h2v2H7V3z M5.5,12H7V8H5.5V7H9v5h1.5v1h-5V12z M0,8c0-4.418,3.582-8,8-8 s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
id="path2384"
style="fill-opacity:1;fill:url(#linearGradient3716)" />
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="59.995201"
height="59.995102"
id="svg3113"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="remove-workspace.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3115">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3121" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.5"
inkscape:cx="-8.1974244"
inkscape:cy="38.948933"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1400"
inkscape:window-height="971"
inkscape:window-x="454"
inkscape:window-y="105" />
<metadata
id="metadata3118">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-498.57383,-439.50749)">
<path
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="M 30 0.40625 C 13.662899 0.40624999 0.40625 13.66291 0.40625 30 C 0.40624999 46.337101 13.6629 59.59377 30 59.59375 C 46.337099 59.593749 59.59365 46.33711 59.59375 30 C 59.59375 13.662901 46.3371 0.40626 30 0.40625 z M 15.03125 23.34375 L 44.96875 23.34375 C 46.83825 23.343751 48.34375 24.84905 48.34375 26.71875 L 48.34375 33.3125 C 48.34375 35.182239 46.83845 36.68751 44.96875 36.6875 L 15.03125 36.6875 C 13.16175 36.687529 11.65635 35.18222 11.65625 33.3125 L 11.65625 26.71875 C 11.65625 24.849031 13.16165 23.34376 15.03125 23.34375 z "
transform="translate(498.57383,439.50749)"
id="path2382" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="23"
height="15"
id="svg6375"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="New document 13">
<defs
id="defs6377">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6383" />
<inkscape:perspective
id="perspective6366"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6380">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<g
style="display:inline"
id="g6243"
transform="translate(-986.28859,-658.2796)">
<rect
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="rect5318"
width="22"
height="14"
x="986.89801"
y="675.86743"
rx="0.49999979"
ry="0.5" />
<g
id="g5320"
transform="translate(402.77304,-12.882544)">
<path
id="path5322"
d="m 595.125,692.53048 0,6.43903"
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
id="path5324"
d="m 598.34451,695.75 -6.43902,0"
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
id="Foreground"
x="0px"
y="0px"
width="22"
height="22"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="close-window.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
id="metadata2399"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs2397"><linearGradient
id="linearGradient3173"><stop
style="stop-color:#c4c4c4;stop-opacity:1;"
offset="0"
id="stop3175" /><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3177" /></linearGradient><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective2401" /></defs><sodipodi:namedview
inkscape:window-height="999"
inkscape:window-width="1680"
inkscape:pageshadow="2"
inkscape:pageopacity="1"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#000000"
id="base"
showgrid="false"
inkscape:zoom="25.648691"
inkscape:cx="8.8097603"
inkscape:cy="9.0472789"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:current-layer="Foreground"
showguides="true"
inkscape:guide-bbox="true" />
<g
id="g3175"><path
sodipodi:nodetypes="csssc"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.59217799;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path2394"
d="M 0.83987936,8.0425327 C 0.83987936,4.0805265 4.0712155,0.86823453 8.0567103,0.86823453 C 12.042205,0.86823453 15.273542,4.0805265 15.273542,8.0425327 C 15.273542,12.004539 12.042205,15.216831 8.0567103,15.216831 C 4.0712155,15.216831 0.83987936,12.004539 0.83987936,8.0425327 z"
clip-rule="evenodd" /><g
id="g3172"><path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.4242673,5.3313047 L 10.515414,10.421272 L 10.714004,10.646491"
id="path3152" /></g></g><path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.4402527,10.650392 L 10.688082,5.3573033"
id="path3154"
sodipodi:nodetypes="cc" /></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

750
data/theme/gnome-shell.css Normal file
View File

@ -0,0 +1,750 @@
/* Copyright 2009, Red Hat, Inc.
*
* Portions adapted from Mx's data/style/default.css
* Copyright 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
.shell-link {
color: #0000ff;
text-decoration: underline;
}
.shell-link:hover {
color: #0000e0;
}
.label-shadow {
color: rgba(0,0,0,0.5);
}
StScrollBar
{
padding: 0px;
}
StScrollView
{
scrollbar-width: 16px;
scrollbar-height: 16px;
}
StScrollView > .top-shadow
{
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 255);
background-gradient-end: rgba(0, 0, 0, 0);
height: 30px;
}
StScrollView > .bottom-shadow
{
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 0);
background-gradient-end: rgba(0, 0, 0, 255);
height: 30px;
}
StScrollBar {
background-color: #080808;
border: 1px solid #2d2d2d;
border-radius: 8px;
}
StScrollBar StButton#vhandle
{
background-image: url("scroll-vhandle.svg");
background-color: #252525;
border: 1px solid #080808;
border-radius: 8px;
}
StScrollBar StButton#hhandle
{
background-image: url("scroll-hhandle.svg");
background-color: #252525;
border: 1px solid #080808;
border-radius: 8px;
}
StScrollBar StButton#hhandle:hover,
StScrollBar StButton#vhandle:hover
{
background-color: #292929;
}
StTooltip {
border: 1px solid rgba(79,111,173,0.9);
border-radius: 5px;
padding: 4px;
background-color: rgba(79,111,173,0.9);
color: #ffffff;
}
/* Panel */
#panel {
color: #ffffff;
font-size: 16px;
background-gradient-direction: vertical;
background-gradient-start: #161616;
background-gradient-end: #000000;
border-bottom: 1px solid #1f1f1f;
}
#panelLeft, #panelCenter, #panelRight {
spacing: 4px;
}
#panelLeft {
padding-right: 4px;
}
#panelRight {
padding-left: 4px;
}
#appMenu {
spacing: 4px;
}
.app-menu-icon {
width: 24px;
height: 24px;
}
.panel-button {
padding: 4px 12px 3px;
border-radius: 5px;
border-radius-bottomleft: 0px;
border-radius-bottomright: 0px;
font: 16px sans-serif;
}
.panel-button:active, .panel-button:checked, .panel-button:pressed {
background-gradient-direction: vertical;
background-gradient-start: #3c3c3c;
background-gradient-end: #131313;
}
#panelActivities {
border-radius-topleft: 0px;
}
#panelStatus {
border-radius-topright: 0px;
}
#statusMenu {
spacing: 4px;
}
/* Overview */
.overview {
background-color: #111;
}
.info-bar {
color: #fff;
font-size: 14px;
spacing: 20px;
}
.info-bar-link-button {
background-color: #2d2d2d;
padding: 2px 14px;
border-radius: 10px;
border: 1px solid #181818;
}
.info-bar-link-button:hover {
border: 1px solid #666666;
}
.workspaces {
color: white;
}
.workspaces.single {
spacing: 25px;
}
.workspaces.mosaic {
spacing: 15px;
}
.workspaces-bar {
height: 48px;
}
.workspaces-bar, .workspaces-bar * {
spacing: 5px;
}
.workspace-indicator {
width: 24px;
height: 16px;
background: rgba(155,155,155,0.8);
border-spacing: 16px;
}
.workspace-indicator.active {
background: rgba(255,255,255,0.8);
}
.window-caption {
background: rgba(0,0,0,0.8);
border: 1px solid rgba(128,128,128,0.40);
border-radius: 10px;
font-size: 12px;
padding: 2px 8px;
-shell-caption-spacing: 4px;
}
.window-close {
background-image: url("close-window.svg");
height: 24px;
width: 24px;
-st-shadow: -2px 2px 6px rgba(0,0,0,0.5);
-shell-close-overlap: 16px;
}
.single-view-controls {
padding: 0px 15px;
}
.workspace-controls {
width: 24px;
height: 16px;
}
.workspace-controls.add {
background-image: url("add-workspace.svg");
}
.workspace-controls.remove {
background-image: url("remove-workspace.svg");
}
.workspace-controls.switch-single {
background-image: url("single-view.svg");
}
.workspace-controls.switch-mosaic {
background-image: url("mosaic-view.svg");
}
.workspace-controls.switch-single:checked {
background-image: url("single-view-active.svg");
}
.workspace-controls.switch-mosaic:checked {
background-image: url("mosaic-view-active.svg");
}
#SwitchScroll {
height: 14px;
}
#SwitchScroll #hhandle {
border-radius: 7px;
}
/* Dash */
#dash {
color: #5f5f5f;
font-size: 12px;
padding: 0px 14px;
}
#dashSections {
spacing: 12px;
}
#searchEntry {
padding: 4px;
border-bottom: 1px solid #262626;
}
#searchEntry:active {
background-color: #c4c4c4;
}
.dash-section {
spacing: 8px;
}
.section-header {
}
.section-header-inner {
spacing: 4px;
}
.section-text-content {
padding: 4px 0px;
}
.section-header-back {
padding: 0px 4px 0px 0px;
border-right: 1px solid #262626;
}
.section-header-back-image {
background-image: url("section-back.svg");
width: 12px;
height: 16px;
}
.section-count {
}
.dash-section-content {
color: #ffffff;
spacing: 8px;
}
.more-link {
}
.more-link-expander {
background-image: url("section-more.svg");
width: 9px;
height: 9px;
}
.more-link-expander.open {
background-image: url("section-more-open.svg");
width: 9px;
height: 9px;
}
.dash-pane {
background-color: rgba(0,0,0,0.95);
border: 1px solid #262626;
padding: 4px;
spacing: 4px;
}
.dash-pane-close {
background-image: url("close.svg");
width: 16px;
height: 16px;
}
.dash-search-section-header {
padding: 6px 0px;
spacing: 4px;
}
.dash-search-section-results {
color: #ffffff;
padding-left: 4px;
}
.dash-search-section-list-results {
spacing: 4px;
}
.dash-search-result-content {
padding: 3px;
}
.dash-search-result-content:selected {
padding: 2px;
border: 1px solid #5c5c5c;
border-radius: 2px;
background-color: #1e1e1e;
}
/* GenericDisplay */
.generic-display-container {
spacing: 4px;
}
.generic-display-item {
height: 50px;
border-radius: 4px;
color: #ffffff;
font-size: 14px;
spacing: 4px;
}
.generic-display-item:selected {
background-color: rgba(79,111,173,0.66);
}
.generic-display-item-text {
spacing: 4px;
}
.generic-display-item-description {
font-size: 12px;
color: #bababa;
}
.generic-display-details {
font-size: 14px;
color: #ffffff;
}
.generic-display-details-name {
font-weight: bold;
}
/* Apps */
.overview-pane {
width: 440px;
}
#dashAppWell {
spacing: 6px;
-shell-grid-item-size: 70px;
}
.all-app {
border-radius: 10px;
background-color: rgba(0,0,0,0.95);
border: 1px solid #262626;
color: #ffffff;
height: 400px;
}
.all-app-controls-panel {
height: 30px;
}
.all-app-scroll-view {
padding-right: 10px;
padding-left: 10px;
padding-bottom: 10px;
}
.app-well-app {
border: 1px solid #181818;
border-radius: 4px;
padding: 2px;
width: 70px;
height: 70px;
font-size: 10px;
}
.app-well-app.running {
background-gradient-direction: vertical;
background-gradient-start: #3d3d3d;
background-gradient-end: #181818;
}
.app-well-app:hover {
border: 1px solid #666666;
}
.app-well-app:active {
background-color: #1e1e1e;
border: 1px solid #5f5f5f;
}
.app-well-menu {
border: 1px solid #5f5f5f;
border-radius: 4px;
padding: 4px;
background-color: rgba(0,0,0,0.9);
color: #ffffff;
-shell-arrow-width: 12px;
-shell-menu-spacing: 4px;
}
.app-well-menu-item:hover {
background-color: #1e1e1e;
}
.app-well-menu-separator {
padding-top: 1px;
border-bottom: 1px solid #5f5f5f;
height: 1px;
}
/* Places */
.places-actions {
spacing: 4px;
}
#placesDevices {
padding-top: 4px;
}
/* LookingGlass */
#LookingGlassDialog
{
background-color: rgba(0,0,0,0.85);
spacing: 4px;
padding: 4px;
border: 1px solid rgba(0,0,172,0.85);
border-radius: 4px;
color: #88ff66;
}
#LookingGlassDialog > #Toolbar
{
border: 1px solid grey;
border-radius: 4px;
}
#LookingGlassDialog .labels {
spacing: 4px;
}
#LookingGlassDialog .notebook-tab {
padding: 2px;
}
#LookingGlassDialog .notebook-tab:selected {
border: 1px solid #88ff66;
padding: 1px;
}
#LookingGlassDialog StLabel
{
color: #88ff66;
}
#LookingGlassDialog StEntry
{
color: #88ff66;
}
#LookingGlassDialog StBoxLayout#EvalBox
{
padding: 4px;
spacing: 4px;
}
#lookingGlassExtensions {
padding: 4px;
}
.lg-extension-list {
padding: 4px;
spacing: 6px;
}
.lg-extension {
border: 1px solid #6f6f6f;
border-radius: 4px;
padding: 4px;
}
.lg-extension-name {
font-weight: bold;
}
.lg-extension-actions {
spacing: 6px;
}
/* Calendar popup */
#calendarPopup {
border-radius: 5px;
background: rgba(0,0,0,0.9);
border: 1px solid rgba(128,128,128,0.45);
color: white;
}
#calendarPopup .calendar {
padding: 10px;
}
.calendar {
spacing-rows: 5px;
spacing-columns: 3px;
}
.calendar-change-month {
padding: 2px;
}
.calendar-change-month:hover {
background: #314a6c;
border-radius: 5px;
}
.calendar-change-month:active {
background: #213050;
border-radius: 5px;
}
.calendar-day {
padding: 1px 2px;
}
.calendar-today {
font-weight: bold;
background: #ffffff;
color: black;
border-radius: 5px;
}
.calendar-other-month-day {
color: #cccccc;
}
/* Message Tray */
#message-tray {
background-gradient-direction: vertical;
background-gradient-start: rgba(0,0,0,0.01);
background-gradient-end: rgba(0,0,0,0.95);
height: 28px;
}
#notification {
font-size: 16px;
border-radius: 5px;
background: rgba(0,0,0,0.9);
color: white;
padding: 2px 10px 10px 10px;
spacing-rows: 5px;
spacing-columns: 10px;
max-width: 40em;
}
#notification-actions {
spacing: 5px;
}
.notification-button {
border: 2px rgba(0,0,0,0.0);
border-radius: 5px;
padding: 5px;
background: #c0c0c0;
color: black;
font-weight: bold;
}
.notification-button:hover {
border: 2px solid white;
}
.notification-button:active {
border: 2px solid white;
background: #808080;
}
#summary-mode {
spacing: 10px;
padding: 2px 4px;
}
/* App Switcher */
.switcher-list {
background: rgba(0,0,0,0.8);
border: 1px solid rgba(128,128,128,0.40);
border-radius: 8px;
padding: 18px;
font: 12px sans-serif;
color: white;
}
.switcher-list .item-box {
padding: 8px;
border-radius: 4px;
}
.switcher-list .thumbnail-box {
padding: 2px;
spacing: 4px;
}
.switcher-list .thumbnail {
width: 256px;
height: 256px;
}
.switcher-list .outlined-item-box {
padding: 6px;
border: 2px solid rgba(85,85,85,1.0);
border-radius: 4px;
}
.switcher-list .selected-item-box {
padding: 8px;
border-radius: 4px;
background: rgba(255,255,255,0.33);
}
.switcher-list .separator {
width: 1px;
background: rgba(255,255,255,0.33);
}
.ripple-box {
width: 52px;
height: 52px;
background-image: url("corner-ripple.png");
}
/* Workspace Switcher */
.workspace-switcher-container {
background: rgba(0,0,0,0.8);
border: 1px solid rgba(128,128,128,0.40);
border-radius: 8px;
padding: 12px;
}
.workspace-switcher {
background: transparent;
border: 0px;
border-radius: 0px;
padding: 4px;
}
.ws-switcher-active-left {
height: 98px;
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-left.svg");
border-radius: 4px;
}
.ws-switcher-active-right {
height: 98px;
border: 0px;
background: rgba(255,255,255,0.5);
background-image: url("ws-switch-arrow-right.svg");
border-radius: 4px;
}
.ws-switcher-spacer {
width: 0.5px;
height: 96px;
border: 0px;
background: transparent;
padding: 4px;
}
.ws-switcher-box {
height: 96px;
border: 2px solid rgba(85,85,85,0.5);
background: transparent;
border-radius: 4px;
}

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6503"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="mosaic-view-active.svg">
<defs
id="defs6505">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6511" />
<inkscape:perspective
id="perspective6494"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="-15.97056"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6508">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-16)">
<g
style="display:inline;fill:#cbcbcb;fill-opacity:1"
transform="translate(-449.85476,-685.85869)"
id="g5306">
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
id="rect5308"
width="11"
height="7"
x="450.5"
y="710.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5310"
width="11"
height="7"
x="462.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5312"
width="11"
height="7"
x="450.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5314"
width="11"
height="7"
x="462.5"
y="710.5"
rx="0.99999958"
ry="1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

113
data/theme/mosaic-view.svg Normal file
View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6503"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="New document 19">
<defs
id="defs6505">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6511" />
<inkscape:perspective
id="perspective6494"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6508">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-16)">
<g
style="display:inline"
transform="translate(-449.85476,-685.85869)"
id="g5306">
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
id="rect5308"
width="11"
height="7"
x="450.5"
y="710.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5310"
width="11"
height="7"
x="462.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5312"
width="11"
height="7"
x="450.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5314"
width="11"
height="7"
x="462.5"
y="710.5"
rx="0.99999958"
ry="1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="23"
height="15"
id="svg5501"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="add-workspace.svg">
<defs
id="defs5503">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective5509" />
<inkscape:perspective
id="perspective5314"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="-0.074583208"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1"
inkscape:snap-grids="true"
inkscape:snap-bbox="true" />
<metadata
id="metadata5506">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<g
style="display:inline"
id="g6239"
transform="translate(-953.97989,-657.32287)">
<rect
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="rect5318-6"
width="22"
height="14"
x="954.5"
y="675"
rx="0.49999979"
ry="0.5" />
<path
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
d="m 968.71951,682 -6.43902,0"
id="path5324-5" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="10"
height="4"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="scroll-hhandle.svg">
<defs
id="defs4">
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="rect3592"
width="2"
height="4"
x="0"
y="0"
rx="0"
ry="0" />
<use
x="0"
y="0"
xlink:href="#rect3592"
id="use2825"
transform="translate(8,0)"
width="10"
height="4" />
<use
x="0"
y="0"
xlink:href="#use2825"
id="use2827"
transform="translate(-4,0)"
width="10"
height="4" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="4"
height="10"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="scroll-hhandle.svg">
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="rect3592"
width="2"
height="4"
x="0"
y="-4"
rx="0"
ry="0"
transform="matrix(0,1,-1,0,0,0)" />
<use
x="0"
y="0"
xlink:href="#rect3592"
id="use3705"
transform="translate(0,4)"
width="4"
height="10" />
<use
x="0"
y="0"
xlink:href="#use3705"
id="use3707"
transform="translate(0,4)"
width="4"
height="10" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5.8600588"
height="9"
id="svg3647"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="section-more.svg">
<defs
id="defs3649">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3655" />
<inkscape:perspective
id="perspective3603"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="82.777778"
inkscape:cx="2.9300294"
inkscape:cy="5.466443"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata3652">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-262.78425,-490.71933)">
<path
transform="matrix(0,-0.98149546,0.71467449,0,25.404986,578.15569)"
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="1.5707963"
sodipodi:arg1="0.52359878"
sodipodi:r2="2.5"
sodipodi:r1="5"
sodipodi:cy="337.5"
sodipodi:cx="84.5"
sodipodi:sides="3"
id="path5497-5"
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
sodipodi:type="star" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

87
data/theme/section-more.svg Executable file
View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5.8600588"
height="9"
id="svg3647"
version="1.1"
inkscape:version="0.46+devel"
sodipodi:docname="New document 6">
<defs
id="defs3649">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3655" />
<inkscape:perspective
id="perspective3603"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="112.21575"
inkscape:cy="-32.642856"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="164"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata3652">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-262.78425,-490.71933)">
<path
transform="matrix(0,0.98149546,-0.71467449,0,506.02358,412.28296)"
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="1.5707963"
sodipodi:arg1="0.52359878"
sodipodi:r2="2.5"
sodipodi:r1="5"
sodipodi:cy="337.5"
sodipodi:cx="84.5"
sodipodi:sides="3"
id="path5497-5"
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
sodipodi:type="star" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6446"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="single-view-active.svg">
<defs
id="defs6448">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6454" />
<inkscape:perspective
id="perspective6441"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="0.014720032"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6451">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<rect
ry="0.5"
rx="0.49999979"
y="17.483809"
x="0.53483802"
height="15"
width="23"
id="rect5304"
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6446"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="single-view.svg">
<defs
id="defs6448">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6454" />
<inkscape:perspective
id="perspective6441"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="0.014720032"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6451">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<rect
ry="0.5"
rx="0.49999979"
y="17.483809"
x="0.53483802"
height="15"
width="23"
id="rect5304"
style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="96" height="96" id="svg25070" version="1.1" inkscape:version="0.47 r22583" sodipodi:docname="dark-arrow-larger.svg">
<defs id="defs25072">
<inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 24 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="48 : 24 : 1" inkscape:persp3d-origin="24 : 16 : 1" id="perspective25078"/>
<inkscape:perspective id="perspective24985" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 0.5 : 1" sodipodi:type="inkscape:persp3d"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4034-0-4" id="linearGradient24957" gradientUnits="userSpaceOnUse" gradientTransform="translate(6)" x1="-86.552246" y1="185.439" x2="-83.37072" y2="197.31261"/>
<linearGradient inkscape:collect="always" id="linearGradient4034-0-4">
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4036-5-7"/>
<stop style="stop-color: rgb(186, 189, 182); stop-opacity: 1;" offset="1" id="stop4038-9-6"/>
</linearGradient>
<filter id="filter24765" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix24767" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix24769" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4632-1-3-9-3-2" id="linearGradient24955" gradientUnits="userSpaceOnUse" gradientTransform="translate(-5)" x1="-74.520325" y1="169.06032" x2="-74.520325" y2="205.94189"/>
<linearGradient id="linearGradient4632-1-3-9-3-2">
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4634-1-8-3-9-0"/>
<stop id="stop4636-1-9-9-8-8" offset="0.0274937" style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"/>
<stop id="stop4638-8-3-9-6-6" offset="0.274937" style="stop-color: rgb(242, 242, 242); stop-opacity: 1;"/>
<stop id="stop4640-8-5-7-8-9" offset="0.38707438" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4642-5-41-9-6-9" offset="0.66528589" style="stop-color: rgb(217, 218, 216); stop-opacity: 1;"/>
<stop id="stop4644-5-2-7-9-2" offset="0.76745707" style="stop-color: rgb(223, 224, 221); stop-opacity: 1;"/>
<stop style="stop-color: rgb(240, 240, 240); stop-opacity: 1;" offset="1" id="stop4646-3-2-3-7-3"/>
</linearGradient>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-1" id="radialGradient24959" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
<linearGradient id="linearGradient4869-4-1">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-2"/>
<stop id="stop4879-7-4" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4877-6-1" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-0"/>
</linearGradient>
<filter id="filter25011" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25013" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25015" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-0" id="radialGradient24961" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
<linearGradient id="linearGradient4869-4-0">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-8"/>
<stop id="stop4879-7-5" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4877-6-5" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-4"/>
</linearGradient>
<filter id="filter25023" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25025" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25027" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941" id="linearGradient24963" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
<linearGradient inkscape:collect="always" id="linearGradient4941">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943"/>
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945"/>
</linearGradient>
<filter id="filter25033" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25035" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25037" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941-7" id="linearGradient24965" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
<linearGradient inkscape:collect="always" id="linearGradient4941-7">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943-2"/>
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945-5"/>
</linearGradient>
<filter id="filter25043" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25045" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25047" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<filter id="filter25049" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25051" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25053" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<filter id="filter25055" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25057" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25059" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
</defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.8284271" inkscape:cx="48.631638" inkscape:cy="57.536221" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="1200" inkscape:window-height="851" inkscape:window-x="0" inkscape:window-y="52" inkscape:window-maximized="0"/>
<metadata id="metadata25075">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer" transform="translate(0, 48)">
<g id="g4030-1-8" transform="matrix(2, 0, 0, 2, 193.25, -374.967)" style="stroke: rgb(0, 0, 0); display: inline; stroke-opacity: 1;">
<path sodipodi:nodetypes="ccc" id="path3165-7-3" d="m -72.5,173.5 -14,14 14,14" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 7; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;"/>
</g>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 185.28, -623.176)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4-8" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 207.28, -623.176)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 166.846, -534.143)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0-9" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 188.846, -534.143)"/>
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; opacity: 0.35; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 317.06251,365.96875 c -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 l -16.125,16.125 16.125,16.125 c 1.11265,1.11265 3.13735,1.11265 4.25,0 1.11265,-1.11264 1.11265,-3.13735 0,-4.25 l -11.875,-11.875 11.875,-11.875 c 0.86584,-0.83655 1.1475,-2.22114 0.6773,-3.32947 -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 z" id="path3165-7-3-1" sodipodi:nodetypes="ccccscccsc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-linecap: round; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 320.08435,397.03059 c 0.007,-0.79449 -0.27079,-1.59203 -0.83434,-2.15559 L 307.37501,383 m 12.5523,-15.20447 c -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 L 298.87501,383" id="path3165-7-3-1-9" sodipodi:nodetypes="ccccccc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="96"
height="96"
id="svg25070">
<defs
id="defs25072">
<linearGradient
x1="-86.552246"
y1="185.439"
x2="-83.37072"
y2="197.31261"
id="linearGradient24957"
xlink:href="#linearGradient4034-0-4"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6,0)" />
<linearGradient
id="linearGradient4034-0-4">
<stop
id="stop4036-5-7"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4038-9-6"
style="stop-color:#babdb6;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter24765">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix24767" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix24769" />
</filter>
<linearGradient
x1="-74.520325"
y1="169.06032"
x2="-74.520325"
y2="205.94189"
id="linearGradient24955"
xlink:href="#linearGradient4632-1-3-9-3-2"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,0)" />
<linearGradient
id="linearGradient4632-1-3-9-3-2">
<stop
id="stop4634-1-8-3-9-0"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4636-1-9-9-8-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0.0274937" />
<stop
id="stop4638-8-3-9-6-6"
style="stop-color:#f2f2f2;stop-opacity:1"
offset="0.274937" />
<stop
id="stop4640-8-5-7-8-9"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.38707438" />
<stop
id="stop4642-5-41-9-6-9"
style="stop-color:#d9dad8;stop-opacity:1"
offset="0.66528589" />
<stop
id="stop4644-5-2-7-9-2"
style="stop-color:#dfe0dd;stop-opacity:1"
offset="0.76745707" />
<stop
id="stop4646-3-2-3-7-3"
style="stop-color:#f0f0f0;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24959"
xlink:href="#linearGradient4869-4-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-1">
<stop
id="stop4871-6-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-4"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-1"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-0"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25011">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25013" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25015" />
</filter>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24961"
xlink:href="#linearGradient4869-4-0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-0">
<stop
id="stop4871-6-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-5"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-5"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-4"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25023">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25025" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25027" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24963"
xlink:href="#linearGradient4941"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941">
<stop
id="stop4943"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25033">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25035" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25037" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24965"
xlink:href="#linearGradient4941-7"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941-7">
<stop
id="stop4943-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945-5"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25043">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25045" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25047" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25049">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25051" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25053" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25055">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25057" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25059" />
</filter>
</defs>
<g
transform="translate(0,48)"
id="layer1">
<g
transform="matrix(-2,0,0,2,-97.2497,-374.967)"
id="g4030-1-8"
style="stroke:#000000;stroke-opacity:1;display:inline">
<path
d="m -72.5,173.5 -14,14 14,14"
id="path3165-7-3"
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
</g>
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-89.2797,-623.176)"
id="path4050-2-7-9-4"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-111.2797,-623.176)"
id="path4050-2-7-9-4-8"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-70.8457,-534.143)"
id="path4050-2-7-9-4-0"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-92.8457,-534.143)"
id="path4050-2-7-9-4-0-9"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m 47.87528,-34.0295 c 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25 -32.25,32.25 c -2.2253,2.2253 -6.2747,2.2253 -8.5,0 -2.2253,-2.22528 -2.2253,-6.2747 0,-8.5 l 23.75,-23.75 -23.75,-23.75 c -1.73168,-1.6731 -2.295,-4.44228 -1.3546,-6.65894 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 z"
id="path3165-7-3-1"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
<path
d="m 41.8316,28.09418 c -0.014,-1.58898 0.54158,-3.18406 1.66868,-4.31118 l 23.75,-23.75 m -25.1046,-30.40894 c 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25"
id="path3165-7-3-1-9"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,4 +1,6 @@
jsmiscdir = $(pkgdatadir)/js/misc
dist_jsmisc_DATA = \
docInfo.js
docInfo.js \
format.js \
params.js

View File

@ -7,6 +7,7 @@ const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Search = imports.ui.search;
const Main = imports.ui.main;
const THUMBNAIL_ICON_MARGIN = 2;
@ -17,69 +18,43 @@ function DocInfo(recentInfo) {
DocInfo.prototype = {
_init : function(recentInfo) {
this._recentInfo = recentInfo;
this.recentInfo = recentInfo;
// We actually used get_modified() instead of get_visited()
// here, as GtkRecentInfo doesn't updated get_visited()
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
this.timestamp = recentInfo.get_modified().getTime() / 1000;
this.name = recentInfo.get_display_name();
this._lowerName = this.name.toLowerCase();
this.uri = recentInfo.get_uri();
this.mimeType = recentInfo.get_mime_type();
},
createIcon : function(size) {
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this._recentInfo);
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
},
launch : function() {
// While using Gio.app_info_launch_default_for_uri() would be
// shorter in terms of lines of code, we are not doing so
// because that would duplicate the work of retrieving the
// mime type.
let appInfo = Gio.app_info_get_default_for_type(this.mimeType, true);
if (appInfo != null) {
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
} else {
log("Failed to get default application info for mime type " + this.mimeType +
". Will try to use the last application that registered the document.");
let appName = this._recentInfo.last_application();
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
if (success) {
log("Will open a document with the following command: " + appExec);
// TODO: Change this once better support for creating
// GAppInfo is added to GtkRecentInfo, as right now
// this relies on the fact that the file uri is
// already a part of appExec, so we don't supply any
// files to appInfo.launch().
// The 'command line' passed to
// create_from_command_line is allowed to contain
// '%<something>' macros that are expanded to file
// name / icon name, etc, so we need to escape % as %%
appExec = appExec.replace(/%/g, "%%");
let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
// The point of passing an app launch context to
// launch() is mostly to get startup notification and
// associated benefits like the app appearing on the
// right desktop; but it doesn't really work for now
// because with the way we create the appInfo we
// aren't reading the application's desktop file, and
// thus don't find the StartupNotify=true in it. So,
// despite passing the app launch context, no startup
// notification occurs.
appInfo.launch([], Main.createAppLaunchContext());
} else {
log("Failed to get application info for " + this.uri);
}
}
Shell.DocSystem.get_default().open(this.recentInfo);
},
exists : function() {
return this._recentInfo.exists();
matchTerms: function(terms) {
let mtype = Search.MatchType.NONE;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
let idx = this._lowerName.indexOf(term);
if (idx == 0) {
if (mtype != Search.MatchType.NONE)
return Search.MatchType.MULTIPLE;
mtype = Search.MatchType.PREFIX;
} else if (idx > 0) {
if (mtype != Search.MatchType.NONE)
return Search.MatchType.MULTIPLE;
mtype = Search.MatchType.SUBSTRING;
} else {
continue;
}
}
return mtype;
}
};
@ -91,50 +66,86 @@ function getDocManager() {
return docManagerInstance;
}
/**
* DocManager wraps the DocSystem, primarily to expose DocInfo objects
* which conform to the GenericDisplay item API.
*/
function DocManager() {
this._init();
}
DocManager.prototype = {
_init: function() {
this._recentManager = Gtk.RecentManager.get_default();
this._items = {};
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
this._reload();
this.emit('changed');
}));
this._docSystem = Shell.DocSystem.get_default();
this._infosByTimestamp = [];
this._infosByUri = {};
this._docSystem.connect('changed', Lang.bind(this, this._reload));
this._reload();
},
_reload: function() {
let docs = this._recentManager.get_items();
let newItems = {};
let docs = this._docSystem.get_all();
this._infosByTimestamp = [];
this._infosByUri = {};
for (let i = 0; i < docs.length; i++) {
let recentInfo = docs[i];
if (!recentInfo.exists())
continue;
let docInfo = new DocInfo(recentInfo);
// we use GtkRecentInfo URI as an item Id
newItems[docInfo.uri] = docInfo;
this._infosByTimestamp.push(docInfo);
this._infosByUri[docInfo.uri] = docInfo;
}
let deleted = {};
for (var uri in this._items) {
if (!(uri in newItems))
deleted[uri] = this._items[uri];
}
/* If we'd cached any thumbnail references that no longer exist,
dump them here */
let texCache = Shell.TextureCache.get_default();
for (var uri in deleted) {
texCache.evict_recent_thumbnail(this._items[uri]);
}
this._items = newItems;
this.emit('changed');
},
getItems: function() {
return this._items;
getTimestampOrderedInfos: function() {
return this._infosByTimestamp;
},
getInfosByUri: function() {
return this._infosByUri;
},
lookupByUri: function(uri) {
return this._infosByUri[uri];
},
queueExistenceCheck: function(count) {
return this._docSystem.queue_existence_check(count);
},
initialSearch: function(terms) {
let multipleMatches = [];
let prefixMatches = [];
let substringMatches = [];
for (let i = 0; i < this._infosByTimestamp.length; i++) {
let item = this._infosByTimestamp[i];
let mtype = item.matchTerms(terms);
if (mtype == Search.MatchType.MULTIPLE)
multipleMatches.push(item.uri);
else if (mtype == Search.MatchType.PREFIX)
prefixMatches.push(item.uri);
else if (mtype == Search.MatchType.SUBSTRING)
substringMatches.push(item.uri);
}
return multipleMatches.concat(prefixMatches.concat(substringMatches));
},
subsearch: function(previousResults, terms) {
let multipleMatches = [];
let prefixMatches = [];
let substringMatches = [];
for (let i = 0; i < previousResults.length; i++) {
let uri = previousResults[i];
let item = this._infosByUri[uri];
let mtype = item.matchTerms(terms);
if (mtype == Search.MatchType.MULTIPLE)
multipleMatches.push(uri);
else if (mtype == Search.MatchType.PREFIX)
prefixMatches.push(uri);
else if (mtype == Search.MatchType.SUBSTRING)
substringMatches.push(uri);
}
return multipleMatches.concat(prefixMatches.concat(substringMatches));
}
}

44
js/misc/format.js Normal file
View File

@ -0,0 +1,44 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* This function is intended to extend the String object and provide
* an String.format API for string formatting.
* It has to be set up using String.prototype.format = Format.format;
* Usage:
* "somestring %s %d".format('hello', 5);
* It supports %s, %d and %f, for %f it also support precisions like
* "%.2f".format(1.526)
*/
function format() {
let str = this;
let i = 0;
let args = arguments;
return str.replace(/%(?:\.([0-9]+))?(.)/g, function (str, precisionGroup, genericGroup) {
if (precisionGroup != '' && genericGroup != 'f')
throw new Error("Precision can only be specified for 'f'");
switch (genericGroup) {
case '%':
return '%';
break;
case 's':
return args[i++].toString();
break;
case 'd':
return parseInt(args[i++]);
break;
case 'f':
if (precisionGroup == '')
return parseFloat(args[i++]);
else
return parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
break;
default:
throw new Error('Unsupported conversion character %' + genericGroup);
}
return ""; // Suppress warning
});
}

33
js/misc/params.js Normal file
View File

@ -0,0 +1,33 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// parse:
// @params: caller-provided parameter object, or %null
// @default: function-provided defaults object
// @allowExtras: whether or not to allow properties not in @default
//
// Examines @params and fills in default values from @defaults for
// any properties in @defaults that don't appear in @params. If
// @allowExtras is not %true, it will throw an error if @params
// contains any properties that aren't in @defaults.
//
// If @params is %null, this returns @defaults.
//
// Return value: the updated params
function parse(params, defaults, allowExtras) {
if (!params)
return defaults;
if (!allowExtras) {
for (let prop in params) {
if (!(prop in defaults))
throw new Error('Unrecognized parameter "' + prop + '"');
}
}
for (let prop in defaults) {
if (!(prop in params))
params[prop] = defaults[prop];
}
return params;
}

View File

@ -3,23 +3,34 @@ jsuidir = $(pkgdatadir)/js/ui
dist_jsui_DATA = \
altTab.js \
appDisplay.js \
appIcon.js \
button.js \
appFavorites.js \
calendar.js \
chrome.js \
dash.js \
dnd.js \
docDisplay.js \
environment.js \
extensionSystem.js \
genericDisplay.js \
lightbox.js \
link.js \
lookingGlass.js \
main.js \
messageTray.js \
notificationDaemon.js \
overview.js \
panel.js \
places.js \
placeDisplay.js \
runDialog.js \
search.js \
shellDBus.js \
sidebar.js \
statusMenu.js \
tweener.js \
widget.js \
widgetBox.js \
windowAttentionHandler.js \
windowManager.js \
workspaces.js
workspacesView.js \
workspaceSwitcherPopup.js \
workspace.js

View File

@ -2,33 +2,37 @@
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const POPUP_BG_COLOR = new Clutter.Color();
POPUP_BG_COLOR.from_pixel(0x00000080);
const POPUP_INDICATOR_COLOR = new Clutter.Color();
POPUP_INDICATOR_COLOR.from_pixel(0xf0f0f0ff);
const POPUP_TRANSPARENT = new Clutter.Color();
POPUP_TRANSPARENT.from_pixel(0x00000000);
const POPUP_ARROW_COLOR = new Clutter.Color();
POPUP_ARROW_COLOR.from_pixel(0xffffffff);
const POPUP_UNFOCUSED_ARROW_COLOR = new Clutter.Color();
POPUP_UNFOCUSED_ARROW_COLOR.from_pixel(0x808080ff);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const POPUP_INDICATOR_WIDTH = 4;
const POPUP_GRID_SPACING = 8;
const POPUP_ICON_SIZE = 48;
const POPUP_NUM_COLUMNS = 5;
const POPUP_APPICON_SIZE = 96;
const POPUP_LIST_SPACING = 8;
const POPUP_LABEL_MAX_WIDTH = POPUP_NUM_COLUMNS * (POPUP_ICON_SIZE + POPUP_GRID_SPACING);
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds
const OVERLAY_COLOR = new Clutter.Color();
OVERLAY_COLOR.from_pixel(0x00000044);
const THUMBNAIL_SIZE = 256;
const THUMBNAIL_POPUP_TIME = 500; // milliseconds
const THUMBNAIL_FADE_TIME = 0.2; // seconds
const SHOW_TIME = 0.05;
const SWITCH_TIME = 0.1;
function mod(a, b) {
return (a + b) % b;
}
function AltTabPopup() {
this._init();
@ -36,244 +40,738 @@ function AltTabPopup() {
AltTabPopup.prototype = {
_init : function() {
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
corner_radius: POPUP_GRID_SPACING,
padding: POPUP_GRID_SPACING,
spacing: POPUP_GRID_SPACING,
orientation: Big.BoxOrientation.VERTICAL });
this.actor = new Clutter.Group({ reactive: true,
x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height });
// Icon grid. TODO: Investigate Nbtk.Grid once that lands. Currently
// just implemented using a chain of Big.Box.
this._grid = new Big.Box({ spacing: POPUP_GRID_SPACING,
orientation: Big.BoxOrientation.VERTICAL });
let gcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER });
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
// Selected-window label
this._label = new Clutter.Text({ font_name: "Sans 16px",
ellipsize: Pango.EllipsizeMode.END });
this._haveModal = false;
let labelbox = new Big.Box({ background_color: POPUP_INDICATOR_COLOR,
corner_radius: POPUP_GRID_SPACING / 2,
padding: POPUP_GRID_SPACING / 2 });
labelbox.append(this._label, Big.BoxPackFlags.NONE);
let lcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
width: POPUP_LABEL_MAX_WIDTH + POPUP_GRID_SPACING });
lcenterbox.append(labelbox, Big.BoxPackFlags.NONE);
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
this._currentApp = 0;
this._currentWindow = 0;
this._thumbnailTimeoutId = 0;
this._motionTimeoutId = 0;
// Indicator around selected icon
this._indicator = new Big.Rectangle({ border_width: POPUP_INDICATOR_WIDTH,
corner_radius: POPUP_INDICATOR_WIDTH / 2,
border_color: POPUP_INDICATOR_COLOR,
color: POPUP_TRANSPARENT });
this.actor.append(this._indicator, Big.BoxPackFlags.FIXED);
this._items = [];
this._toplevels = global.window_group.get_children();
// Initially disable hover so we ignore the enter-event if
// the switcher appears underneath the current pointer location
this._disableHover();
global.stage.add_actor(this.actor);
// Dark translucent window used to cover all but the
// currently-selected window while Alt-Tabbing. Actually
// contains four actors which can we rearrange to create
// a hole in the overlay.
this._overlay = new Clutter.Group({ reactive: true });
this._overlay_top = new Clutter.Rectangle({ color: OVERLAY_COLOR,
border_width: 0 });
this._overlay_bottom = new Clutter.Rectangle({ color: OVERLAY_COLOR,
border_width: 0 });
this._overlay_left = new Clutter.Rectangle({ color: OVERLAY_COLOR,
border_width: 0 });
this._overlay_right = new Clutter.Rectangle({ color: OVERLAY_COLOR,
border_width: 0 });
this._overlay.add_actor(this._overlay_top);
this._overlay.add_actor(this._overlay_bottom);
this._overlay.add_actor(this._overlay_left);
this._overlay.add_actor(this._overlay_right);
},
addWindow : function(win) {
let item = { window: win,
metaWindow: win.get_meta_window() };
show : function(backward) {
let tracker = Shell.WindowTracker.get_default();
let apps = tracker.get_running_apps ("");
let pixbuf = item.metaWindow.icon;
item.icon = new Clutter.Texture({ width: POPUP_ICON_SIZE,
height: POPUP_ICON_SIZE,
keep_aspect_ratio: true });
Shell.clutter_texture_set_from_pixbuf(item.icon, pixbuf);
if (!apps.length)
return false;
item.box = new Big.Box({ padding: POPUP_INDICATOR_WIDTH * 2 });
item.box.append(item.icon, Big.BoxPackFlags.NONE);
if (!Main.pushModal(this.actor))
return false;
this._haveModal = true;
item.above = null;
for (let i = 1; i < this._toplevels.length; i++) {
if (this._toplevels[i] == win) {
item.above = this._toplevels[i - 1];
break;
this._keyPressEventId = global.stage.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this._keyReleaseEventId = global.stage.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
this._appSwitcher = new AppSwitcher(apps);
this.actor.add_actor(this._appSwitcher.actor);
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
let focus = global.get_focus_monitor();
this._appSwitcher.actor.x = focus.x + Math.floor((focus.width - this._appSwitcher.actor.width) / 2);
this._appSwitcher.actor.y = focus.y + Math.floor((focus.height - this._appSwitcher.actor.height) / 2);
this._appIcons = this._appSwitcher.icons;
// Make the initial selection
if (this._appIcons.length == 1) {
if (!backward && this._appIcons[0].cachedWindows.length > 1) {
// For compatibility with the multi-app case below
this._select(0, 1, true);
} else
this._select(0);
} else if (backward) {
this._select(this._appIcons.length - 1);
} else {
let firstWindows = this._appIcons[0].cachedWindows;
if (firstWindows.length > 1) {
let curAppNextWindow = firstWindows[1];
let nextAppWindow = this._appIcons[1].cachedWindows[0];
// If the next window of the current app is more-recently-used
// than the first window of the next app, then select it.
if (curAppNextWindow.get_workspace() == global.screen.get_active_workspace() &&
curAppNextWindow.get_user_time() > nextAppWindow.get_user_time())
this._select(0, 1, true);
else
this._select(1);
} else
this._select(1);
}
// There's a race condition; if the user released Alt before
// we got the grab, then we won't be notified. (See
// https://bugzilla.gnome.org/show_bug.cgi?id=596695 for
// details.) So we check now. (Have to do this after updating
// selection.)
let mods = global.get_modifier_keys();
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
this._finish();
return false;
}
return true;
},
_nextApp : function() {
return mod(this._currentApp + 1, this._appIcons.length);
},
_previousApp : function() {
return mod(this._currentApp - 1, this._appIcons.length);
},
_nextWindow : function() {
return mod(this._currentWindow + 1,
this._appIcons[this._currentApp].cachedWindows.length);
},
_previousWindow : function() {
return mod(this._currentWindow - 1,
this._appIcons[this._currentApp].cachedWindows.length);
},
_keyPressEvent : function(actor, event) {
let keysym = event.get_key_symbol();
let shift = (Shell.get_event_state(event) & Clutter.ModifierType.SHIFT_MASK);
this._disableHover();
// The WASD stuff is for debugging in Xephyr, where the arrow
// keys aren't mapped correctly
if (keysym == Clutter.grave)
this._select(this._currentApp, shift ? this._previousWindow() : this._nextWindow());
else if (keysym == Clutter.Escape)
this.destroy();
else if (this._thumbnailsFocused) {
if (keysym == Clutter.Tab) {
if (shift && this._currentWindow == 0)
this._select(this._previousApp());
else if (!shift && this._currentWindow == this._appIcons[this._currentApp].cachedWindows.length - 1)
this._select(this._nextApp());
else
this._select(this._currentApp, shift ? this._previousWindow() : this._nextWindow());
} else if (keysym == Clutter.Left || keysym == Clutter.a)
this._select(this._currentApp, this._previousWindow());
else if (keysym == Clutter.Right || keysym == Clutter.d)
this._select(this._currentApp, this._nextWindow());
else if (keysym == Clutter.Up || keysym == Clutter.w)
this._select(this._currentApp, null, true);
} else {
if (keysym == Clutter.Tab)
this._select(shift ? this._previousApp() : this._nextApp());
else if (keysym == Clutter.Left || keysym == Clutter.a)
this._select(this._previousApp());
else if (keysym == Clutter.Right || keysym == Clutter.d)
this._select(this._nextApp());
else if (keysym == Clutter.Down || keysym == Clutter.s)
this._select(this._currentApp, this._currentWindow);
}
return true;
},
_keyReleaseEvent : function(actor, event) {
let keysym = event.get_key_symbol();
if (keysym == Clutter.Alt_L || keysym == Clutter.Alt_R)
this._finish();
return true;
},
_onScroll : function(actor, event) {
let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.UP) {
if (this._thumbnailsFocused) {
if (this._currentWindow == 0)
this._select(this._previousApp());
else
this._select(this._currentApp, this._previousWindow());
} else {
let nwindows = this._appIcons[this._currentApp].cachedWindows.length;
if (nwindows > 1)
this._select(this._currentApp, nwindows - 1);
else
this._select(this._previousApp());
}
} else if (direction == Clutter.ScrollDirection.DOWN) {
if (this._thumbnailsFocused) {
if (this._currentWindow == this._appIcons[this._currentApp].cachedWindows.length - 1)
this._select(this._nextApp());
else
this._select(this._currentApp, this._nextWindow());
} else {
let nwindows = this._appIcons[this._currentApp].cachedWindows.length;
if (nwindows > 1)
this._select(this._currentApp, 0);
else
this._select(this._nextApp());
}
}
item.visible = item.metaWindow.showing_on_its_workspace();
if (!item.visible) {
let rect = new Meta.Rectangle();
if (item.metaWindow.get_icon_geometry(rect))
item.icon_rect = rect;
}
item.n = this._items.length;
this._items.push(item);
// Add it to the grid
if (!this._gridRow || this._gridRow.get_children().length == POPUP_NUM_COLUMNS) {
this._gridRow = new Big.Box({ spacing: POPUP_GRID_SPACING,
orientation: Big.BoxOrientation.HORIZONTAL });
this._grid.append(this._gridRow, Big.BoxPackFlags.NONE);
}
this._gridRow.append(item.box, Big.BoxPackFlags.NONE);
},
show : function(initialSelection) {
global.window_group.add_actor(this._overlay);
this._overlay.raise_top();
this._overlay.show();
this.actor.opacity = 0;
Tweener.addTween(this.actor, { opacity: 255,
time: SHOW_TIME,
transition: "easeOutQuad" });
_clickedOutside : function(actor, event) {
this.destroy();
},
this.actor.show_all();
this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2);
this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2);
_appActivated : function(appSwitcher, n) {
// If the user clicks on the selected app, activate the
// selected window; otherwise (eg, they click on an app while
// !mouseActive) activate the first window of the clicked-on
// app.
let window = (n == this._currentApp) ? this._currentWindow : 0;
Main.activateWindow(this._appIcons[n].cachedWindows[window]);
this.destroy();
},
this.select(initialSelection);
_appEntered : function(appSwitcher, n) {
if (!this._mouseActive)
return;
this._select(n);
},
_windowActivated : function(thumbnailList, n) {
Main.activateWindow(this._appIcons[this._currentApp].cachedWindows[n]);
this.destroy();
},
_windowEntered : function(thumbnailList, n) {
if (!this._mouseActive)
return;
this._select(this._currentApp, n);
},
_disableHover : function() {
this._mouseActive = false;
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, Lang.bind(this, this._mouseTimedOut));
},
_mouseTimedOut : function() {
this._motionTimeoutId = 0;
this._mouseActive = true;
},
_finish : function() {
let app = this._appIcons[this._currentApp];
let window = app.cachedWindows[this._currentWindow];
Main.activateWindow(window);
this.destroy();
},
destroy : function() {
this.actor.destroy();
this._overlay.destroy();
},
select : function(n) {
if (this._selected) {
// Unselect previous
_onDestroy : function() {
if (this._haveModal)
Main.popModal(this.actor);
if (this._allocationChangedId) {
this._selected.box.disconnect(this._allocationChangedId);
delete this._allocationChangedId;
}
if (this._keyPressEventId)
global.stage.disconnect(this._keyPressEventId);
if (this._keyReleaseEventId)
global.stage.disconnect(this._keyReleaseEventId);
if (this._selected.above)
this._selected.window.raise(this._selected.above);
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
if (this._thumbnailTimeoutId != 0)
Mainloop.source_remove(this._thumbnailTimeoutId);
},
/**
* _select:
* @app: index of the app to select
* @window: (optional) index of which of @app's windows to select
* @forceAppFocus: optional flag, see below
*
* Selects the indicated @app, and optional @window, and sets
* this._thumbnailsFocused appropriately to indicate whether the
* arrow keys should act on the app list or the thumbnail list.
*
* If @app is specified and @window is unspecified or %null, then
* the app is highlighted (ie, given a light background), and the
* current thumbnail list, if any, is destroyed. If @app has
* multiple windows, and @forceAppFocus is not %true, then a
* timeout is started to open a thumbnail list.
*
* If @app and @window are specified (and @forceAppFocus is not),
* then @app will be outlined, a thumbnail list will be created
* and focused (if it hasn't been already), and the @window'th
* window in it will be highlighted.
*
* If @app and @window are specified and @forceAppFocus is %true,
* then @app will be highlighted, and @window outlined, and the
* app list will have the keyboard focus.
*/
_select : function(app, window, forceAppFocus) {
if (app != this._currentApp || window == null) {
if (this._thumbnails)
this._destroyThumbnails();
}
if (this._thumbnailTimeoutId != 0) {
Mainloop.source_remove(this._thumbnailTimeoutId);
this._thumbnailTimeoutId = 0;
}
this._thumbnailsFocused = (window != null) && !forceAppFocus;
this._currentApp = app;
this._currentWindow = window ? window : 0;
this._appSwitcher.highlight(app, this._thumbnailsFocused);
if (window != null) {
if (!this._thumbnails)
this._createThumbnails();
this._currentWindow = window;
this._thumbnails.highlight(window, forceAppFocus);
} else if (this._appIcons[this._currentApp].cachedWindows.length > 1 &&
!forceAppFocus) {
this._thumbnailTimeoutId = Mainloop.timeout_add (
THUMBNAIL_POPUP_TIME,
Lang.bind(this, function () {
this._select(this._currentApp, 0, true);
return false;
}));
}
},
_destroyThumbnails : function() {
Tweener.addTween(this._thumbnails.actor,
{ opacity: 0,
time: THUMBNAIL_FADE_TIME,
transition: "easeOutQuad",
onComplete: function() { this.destroy(); }
});
this._thumbnails = null;
},
_createThumbnails : function() {
this._thumbnails = new ThumbnailList (this._appIcons[this._currentApp].cachedWindows);
this._thumbnails.connect('item-activated', Lang.bind(this, this._windowActivated));
this._thumbnails.connect('item-entered', Lang.bind(this, this._windowEntered));
this.actor.add_actor(this._thumbnails.actor);
let thumbnailCenter;
if (this._thumbnails.actor.width < this._appSwitcher.actor.width) {
// Center the thumbnails under the corresponding AppIcon.
// If this is being called when the switcher is first
// being brought up, then nothing will have been assigned
// an allocation yet, and the get_transformed_position()
// call will return 0,0.
// (http://bugzilla.openedhand.com/show_bug.cgi?id=1115).
// Calling clutter_actor_get_allocation_box() would force
// it to properly allocate itself, but we can't call that
// because it has an out-caller-allocates arg. So we use
// clutter_stage_get_actor_at_pos(), which will force a
// reallocation as a side effect.
global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, 0, 0);
let icon = this._appIcons[this._currentApp].actor;
let [stageX, stageY] = icon.get_transformed_position();
thumbnailCenter = stageX + icon.width / 2;
} else {
// Center the thumbnails on the monitor
let focus = global.get_focus_monitor();
thumbnailCenter = focus.x + focus.width / 2;
}
this._thumbnails.actor.x = Math.floor(thumbnailCenter - this._thumbnails.actor.width / 2);
this._thumbnails.actor.y = this._appSwitcher.actor.y + this._appSwitcher.actor.height + POPUP_LIST_SPACING;
this._thumbnails.actor.opacity = 0;
Tweener.addTween(this._thumbnails.actor,
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: "easeOutQuad"
});
}
};
function SwitcherList(squareItems) {
this._init(squareItems);
}
SwitcherList.prototype = {
_init : function(squareItems) {
this.actor = new St.Bin({ style_class: 'switcher-list' });
// Here we use a GenericContainer so that we can force all the
// children except the separator to have the same width.
this._list = new Shell.GenericContainer();
this._list.spacing = POPUP_LIST_SPACING;
this._list.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._list.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._list.connect('allocate', Lang.bind(this, this._allocate));
this.actor.add_actor(this._list);
this._items = [];
this._highlighted = -1;
this._separator = null;
this._squareItems = squareItems;
},
addItem : function(item) {
let bbox = new St.Clickable({ style_class: 'item-box',
reactive: true });
bbox.set_child(item);
this._list.add_actor(bbox);
let n = this._items.length;
bbox.connect('clicked', Lang.bind(this, function () {
this._itemActivated(n);
}));
bbox.connect('enter-event', Lang.bind(this, function () {
this._itemEntered(n);
}));
this._items.push(bbox);
},
addSeparator: function () {
let box = new St.Bin({ style_class: 'separator' })
this._separator = box;
this._list.add_actor(box);
},
highlight: function(index, justOutline) {
if (this._highlighted != -1)
this._items[this._highlighted].style_class = 'item-box';
this._highlighted = index;
if (this._highlighted != -1) {
if (justOutline)
this._items[this._highlighted].style_class = 'outlined-item-box';
else
this._selected.window.lower_bottom();
this._items[this._highlighted].style_class = 'selected-item-box';
}
},
_itemActivated: function(n) {
this.emit('item-activated', n);
},
_itemEntered: function(n) {
this.emit('item-entered', n);
},
_maxChildWidth: function (forHeight) {
let maxChildMin = 0;
let maxChildNat = 0;
for (let i = 0; i < this._items.length; i++) {
let [childMin, childNat] = this._items[i].get_preferred_width(forHeight);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
if (this._squareItems) {
let [childMin, childNat] = this._items[i].get_preferred_height(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
}
}
let item = this._items[n];
let changed = this._selected && item != this._selected;
this._selected = item;
return [maxChildMin, maxChildNat];
},
if (this._selected) {
this._label.set_size(-1, -1);
this._label.text = this._selected.metaWindow.title;
if (this._label.width > POPUP_LABEL_MAX_WIDTH)
this._label.width = POPUP_LABEL_MAX_WIDTH;
_getPreferredWidth: function (actor, forHeight, alloc) {
let [maxChildMin, maxChildNat] = this._maxChildWidth(forHeight);
// Figure out this._selected.box's coordinates in terms of
// this.actor
let bx = this._selected.box.x, by = this._selected.box.y;
let actor = this._selected.box.get_parent();
while (actor != this.actor) {
bx += actor.x;
by += actor.y;
actor = actor.get_parent();
}
let separatorWidth = 0;
if (this._separator) {
let [sepMin, sepNat] = this._separator.get_preferred_width(forHeight);
separatorWidth = sepNat + this._list.spacing;
}
if (changed) {
Tweener.addTween(this._indicator,
{ x: bx,
y: by,
width: this._selected.box.width,
height: this._selected.box.height,
time: SWITCH_TIME,
transition: "easeOutQuad" });
let totalSpacing = this._list.spacing * (this._items.length - 1);
alloc.min_size = this._items.length * maxChildMin + separatorWidth + totalSpacing;
alloc.natural_size = alloc.min_size;
},
_getPreferredHeight: function (actor, forWidth, alloc) {
let maxChildMin = 0;
let maxChildNat = 0;
for (let i = 0; i < this._items.length; i++) {
let [childMin, childNat] = this._items[i].get_preferred_height(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
}
if (this._squareItems) {
let [childMin, childNat] = this._maxChildWidth(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = maxChildMin;
}
alloc.min_size = maxChildMin;
alloc.natural_size = maxChildNat;
},
_allocate: function (actor, box, flags) {
let childHeight = box.y2 - box.y1;
let [maxChildMin, maxChildNat] = this._maxChildWidth(childHeight);
let totalSpacing = this._list.spacing * (this._items.length - 1);
let separatorWidth = 0;
if (this._separator) {
let [sepMin, sepNat] = this._separator.get_preferred_width(childHeight);
separatorWidth = sepNat;
totalSpacing += this._list.spacing;
}
let childWidth = Math.floor(Math.max(0, box.x2 - box.x1 - totalSpacing - separatorWidth) / this._items.length);
let x = 0;
let children = this._list.get_children();
let childBox = new Clutter.ActorBox();
for (let i = 0; i < children.length; i++) {
if (this._items.indexOf(children[i]) != -1) {
let [childMin, childNat] = children[i].get_preferred_height(childWidth);
let vSpacing = (childHeight - childNat) / 2;
childBox.x1 = x;
childBox.y1 = vSpacing;
childBox.x2 = x + childWidth;
childBox.y2 = childBox.y1 + childNat;
children[i].allocate(childBox, flags);
x += this._list.spacing + childWidth;
} else if (children[i] == this._separator) {
// We want the separator to be more compact than the rest.
childBox.x1 = x;
childBox.y1 = 0;
childBox.x2 = x + separatorWidth;
childBox.y2 = childHeight;
children[i].allocate(childBox, flags);
x += this._list.spacing + separatorWidth;
} else {
Tweener.removeTweens(this.indicator);
this._indicator.set_position(bx, by);
this._indicator.set_size(this._selected.box.width,
this._selected.box.height);
// Something else, eg, AppSwitcher's arrows;
// we don't allocate it.
}
this._indicator.show();
if (this._overlay.visible) {
if (this._selected.visible)
this._selected.window.raise(this._overlay);
this._adjust_overlay();
}
this._allocationChangedId =
this._selected.box.connect('notify::allocation',
Lang.bind(this, this._allocationChanged));
} else {
this._label.text = "";
this._indicator.hide();
}
},
_allocationChanged : function() {
if (this._selected)
this.select(this._selected.n);
},
_adjust_overlay : function() {
if (this._selected && this._selected.icon_rect) {
// We want to highlight a specific rectangle within the
// task bar, so rearrange the pieces of the overlay to
// cover the whole screen except that rectangle
let rect = this._selected.icon_rect;
this._overlay_top.x = 0;
this._overlay_top.y = 0;
this._overlay_top.width = global.screen_width;
this._overlay_top.height = rect.y;
this._overlay_left.x = 0;
this._overlay_left.y = rect.y;
this._overlay_left.width = rect.x;
this._overlay_left.height = rect.height;
this._overlay_left.show();
this._overlay_right.x = rect.x + rect.width;
this._overlay_right.y = rect.y;
this._overlay_right.width = global.screen_width - rect.x - rect.width;
this._overlay_right.height = rect.height;
this._overlay_right.show();
this._overlay_bottom.x = 0;
this._overlay_bottom.y = rect.y + rect.height;
this._overlay_bottom.width = global.screen_width;
this._overlay_bottom.height = global.screen_height - rect.y - rect.height;
this._overlay_bottom.show();
} else {
// Either there's no current selection, or the selection
// is a visible window. Make the overlay cover the whole
// screen. select() will raise the selected window over
// the overlay.
this._overlay_top.x = 0;
this._overlay_top.y = 0;
this._overlay_top.width = global.screen_width;
this._overlay_top.height = global.screen_height;
this._overlay_top.show();
this._overlay_left.hide();
this._overlay_right.hide();
this._overlay_bottom.hide();
}
}
};
Signals.addSignalMethods(SwitcherList.prototype);
function AppIcon(app) {
this._init(app);
}
AppIcon.prototype = {
_init: function(app) {
this.app = app;
this.actor = new St.BoxLayout({ style_class: "alt-tab-app",
vertical: true });
this._icon = this.app.create_icon_texture(POPUP_APPICON_SIZE);
let iconBin = new St.Bin({height: POPUP_APPICON_SIZE, width: POPUP_APPICON_SIZE});
iconBin.child = this._icon;
this.actor.add(iconBin, { x_fill: false, y_fill: false } );
this._label = new St.Label({ text: this.app.get_name() });
this.actor.add(this._label, { x_fill: false });
}
}
function AppSwitcher(apps) {
this._init(apps);
}
AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(apps) {
SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, sort by time, add to the popup
let activeWorkspace = global.screen.get_active_workspace();
let workspaceIcons = [];
let otherIcons = [];
for (let i = 0; i < apps.length; i++) {
let appIcon = new AppIcon(apps[i]);
// Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it
appIcon.cachedWindows = appIcon.app.get_windows();
if (this._hasWindowsOnWorkspace(appIcon, activeWorkspace))
workspaceIcons.push(appIcon);
else
otherIcons.push(appIcon);
}
workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
otherIcons.sort(Lang.bind(this, this._sortAppIcon));
this.icons = [];
this._arrows = [];
for (let i = 0; i < workspaceIcons.length; i++)
this._addIcon(workspaceIcons[i]);
if (workspaceIcons.length > 0 && otherIcons.length > 0)
this.addSeparator();
for (let i = 0; i < otherIcons.length; i++)
this._addIcon(otherIcons[i]);
this._curApp = -1;
},
_allocate: function (actor, box, flags) {
// Allocate the main list items
SwitcherList.prototype._allocate.call(this, actor, box, flags);
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let arrowWidth = arrowHeight * 2;
// Now allocate each arrow underneath its item
let childBox = new Clutter.ActorBox();
for (let i = 0; i < this._items.length; i++) {
let itemBox = this._items[i].allocation;
childBox.x1 = Math.floor(itemBox.x1 + (itemBox.x2 - itemBox.x1 - arrowWidth) / 2);
childBox.x2 = childBox.x1 + arrowWidth;
childBox.y1 = itemBox.y2 + arrowHeight;
childBox.y2 = childBox.y1 + arrowHeight;
this._arrows[i].allocate(childBox, flags);
}
},
// We override SwitcherList's highlight() method to also deal with
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
// will hide their arrows by default, but show them when their
// thumbnails are visible (ie, when the app icon is supposed to be
// in justOutline mode). Apps with multiple windows will normally
// show a dim arrow, but show a bright arrow when they are
// highlighted; their redraw handler will use the right color
// based on this._curApp; we just need to do a queue_relayout() to
// force it to redraw. (queue_redraw() doesn't work because
// ShellDrawingArea only redraws on allocate.)
highlight : function(n, justOutline) {
if (this._curApp != -1) {
if (this.icons[this._curApp].cachedWindows.length == 1)
this._arrows[this._curApp].hide();
else
this._arrows[this._curApp].queue_relayout();
}
SwitcherList.prototype.highlight.call(this, n, justOutline);
this._curApp = n;
if (this._curApp != -1) {
if (justOutline && this.icons[this._curApp].cachedWindows.length == 1)
this._arrows[this._curApp].show();
else
this._arrows[this._curApp].queue_relayout();
}
},
_addIcon : function(appIcon) {
this.icons.push(appIcon);
this.addItem(appIcon.actor);
let n = this._arrows.length;
let arrow = new St.DrawingArea();
arrow.connect('redraw', Lang.bind(this,
function (area, texture) {
Shell.draw_box_pointer(texture, Shell.PointerDirection.DOWN,
TRANSPARENT_COLOR,
this._curApp == n ? POPUP_ARROW_COLOR : POPUP_UNFOCUSED_ARROW_COLOR);
}));
this._list.add_actor(arrow);
this._arrows.push(arrow);
if (appIcon.cachedWindows.length == 1)
arrow.hide();
},
_hasWindowsOnWorkspace: function(appIcon, workspace) {
let windows = appIcon.cachedWindows;
for (let i = 0; i < windows.length; i++) {
if (windows[i].get_workspace() == workspace)
return true;
}
return false;
},
_sortAppIcon : function(appIcon1, appIcon2) {
return appIcon1.app.compare(appIcon2.app);
}
};
function ThumbnailList(windows) {
this._init(windows);
}
ThumbnailList.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(windows) {
SwitcherList.prototype._init.call(this);
let activeWorkspace = global.screen.get_active_workspace();
// We fake the value of "separatorAdded" when the app has no window
// on the current workspace, to avoid displaying a useless separator in
// that case.
let separatorAdded = windows.length == 0 || windows[0].get_workspace() != activeWorkspace;
for (let i = 0; i < windows.length; i++) {
if (!separatorAdded && windows[i].get_workspace() != activeWorkspace) {
this.addSeparator();
separatorAdded = true;
}
let mutterWindow = windows[i].get_compositor_private();
let windowTexture = mutterWindow.get_texture ();
let [width, height] = windowTexture.get_size();
let scale = Math.min(1.0, THUMBNAIL_SIZE / width, THUMBNAIL_SIZE / height);
let box = new St.BoxLayout({ style_class: "thumbnail-box",
vertical: true });
let bin = new St.Bin({ style_class: "thumbnail" });
let clone = new Clutter.Clone ({ source: windowTexture,
reactive: true,
width: width * scale,
height: height * scale });
bin.add_actor(clone);
box.add_actor(bin);
let title = windows[i].get_title();
if (title) {
let name = new St.Label({ text: title });
// St.Label doesn't support text-align so use a Bin
let bin = new St.Bin({ x_align: St.Align.MIDDLE });
bin.add_actor(name);
box.add_actor(bin);
}
this.addItem(box);
}
}
};

File diff suppressed because it is too large Load Diff

120
js/ui/appFavorites.js Normal file
View File

@ -0,0 +1,120 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
function AppFavorites() {
this._init();
}
AppFavorites.prototype = {
FAVORITE_APPS_KEY: 'favorite_apps',
_init: function() {
this._favorites = {};
this._gconf = Shell.GConf.get_default();
this._gconf.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
this._reload();
},
_onFavsChanged: function() {
this._reload();
this.emit('changed');
},
_reload: function() {
let ids = Shell.GConf.get_default().get_string_list('favorite_apps');
let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) {
return appSys.get_app(id);
}).filter(function (app) {
return app != null;
});
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
this._favorites[app.get_id()] = app;
}
},
_getIds: function() {
let ret = [];
for (let id in this._favorites)
ret.push(id);
return ret;
},
getFavoriteMap: function() {
return this._favorites;
},
getFavorites: function() {
let ret = [];
for (let id in this._favorites)
ret.push(this._favorites[id]);
return ret;
},
isFavorite: function(appId) {
return appId in this._favorites;
},
_addFavorite: function(appId) {
if (appId in this._favorites)
return false;
let app = Shell.AppSystem.get_default().get_app(appId);
if (!app)
return false;
let ids = this._getIds();
ids.push(appId);
this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
this._favorites[appId] = app;
return true;
},
addFavorite: function(appId) {
if (!this._addFavorite(appId))
return;
let app = Shell.AppSystem.get_default().get_app(appId);
Main.overview.infoBar.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
this._removeFavorite(appId);
}));
},
_removeFavorite: function(appId) {
if (!appId in this._favorites)
return false;
let ids = this._getIds().filter(function (id) { return id != appId; });
this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
return true;
},
removeFavorite: function(appId) {
if (!this._removeFavorite(appId))
return;
Main.overview.infoBar.setMessage(_("%s has been removed from your favorites.").format(this._favorites[appId].get_name()),
Lang.bind(this, function () {
this._addFavorite(appId);
}));
}
};
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;
function getAppFavorites() {
if (appFavoritesInstance == null)
appFavoritesInstance = new AppFavorites();
return appFavoritesInstance;
}

View File

@ -1,133 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const GLOW_COLOR = new Clutter.Color();
GLOW_COLOR.from_pixel(0x4f6ba4ff);
const GLOW_PADDING_HORIZONTAL = 3;
const GLOW_PADDING_VERTICAL = 3;
const APP_ICON_SIZE = 48;
function AppIcon(appInfo) {
this._init(appInfo);
}
AppIcon.prototype = {
_init : function(appInfo) {
this.appInfo = appInfo;
this.windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
for (let i = 0; i < this.windows.length; i++) {
this.windows[i].connect('notify::user-time', Lang.bind(this, this._resortWindows));
}
this._resortWindows();
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
corner_radius: 2,
padding: 1,
reactive: true });
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER });
this.icon = appInfo.create_icon_texture(APP_ICON_SIZE);
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
let nameBox = new Shell.GenericContainer();
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
this._nameBox = nameBox;
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans 12px",
line_alignment: Pango.Alignment.CENTER,
ellipsize: Pango.EllipsizeMode.END,
text: appInfo.get_name() });
nameBox.add_actor(this._name);
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
for (let i = 0; i < this._windows.length && i < 3; i++) {
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
glowPath, -1, -1);
glow.keep_aspect_ratio = false;
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
}
this._nameBox.add_actor(this._glowBox);
this._glowBox.lower(this._name);
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
},
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
let [min, natural] = this._name.get_preferred_width(forHeight);
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
},
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
let [min, natural] = this._name.get_preferred_height(forWidth);
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
},
_nameBoxAllocate: function (nameBox, box, flags) {
let childBox = new Clutter.ActorBox();
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let targetWidth = availWidth;
let xPadding = 0;
if (naturalWidth < availWidth) {
xPadding = Math.floor((availWidth - naturalWidth) / 2);
}
childBox.x1 = xPadding;
childBox.x2 = availWidth - xPadding;
childBox.y1 = GLOW_PADDING_VERTICAL;
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
this._name.allocate(childBox, flags);
// Now the glow
if (this._glowBox != null) {
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
glowPaddingHoriz = Math.max(GLOW_PADDING_HORIZONTAL, glowPaddingHoriz);
childBox.x1 = glowPaddingHoriz;
childBox.x2 = availWidth - glowPaddingHoriz;
childBox.y1 = 0;
childBox.y2 = availHeight;
this._glowBox.allocate(childBox, flags);
}
},
_resortWindows: function() {
this.windows.sort(function (a, b) {
let timeA = a.get_user_time();
let timeB = b.get_user_time();
if (timeA == timeB)
return 0;
else if (timeA > timeB)
return -1;
return 1;
});
},
getDragActor: function() {
return this.appInfo.create_icon_texture(APP_ICON_SIZE);
},
getDragActorSource: function() {
return this.icon;
}
};

View File

@ -1,173 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Tweener = imports.ui.tweener;
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
const DEFAULT_TEXT_COLOR = new Clutter.Color();
DEFAULT_TEXT_COLOR.from_pixel(0x000000ff);
const DEFAULT_FONT = 'Sans Bold 16px';
// Padding on the left and right side of the button.
const SIDE_PADDING = 14;
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
}
Button.prototype = {
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
this._buttonColor = buttonColor
if (buttonColor == null)
this._buttonColor = DEFAULT_BUTTON_COLOR;
this._pressedButtonColor = pressedButtonColor
if (pressedButtonColor == null)
this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
this._textColor = textColor;
if (textColor == null)
this._textColor = DEFAULT_TEXT_COLOR;
this._font = font;
if (font == null)
this._font = DEFAULT_FONT;
this._isBetweenPressAndRelease = false;
this._mouseIsOverButton = false;
this.actor = new Shell.ButtonBox({ reactive: true,
corner_radius: 5,
padding_left: SIDE_PADDING,
padding_right: SIDE_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER
});
if (typeof widgetOrText == 'string') {
this._widget = new Clutter.Text({ font_name: this._font,
color: this._textColor,
text: widgetOrText });
} else {
this._widget = widgetOrText;
}
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
},
_updateColors : function() {
if (this.actor.active || this.actor.pressed)
this.actor.backgroundColor = this._pressedButtonColor;
else if (this.actor.hover)
this.actor.backgroundColor = this._buttonColor;
else
this.actor.backgroundColor = null;
}
};
Signals.addSignalMethods(Button.prototype);
/* Delay before the icon should appear, in seconds after the pointer has entered the parent */
const ANIMATION_TIME = 0.25;
/* This is an icon button that fades in/out when mouse enters/leaves the parent.
* A delay is used before the fading starts. You can force it to be shown if needed.
*
* parent -- used to show/hide the button depending on mouse entering/leaving it
* size -- size in pixels of both the button and the icon it contains
* texture -- optional, must be used if the texture for the icon is already created (else, use setIconFromName)
*/
function iconButton(parent, size, texture) {
this._init(parent, size, texture);
}
iconButton.prototype = {
_init : function(parent, size, texture) {
this._size = size;
if (texture)
this.actor = texture;
else
this.actor = new Clutter.Texture({ width: this._size, height: this._size });
this.actor.set_reactive(true);
this.actor.set_opacity(0);
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
this._shouldHide = false;
// Nothing to do if the cursor has come back from a child of the parent actor
if (actor.get_children().indexOf(event.get_related()) != -1)
return;
this._fadeIn();
}));
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
// Nothing to do if the cursor has merely entered a child of the parent actor
if (actor.get_children().indexOf(event.get_related()) != -1)
return;
// Remember that we should not be visible to hide the button if forceShow is unset
if (this._forceShow) {
this._shouldHide = true;
return;
}
this._fadeOut();
}));
},
/// Private methods ///
setIconFromName : function(iconName) {
let iconTheme = Gtk.IconTheme.get_default();
let iconInfo = iconTheme.lookup_icon(iconName, this._size, 0);
if (!iconInfo)
return;
let iconPath = iconInfo.get_filename();
this.actor.set_from_file(iconPath);
},
// Useful if we want to show the button immediately,
// e.g. in case the mouse is already in the parent when the button is created
show : function() {
this.actor.set_opacity(255);
},
// If show is true, prevents the button from fading out
forceShow : function(show) {
this._forceShow = show;
// Hide the button if it should have been hidden under normal conditions
if (!this._forceShow && this._shouldHide) {
this._fadeOut();
}
},
/// Private methods ///
_fadeIn : function() {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor, { opacity: 255,
time: ANIMATION_TIME,
transition :"easeInQuad" });
},
_fadeOut : function() {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor, { opacity: 0,
time: ANIMATION_TIME,
transition :"easeOutQuad" });
}
};

182
js/ui/calendar.js Normal file
View File

@ -0,0 +1,182 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Gettext_gtk20 = imports.gettext.domain('gtk20');
const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
function _sameDay(dateA, dateB) {
return (dateA.getDate() == dateB.getDate() &&
dateA.getMonth() == dateB.getMonth() &&
dateA.getYear() == dateB.getYear());
}
function Calendar() {
this._init();
};
Calendar.prototype = {
_init: function() {
// FIXME: This is actually the fallback method for GTK+ for the week start;
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
// should add a C function so we can do the full handling.
this._weekStart = NaN;
let weekStartString = Gettext_gtk20.gettext("calendar:week_start:0");
if (weekStartString.indexOf("calendar:week_start:") == 0) {
this._weekStart = parseInt(weekStartString.substring(20));
}
if (isNaN(this._weekStart) || this._weekStart < 0 || this._weekStart > 6) {
log("Translation of 'calendar:week_start:0' in GTK+ is not correct");
this._weekStart = 0;
}
// Find the ordering for month/year in the calendar heading
switch (Gettext_gtk20.gettext("calendar:MY")) {
case "calendar:MY":
this._headerFormat = "%B %Y";
break;
case "calendar:YM":
this._headerFormat = "%Y %B";
break;
default:
log("Translation of 'calendar:MY' in GTK+ is not correct");
this._headerFormat = "%B %Y";
break;
}
// Start off with the current date
this.date = new Date();
this.actor = new St.Table({ homogeneous: false,
style_class: "calendar",
reactive: true });
this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll));
// Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout();
this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: 7 });
let [backlabel, forwardlabel] = ["&lt;", "&gt;"];
if (St.Widget.get_default_direction () == St.TextDirection.RTL) {
[backlabel, forwardlabel] = [forwardlabel, backlabel];
}
let back = new St.Button({ label: backlabel, style_class: 'calendar-change-month' });
this._topBox.add(back);
back.connect("clicked", Lang.bind(this, this._prevMonth));
this._dateLabel = new St.Label();
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
this._topBox.add(forward);
forward.connect("clicked", Lang.bind(this, this._nextMonth));
// We need to figure out the abbreviated localized names for the days of the week;
// we do this by just getting the next 7 days starting from right now and then putting
// them in the right cell in the table. It doesn't matter if we add them in order
let iter = new Date(this.date);
iter.setSeconds(0); // Leap second protection. Hah!
iter.setHours(12);
for (let i = 0; i < 7; i++) {
this.actor.add(new St.Label({ text: iter.toLocaleFormat("%a") }),
{ row: 1,
col: (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: St.Align.END });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
// All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.actor.get_children().length;
this._update();
},
// Sets the calendar to show a specific date
setDate: function(date) {
if (!_sameDay(date, this.date)) {
this.date = date;
this._update();
}
},
_onScroll : function(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT:
this._prevMonth();
break;
case Clutter.ScrollDirection.DOWN:
case Clutter.ScrollDirection.RIGHT:
this._nextMonth();
break;
}
},
_prevMonth: function() {
if (this.date.getMonth() == 0) {
this.date.setMonth(11);
this.date.setFullYear(this.date.getFullYear() - 1);
} else {
this.date.setMonth(this.date.getMonth() - 1);
}
this._update();
},
_nextMonth: function() {
if (this.date.getMonth() == 11) {
this.date.setMonth(0);
this.date.setFullYear(this.date.getFullYear() + 1);
} else {
this.date.setMonth(this.date.getMonth() + 1);
}
this._update();
},
_update: function() {
this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat);
// Remove everything but the topBox and the weekday labels
let children = this.actor.get_children();
for (let i = this._firstDayIndex; i < children.length; i++)
children[i].destroy();
// Start at the beginning of the week before the start of the month
let iter = new Date(this.date);
iter.setDate(1);
iter.setSeconds(0);
iter.setHours(12);
iter.setTime(iter.getTime() - (iter.getDay() - this._weekStart) * MSECS_IN_DAY);
let now = new Date();
let row = 2;
while (true) {
let label = new St.Label({ text: iter.getDate().toString() });
if (_sameDay(now, iter))
label.style_class = "calendar-day calendar-today";
else if (iter.getMonth() != this.date.getMonth())
label.style_class = "calendar-day calendar-other-month-day";
else
label.style_class = "calendar-day";
this.actor.add(label,
{ row: row, col: (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: St.Align.END });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
if (iter.getDay() == this._weekStart) {
// We stop on the first "first day of the week" after the month we are displaying
if (iter.getMonth() > this.date.getMonth() || iter.getYear() > this.date.getYear())
break;
row++;
}
}
}
};

View File

@ -7,6 +7,7 @@ const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const Params = imports.misc.params;
// This manages the shell "chrome"; the UI that's visible in the
// normal mode (ie, outside the Overview), that surrounds the main
@ -54,7 +55,7 @@ Chrome.prototype = {
// addActor:
// @actor: an actor to add to the chrome layer
// @shapeActor: optional "shape actor".
// @params: (optional) additional params
//
// Adds @actor to the chrome layer and extends the input region
// and window manager struts to include it. (Window manager struts
@ -64,59 +65,45 @@ Chrome.prototype = {
// in its visibility will affect the input region, but NOT the
// struts.
//
// If @shapeActor is provided, it will be used instead of @actor
// for the input region/strut shape. (This lets you have things like
// drop shadows in @actor that don't affect the struts.) It must
// be a child of @actor. Alternatively, you can pass %null for
// @shapeActor to indicate that @actor should not affect the input
// region or struts at all.
addActor: function(actor, shapeActor) {
if (shapeActor === undefined)
shapeActor = actor;
else if (shapeActor && !this._verifyAncestry(shapeActor, actor))
throw new Error('shapeActor is not a descendent of actor');
// If %visibleInOverview is %true in @params, @actor will remain
// visible when the overview is brought up. Otherwise it will
// automatically be hidden. If %affectsStruts or %affectsInputRegion
// is %false, the actor will not have the indicated effect.
addActor: function(actor, params) {
params = Params.parse(params, { visibleInOverview: false,
affectsStruts: true,
affectsInputRegion: true });
this.nonOverviewActor.add_actor(actor);
if (shapeActor)
this._trackActor(shapeActor, true, true);
},
// setVisibleInOverview:
// @actor: an actor in the chrome layer
// @visible: Overview visibility
//
// By default, actors in the chrome layer are automatically hidden
// when the Overview is shown. This can be used to override that
// behavior
setVisibleInOverview: function(actor, visible) {
if (!this._verifyAncestry(actor, this.actor))
throw new Error('actor is not a descendent of the chrome layer');
if (visible)
actor.reparent(this.actor);
if (params.visibleInOverview)
this.actor.add_actor(actor);
else
actor.reparent(this.nonOverviewActor);
this.nonOverviewActor.add_actor(actor);
this._trackActor(actor, params.affectsInputRegion, params.affectsStruts);
},
// addInputRegionActor:
// @actor: an actor to add to the stage input region
// trackActor:
// @actor: a descendant of the chrome to begin tracking
// @params: parameters describing how to track @actor
//
// Adds @actor to the stage input region, as with addActor(), but
// for actors that are already descendants of the chrome layer.
addInputRegionActor: function(actor) {
// Tells the chrome to track @actor, which must be a descendant
// of an actor added via addActor(). This can be used to extend the
// struts or input region to cover specific children.
trackActor: function(actor, params) {
if (!this._verifyAncestry(actor, this.actor))
throw new Error('actor is not a descendent of the chrome layer');
this._trackActor(actor, true, false);
params = Params.parse(params, { affectsStruts: true,
affectsInputRegion: true });
this._trackActor(actor, params.affectsInputRegion, params.affectsStruts);
},
// removeInputRegionActor:
// @actor: an actor previously added to the stage input region
// untrackActor:
// @actor: an actor previously tracked via trackActor()
//
// Undoes the effect of addInputRegionActor()
removeInputRegionActor: function(actor) {
this._untrackActor(actor, true, false);
// Undoes the effect of trackActor()
untrackActor: function(actor) {
this._untrackActor(actor);
},
// removeActor:
@ -128,7 +115,7 @@ Chrome.prototype = {
this.nonOverviewActor.remove_actor(actor);
else
this.actor.remove_actor(actor);
this._untrackActor(actor, true, true);
this._untrackActor(actor);
},
_findActor: function(actor) {
@ -142,23 +129,13 @@ Chrome.prototype = {
_trackActor: function(actor, inputRegion, strut) {
let actorData;
let i = this._findActor(actor);
if (i != -1) {
actorData = this._trackedActors[i];
if (inputRegion)
actorData.inputRegion++;
if (strut)
actorData.strut++;
if (!inputRegion && !strut)
actorData.children++;
return;
}
if (this._findActor(actor) != -1)
throw new Error('trying to re-track existing chrome actor');
actorData = { actor: actor,
inputRegion: inputRegion ? 1 : 0,
strut: strut ? 1 : 0,
children: 0 };
inputRegion: inputRegion,
strut: strut };
actorData.visibleId = actor.connect('notify::visible',
Lang.bind(this, this._queueUpdateRegions));
@ -166,54 +143,31 @@ Chrome.prototype = {
Lang.bind(this, this._queueUpdateRegions));
actorData.parentSetId = actor.connect('parent-set',
Lang.bind(this, this._actorReparented));
// Note that destroying actor will unset its parent, so we don't
// need to connect to 'destroy' too.
this._trackedActors.push(actorData);
actor = actor.get_parent();
if (actor != this.actor && actor != this.nonOverviewActor)
this._trackActor(actor, false, false);
if (inputRegion || strut)
this._queueUpdateRegions();
this._queueUpdateRegions();
},
_untrackActor: function(actor, inputRegion, strut) {
_untrackActor: function(actor) {
let i = this._findActor(actor);
if (i == -1)
return;
let actorData = this._trackedActors[i];
if (inputRegion)
actorData.inputRegion--;
if (strut)
actorData.strut--;
if (!inputRegion && !strut)
actorData.children--;
this._trackedActors.splice(i, 1);
actor.disconnect(actorData.visibleId);
actor.disconnect(actorData.allocationId);
actor.disconnect(actorData.parentSetId);
if (actorData.inputRegion <= 0 && actorData.strut <= 0 && actorData.children <= 0) {
this._trackedActors.splice(i, 1);
actor.disconnect(actorData.visibleId);
actor.disconnect(actorData.allocationId);
actor.disconnect(actorData.parentSetId);
actor = actor.get_parent();
if (actor && actor != this.actor && actor != this.nonOverviewActor)
this._untrackActor(actor, false, false);
}
if (inputRegion || strut)
this._queueUpdateRegions();
this._queueUpdateRegions();
},
_actorReparented: function(actor, oldParent) {
if (this._verifyAncestry(actor, this.actor)) {
let newParent = actor.get_parent();
if (newParent != this.actor && newParent != this.nonOverviewActor)
this._trackActor(newParent, false, false);
}
if (oldParent != this.actor && oldParent != this.nonOverviewActor)
this._untrackActor(oldParent, false, false);
if (!this._verifyAncestry(actor, this.actor))
this._untrackActor(actor);
},
_overviewShowing: function() {
@ -237,6 +191,7 @@ Chrome.prototype = {
_windowsRestacked: function() {
let windows = global.get_windows();
let primary = global.get_primary_monitor();
// The chrome layer should be visible unless there is a window
// with layer FULLSCREEN, or a window with layer
@ -253,18 +208,21 @@ Chrome.prototype = {
this._obscuredByFullscreen = false;
for (let i = windows.length - 1; i > -1; i--) {
let layer = windows[i].get_meta_window().get_layer();
if (layer == Meta.StackLayer.FULLSCREEN) {
if (windows[i].x >= primary.x && windows[i].x <= primary.x + primary.width &&
windows[i].y >= primary.y && windows[i].y <= primary.y + primary.height) {
this._obscuredByFullscreen = true;
break;
}
}
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
if (windows[i].x <= 0 &&
windows[i].x + windows[i].width >= global.screen_width &&
windows[i].y <= 0 &&
windows[i].y + windows[i].height >= global.screen_height) {
if (windows[i].x <= primary.x &&
windows[i].x + windows[i].width >= primary.x + primary.width &&
windows[i].y <= primary.y &&
windows[i].y + windows[i].height >= primary.y + primary.height) {
this._obscuredByFullscreen = true;
break;
}
} else if (layer == Meta.StackLayer.FULLSCREEN) {
this._obscuredByFullscreen = true;
break;
} else
break;
}

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,25 @@ const Tweener = imports.ui.tweener;
const SNAP_BACK_ANIMATION_TIME = 0.25;
let eventHandlerActor = null;
let currentDraggable = null;
function _getEventHandlerActor() {
if (!eventHandlerActor) {
eventHandlerActor = new Clutter.Rectangle();
eventHandlerActor.width = 0;
eventHandlerActor.height = 0;
global.stage.add_actor(eventHandlerActor);
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer.
eventHandlerActor.connect('event',
function(actor, event) {
return currentDraggable._onEvent(actor, event);
});
}
return eventHandlerActor;
}
function _Draggable(actor, manualMode) {
this._init(actor, manualMode);
}
@ -18,7 +37,11 @@ _Draggable.prototype = {
if (!manualMode)
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this._haveSourceGrab = false;
this._onEventId = null;
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
},
_onButtonPress : function (actor, event) {
@ -27,8 +50,8 @@ _Draggable.prototype = {
if (Tweener.getTweenCount(actor))
return false;
this._haveSourceGrab = true;
this._grabActor(actor);
this._buttonDown = true;
this._grabActor();
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
@ -37,41 +60,69 @@ _Draggable.prototype = {
return false;
},
_grabActor : function (actor) {
Clutter.grab_pointer(actor);
// We intercept motion and button-release events so that when
// you release after dragging, the app doesn't see that and
// think you just clicked. We connect to 'event' rather than
// 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer.
this._onEventId = actor.connect('event',
Lang.bind(this, this._onEvent));
_grabActor: function() {
Clutter.grab_pointer(this.actor);
this._onEventId = this.actor.connect('event',
Lang.bind(this, this._onEvent));
},
_ungrabActor : function (actor) {
_ungrabActor: function() {
Clutter.ungrab_pointer();
actor.disconnect(this._onEventId);
this.actor.disconnect(this._onEventId);
this._onEventId = null;
},
_onEvent : function (actor, event) {
if (this._dragActor) {
if (actor != this._dragActor )
return false;
} else if (actor != this.actor)
return false;
_grabEvents: function() {
Clutter.grab_pointer(_getEventHandlerActor());
Clutter.grab_keyboard(_getEventHandlerActor());
},
if (event.type() == Clutter.EventType.BUTTON_RELEASE)
return this._onButtonRelease(actor, event);
else if (event.type() == Clutter.EventType.MOTION)
return this._onMotion(actor, event);
else
return false;
_ungrabEvents: function() {
Clutter.ungrab_pointer();
Clutter.ungrab_keyboard();
},
_onEvent: function(actor, event) {
// We intercept BUTTON_RELEASE event to know that the button was released in case we
// didn't start the drag, to drop the draggable in case the drag was in progress, and
// to complete the drag and ensure that whatever happens to be under the pointer does
// not get triggered if the drag was cancelled with Esc.
if (event.type() == Clutter.EventType.BUTTON_RELEASE) {
this._buttonDown = false;
if (this._dragInProgress) {
return this._dragActorDropped(event);
} else if (this._dragActor != null && !this._snapBackInProgress) {
// Drag must have been cancelled with Esc.
this._dragComplete();
return true;
} else {
// Drag has never started.
this._ungrabActor();
return false;
}
// We intercept MOTION event to figure out if the drag has started and to draw
// this._dragActor under the pointer when dragging is in progress
} else if (event.type() == Clutter.EventType.MOTION) {
if (this._dragInProgress) {
return this._updateDragPosition(event);
} else if (this._dragActor == null) {
return this._maybeStartDrag(event);
}
// We intercept KEY_PRESS event so that we can process Esc key press to cancel
// dragging and ignore all other key presses.
} else if (event.type() == Clutter.EventType.KEY_PRESS && this._dragInProgress) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
this._cancelDrag(event.get_time());
return true;
}
}
return false;
},
/**
* startDrag:
* @actor: Origin actor for drag and drop
* @stageX: X coordinate of event
* @stageY: Y coordinate of event
* @time: Event timestamp
@ -80,8 +131,14 @@ _Draggable.prototype = {
* This function is useful to call if you've specified manualMode
* for the draggable.
*/
startDrag: function (actor, stageX, stageY, time) {
startDrag: function (stageX, stageY, time) {
currentDraggable = this;
this._dragInProgress = true;
this.emit('drag-begin', time);
if (this._onEventId)
this._ungrabActor();
this._grabEvents();
this._dragStartX = stageX;
this._dragStartY = stageY;
@ -112,59 +169,59 @@ _Draggable.prototype = {
this._dragActorSource = this.actor;
}
this._dragOrigParent = undefined;
if (this._haveSourceGrab) {
this._haveSourceGrab = false;
this._ungrabActor(actor);
}
this._grabActor(this._dragActor);
this._dragOffsetX = this._dragActor.x - this._dragStartX;
this._dragOffsetY = this._dragActor.y - this._dragStartY;
} else {
this._dragActor = actor;
this._dragActor = this.actor;
this._dragActorSource = undefined;
this._dragOrigParent = actor.get_parent();
this._dragOrigParent = this.actor.get_parent();
this._dragOrigX = this._dragActor.x;
this._dragOrigY = this._dragActor.y;
this._dragOrigScale = this._dragActor.scale_x;
let [actorStageX, actorStageY] = actor.get_transformed_position();
let [actorStageX, actorStageY] = this.actor.get_transformed_position();
this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY;
// Set the actor's scale such that it will keep the same
// transformed size when it's reparented to the stage
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
actor.set_scale(scaledWidth / actor.width,
scaledHeight / actor.height);
let [scaledWidth, scaledHeight] = this.actor.get_transformed_size();
this.actor.set_scale(scaledWidth / this.actor.width,
scaledHeight / this.actor.height);
}
this._dragActor.reparent(actor.get_stage());
this._dragActor.reparent(this.actor.get_stage());
this._dragActor.raise_top();
},
_onMotion : function (actor, event) {
_maybeStartDrag: function(event) {
let [stageX, stageY] = event.get_coords();
// If we haven't begun a drag, see if the user has moved the
// mouse enough to trigger a drag
// See if the user has moved the mouse enough to trigger a drag
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
if (!this._dragActor &&
(Math.abs(stageX - this._dragStartX) > threshold ||
if ((Math.abs(stageX - this._dragStartX) > threshold ||
Math.abs(stageY - this._dragStartY) > threshold)) {
this.startDrag(actor, stageX, stageY, event.get_time());
this.startDrag(stageX, stageY, event.get_time());
this._updateDragPosition(event);
}
return true;
},
_updateDragPosition : function (event) {
let [stageX, stageY] = event.get_coords();
// If we are dragging, update the position
if (this._dragActor) {
this._dragActor.set_position(stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
// Because we want to find out what other actor is located at the current position of this._dragActor,
// we have to temporarily hide this._dragActor.
this._dragActor.hide();
let target = actor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
this._dragActor.hide();
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
this._dragActor.show();
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
@ -172,7 +229,7 @@ _Draggable.prototype = {
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
target._delegate.handleDragOver(this.actor._delegate, actor,
target._delegate.handleDragOver(this.actor._delegate, this._dragActor,
(stageX + this._dragOffsetX - targX) / target.scale_x,
(stageY + this._dragOffsetY - targY) / target.scale_y,
event.get_time());
@ -184,40 +241,42 @@ _Draggable.prototype = {
return true;
},
_onButtonRelease : function (actor, event) {
this._ungrabActor(actor);
let dragging = (actor == this._dragActor);
this._dragActor = undefined;
if (!dragging)
return false;
// Find a drop target
actor.hide();
_dragActorDropped: function(event) {
// Find a drop target. Because we want to find out what other actor is located at
// the current position of this._dragActor, we have to temporarily hide this._dragActor.
this._dragActor.hide();
let [dropX, dropY] = event.get_coords();
let target = actor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
dropX, dropY);
actor.show();
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
dropX, dropY);
this._dragActor.show();
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [targX, targY] = target.get_transformed_position();
if (target._delegate.acceptDrop(this.actor._delegate, actor,
if (target._delegate.acceptDrop(this.actor._delegate, this._dragActor,
(dropX - targX) / target.scale_x,
(dropY - targY) / target.scale_y,
event.get_time())) {
// If it accepted the drop without taking the actor,
// destroy it.
if (actor.get_parent() == actor.get_stage())
actor.destroy();
if (this._dragActor.get_parent() == this._dragActor.get_stage())
this._dragActor.destroy();
this._dragInProgress = false;
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
}
}
target = target.get_parent();
}
this._cancelDrag(event.get_time());
return true;
},
_cancelDrag: function(eventTime) {
this._dragInProgress = false;
// Snap back to the actor source if the source is still around, snap back
// to the original location if the actor itself was being dragged or the
// source is no longer around.
@ -227,17 +286,17 @@ _Draggable.prototype = {
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
}
this._snapBackInProgress = true;
// No target, so snap back
Tweener.addTween(actor,
Tweener.addTween(this._dragActor,
{ x: snapBackX,
y: snapBackY,
time: SNAP_BACK_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onSnapBackComplete,
onCompleteScope: this,
onCompleteParams: [actor, event.get_time()]
onCompleteParams: [this._dragActor, eventTime]
});
return true;
},
_onSnapBackComplete : function (dragActor, eventTime) {
@ -249,6 +308,16 @@ _Draggable.prototype = {
dragActor.destroy();
}
this.emit('drag-end', eventTime, false);
this._snapBackInProgress = false;
if (!this._buttonDown)
this._dragComplete();
},
_dragComplete: function() {
this._dragActor = undefined;
currentDraggable = null;
this._ungrabEvents();
}
};

View File

@ -8,13 +8,18 @@ const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const DocInfo = imports.misc.docInfo;
const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Search = imports.ui.search;
const MAX_DASH_DOCS = 50;
const DASH_DOCS_ICON_SIZE = 16;
const DEFAULT_SPACING = 4;
@ -111,19 +116,19 @@ DocDisplayItem.prototype = {
/* This class represents a display containing a collection of document items.
* The documents are sorted by how recently they were last visited.
*/
function DocDisplay() {
this._init();
function DocDisplay(flags) {
this._init(flags);
}
DocDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function() {
GenericDisplay.GenericDisplay.prototype._init.call(this);
_init : function(flags) {
GenericDisplay.GenericDisplay.prototype._init.call(this, flags);
// We keep a single timeout callback for updating last visited times
// for all the items in the display. This avoids creating individual
// callbacks for each item in the display. So proper time updates
// for individual items and item details depend on the item being
// for individual items and item details depend on the item being
// associated with one of the displays.
this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
@ -136,7 +141,7 @@ DocDisplay.prototype = {
// but redisplaying right away is cool when we use Zephyr.
// Also, we might be displaying remote documents, like Google Docs, in the future
// which might be edited by someone else.
this._redisplay(false);
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
}));
this.connect('destroy', Lang.bind(this, function (o) {
@ -150,9 +155,11 @@ DocDisplay.prototype = {
// Gets the list of recent items from the recent items manager.
_refreshCache : function() {
if (!this._docsStale)
return;
this._allItems = this._docManager.getItems();
return true;
this._allItems = {};
Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
this._docsStale = false;
return false;
},
// Sets the list of the displayed items based on how recently they were last visited.
@ -171,21 +178,19 @@ DocDisplay.prototype = {
// them once when they are returned by this._recentManager.get_items() to avoid having to do
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
// to introduce an additional class variable.
this._matchedItems = [];
this._matchedItems = {};
this._matchedItemKeys = [];
let docIdsToRemove = [];
for (docId in this._allItems) {
// this._allItems[docId].exists() checks if the resource still exists
if (this._allItems[docId].exists())
this._matchedItems.push(docId);
else
docIdsToRemove.push(docId);
this._matchedItems[docId] = 1;
this._matchedItemKeys.push(docId);
}
for (docId in docIdsToRemove) {
delete this._allItems[docId];
}
this._matchedItems.sort(Lang.bind(this, function (a,b) { return this._compareItems(a,b); }));
this._matchedItemKeys.sort(Lang.bind(this, this._compareItems));
},
// Compares items associated with the item ids based on how recently the items
@ -270,18 +275,21 @@ DashDocDisplayItem.prototype = {
Main.overview.hide();
}));
this.actor._delegate = this;
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
let name = new Clutter.Text({ font_name: "Sans 14px",
color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
ellipsize: Pango.EllipsizeMode.END,
text: docInfo.name });
let name = new St.Label({ style_class: 'dash-recent-docs-item',
text: docInfo.name });
this.actor.append(name, Big.BoxPackFlags.EXPAND);
let draggable = DND.makeDraggable(this.actor);
this.actor._delegate = this;
},
getUri: function() {
return this._info.uri;
},
getDragActorSource: function() {
@ -298,7 +306,7 @@ DashDocDisplayItem.prototype = {
shellWorkspaceLaunch: function () {
this._info.launch();
}
}
};
/**
* Class used to display two column recent documents in the dash
@ -313,12 +321,14 @@ DashDocDisplay.prototype = {
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
this._actorsByUri = {};
this._docManager = DocInfo.getDocManager();
this._docManager.connect('changed', Lang.bind(this, function(mgr) {
this._redisplay();
}));
this._redisplay();
this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
this._pendingDocsChange = true;
this._checkDocExistence = false;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
@ -347,90 +357,161 @@ DashDocDisplay.prototype = {
_getPreferredHeight: function(actor, forWidth, alloc) {
let children = actor.get_children();
// Two columns, where we go vertically down first. So just take
// the height of half of the children as our preferred height.
// The width of an item is our allocated width, minus spacing, divided in half.
this._itemWidth = Math.floor((forWidth - DEFAULT_SPACING) / 2);
let firstColumnChildren = children.length / 2;
alloc.min_size = 0;
for (let i = 0; i < firstColumnChildren; i++) {
let maxNatural = 0;
for (let i = 0; i < children.length; i++) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(forWidth);
alloc.natural_size += naturalSize;
if (i > 0 && i < children.length - 1) {
alloc.min_size += DEFAULT_SPACING;
alloc.natural_size += DEFAULT_SPACING;
}
let [minSize, naturalSize] = child.get_preferred_height(this._itemWidth);
maxNatural = Math.max(maxNatural, naturalSize);
}
this._itemHeight = maxNatural;
let firstColumnChildren = Math.ceil(children.length / 2);
alloc.natural_size = (firstColumnChildren * maxNatural +
(firstColumnChildren - 1) * DEFAULT_SPACING);
},
_allocate: function(actor, box, flags) {
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
// Make sure this._itemWidth/Height have been computed, even
// if the parent actor didn't check our size before allocating.
// (Not clear if that is required or not as a Clutter
// invariant; this is safe and cheap because of caching.)
actor.get_preferred_height(width);
let children = actor.get_children();
// The width of an item is our allocated width, minus spacing, divided in half.
let itemWidth = Math.floor((width - DEFAULT_SPACING) / 2);
let x = box.x1;
let y = box.y1;
let x = 0;
let y = 0;
let columnIndex = 0;
let i = 0;
// Loop over the children, going vertically down first. When we run
// out of vertical space (our y variable is bigger than box.y2), switch
// to the second column.
for (; i < children.length; i++) {
while (i < children.length) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(-1);
if (y + naturalSize > box.y2) {
// Is this the second column? Ok, break.
if (columnIndex == 1) {
if (y + this._itemHeight > box.y2) {
// Is this the second column, or we're in
// the first column and can't even fit one
// item? In that case, break.
if (columnIndex == 1 || i == 0) {
break;
}
// Set x to the halfway point.
columnIndex += 1;
x = x + itemWidth + DEFAULT_SPACING;
x = x + this._itemWidth + DEFAULT_SPACING;
// And y is back to the top.
y = box.y1;
y = 0;
// Retry this same item, now that we're in the second column.
// By looping back to the top here, we re-test the size
// again for the second column.
continue;
}
let childBox = new Clutter.ActorBox();
childBox.x1 = x;
childBox.y1 = y;
childBox.x2 = childBox.x1 + itemWidth;
childBox.y2 = y + naturalSize;
childBox.x2 = childBox.x1 + this._itemWidth;
childBox.y2 = y + this._itemHeight;
y = childBox.y2 + DEFAULT_SPACING;
child.show();
child.allocate(childBox, flags);
this.actor.set_skip_paint(child, false);
i++;
}
// Everything else didn't fit, just hide it.
for (; i < children.length; i++) {
children[i].hide();
if (this._checkDocExistence) {
// Now we know how many docs we are displaying, queue a check to see if any of them
// have been deleted. If they are deleted, then we'll get a 'changed' signal; since
// we'll now be displaying items we weren't previously, we'll check again to see
// if they were deleted, and so forth and so on.
// TODO: We should change this to ask for as many as we can fit in the given space:
// https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
this._docManager.queueExistenceCheck(i);
this._checkDocExistence = false;
}
for (; i < children.length; i++)
this.actor.set_skip_paint(children[i], true);
},
_onDocsChanged: function() {
this._checkDocExistence = true;
Main.queueDeferredWork(this._workId);
},
_redisplay: function() {
// Should be kept alive by the _actorsByUri
this.actor.remove_all();
let docs = this._docManager.getItems();
let docUrls = [];
for (let url in docs) {
docUrls.push(url);
let docs = this._docManager.getTimestampOrderedInfos();
for (let i = 0; i < docs.length && i < MAX_DASH_DOCS; i++) {
let doc = docs[i];
let display = this._actorsByUri[doc.uri];
if (display) {
this.actor.add_actor(display.actor);
} else {
let display = new DashDocDisplayItem(doc);
this.actor.add_actor(display.actor);
this._actorsByUri[doc.uri] = display;
}
}
docUrls.sort(function (urlA, urlB) { return docs[urlB].timestamp - docs[urlA].timestamp; });
let textureCache = Shell.TextureCache.get_default();
for (let i = 0; i < docUrls.length; i++) {
let url = docUrls[i];
let docInfo = docs[url];
let display = new DashDocDisplayItem(docInfo);
this.actor.add_actor(display.actor);
// Any unparented actors must have been deleted
for (let uri in this._actorsByUri) {
let display = this._actorsByUri[uri];
if (display.actor.get_parent() == null) {
display.actor.destroy();
delete this._actorsByUri[uri];
}
}
this.emit('changed');
}
};
Signals.addSignalMethods(DashDocDisplay.prototype);
function DocSearchProvider() {
this._init();
}
DocSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function(name) {
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
this._docManager = DocInfo.getDocManager();
},
getResultMeta: function(resultId) {
let docInfo = this._docManager.lookupByUri(resultId);
if (!docInfo)
return null;
return { 'id': resultId,
'name': docInfo.name,
'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)};
},
activateResult: function(id) {
let docInfo = this._docManager.lookupByUri(id);
docInfo.launch();
},
getInitialResultSet: function(terms) {
return this._docManager.initialSearch(terms);
},
getSubsearchResultSet: function(previousResults, terms) {
return this._docManager.subsearch(previousResults, terms);
},
expandSearch: function(terms) {
log("TODO expand docs search");
}
};

42
js/ui/environment.js Normal file
View File

@ -0,0 +1,42 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const St = imports.gi.St;
const Gettext_gtk20 = imports.gettext.domain('gtk20');
const Tweener = imports.ui.tweener;
const Format = imports.misc.format;
// "monkey patch" in some varargs ClutterContainer methods; we need
// to do this per-container class since there is no representation
// of interfaces in Javascript
function _patchContainerClass(containerClass) {
// This one is a straightforward mapping of the C method
containerClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor);
for (prop in props)
meta[prop] = props[prop];
};
// clutter_container_add() actually is a an add-many-actors
// method. We conveniently, but somewhat dubiously, take the
// this opportunity to make it do something more useful.
containerClass.prototype.add = function(actor, props) {
this.add_actor(actor);
if (props)
this.child_set(actor, props);
};
}
_patchContainerClass(St.BoxLayout);
_patchContainerClass(St.Table);
function init() {
Tweener.init();
String.prototype.format = Format.format;
// Set the default direction for St widgets (this needs to be done before any use of St)
if (Gettext_gtk20.gettext("default:LTR") == "default:RTL") {
St.Widget.set_default_direction(St.TextDirection.RTL);
}
}

158
js/ui/extensionSystem.js Normal file
View File

@ -0,0 +1,158 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4
};
const ExtensionType = {
SYSTEM: 1,
PER_USER: 2
};
// Maps uuid -> metadata object
const extensionMeta = {};
// Maps uuid -> importer object (extension directory tree)
const extensions = {};
// Array of uuids
var disabledExtensions;
// GFile for user extensions
var userExtensionsDir = null;
function loadExtension(dir, enabled, type) {
let info;
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
global.logError(baseErrorString + 'Missing metadata.json');
return;
}
let [success, metadataContents, len, etag] = metadataFile.load_contents(null);
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
return;
}
let requiredProperties = ['uuid', 'name', 'description'];
for (let i = 0; i < requiredProperties; i++) {
let prop = requiredProperties[i];
if (!meta[prop]) {
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
return;
}
}
// Encourage people to add this
if (!meta['url']) {
global.log(baseErrorString + 'Warning: Missing "url" property in metadata.json');
}
let base = dir.get_basename();
if (base != meta.uuid) {
global.logError(baseErrorString + 'uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + base + '"');
return;
}
extensionMeta[meta.uuid] = meta;
extensionMeta[meta.uuid].type = type;
extensionMeta[meta.uuid].path = dir.get_path();
if (!enabled) {
extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
return;
}
// Default to error, we set success as the last step
extensionMeta[meta.uuid].state = ExtensionState.ERROR;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
global.logError(baseErrorString + 'Missing extension.js');
return;
}
let stylesheetPath = null;
let themeContext = St.ThemeContext.get_for_stage(global.stage);
let theme = themeContext.get_theme();
let stylesheetFile = dir.get_child('stylesheet.css');
if (stylesheetFile.query_exists(null)) {
try {
theme.load_stylesheet(stylesheetFile.get_path());
} catch (e) {
global.logError(baseErrorString + 'Stylesheet parse error: ' + e);
return;
}
}
let extensionModule;
try {
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
extensionModule = extensions[meta.uuid].extension;
} catch (e) {
if (stylesheetPath != null)
theme.unload_stylesheet(stylesheetPath);
global.logError(baseErrorString + e);
return;
}
if (!extensionModule.main) {
global.logError(baseErrorString + 'missing \'main\' function');
return;
}
try {
extensionModule.main();
} catch (e) {
if (stylesheetPath != null)
theme.unload_stylesheet(stylesheetPath);
global.logError(baseErrorString + 'Failed to evaluate main function:' + e);
return;
}
extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
global.log('Loaded extension ' + meta.uuid);
}
function init() {
let userConfigPath = GLib.get_user_config_dir();
let userExtensionsPath = GLib.build_filenamev([userConfigPath, 'gnome-shell', 'extensions']);
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
try {
userExtensionsDir.make_directory_with_parents(null);
} catch (e) {
global.logError(""+e);
}
disabledExtensions = Shell.GConf.get_default().get_string_list('disabled_extensions');
}
function _loadExtensionsIn(dir, type) {
let fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
let file, info;
while ((info = fileEnum.next_file(null)) != null) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
continue;
let name = info.get_name();
let enabled = disabledExtensions.indexOf(name) < 0;
let child = dir.get_child(name);
loadExtension(child, enabled, type);
}
fileEnum.close(null);
}
function loadExtensions() {
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
let systemDataDirs = GLib.get_system_data_dirs();
for (let i = 0; i < systemDataDirs.length; i++) {
let dirPath = systemDataDirs[i] + '/gnome-shell/extensions';
let dir = Gio.file_new_for_path(dirPath);
if (dir.query_exists(null))
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
}
}

View File

@ -11,20 +11,18 @@ const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Button = imports.ui.button;
const DND = imports.ui.dnd;
const Link = imports.ui.link;
const Main = imports.ui.main;
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
const RedisplayFlags = { NONE: 0,
FULL: 1 << 1,
SUBSEARCH: 1 << 2,
IMMEDIATE: 1 << 3 };
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb);
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color();
ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x4f6fadaa);
const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color();
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color();
@ -32,10 +30,7 @@ PREVIEW_BOX_BACKGROUND_COLOR.from_pixel(0xADADADf0);
const DEFAULT_PADDING = 4;
const ITEM_DISPLAY_HEIGHT = 50;
const ITEM_DISPLAY_ICON_SIZE = 48;
const ITEM_DISPLAY_PADDING = 1;
const ITEM_DISPLAY_PADDING_RIGHT = 2;
const DEFAULT_COLUMN_GAP = 6;
const PREVIEW_ICON_SIZE = 96;
@ -46,8 +41,6 @@ const PREVIEW_BOX_CORNER_RADIUS = 10;
const PREVIEW_PLACING = 3/4;
const PREVIEW_DETAILS_MIN_WIDTH = PREVIEW_ICON_SIZE * 2;
const INFORMATION_BUTTON_SIZE = 16;
/* This is a virtual class that represents a single display item containing
* a name, a description, and an icon. It allows selecting an item and represents
* it by highlighting it with a different background color than the default.
@ -58,12 +51,8 @@ function GenericDisplayItem() {
GenericDisplayItem.prototype = {
_init: function() {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: ITEM_DISPLAY_PADDING,
reactive: true,
background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
corner_radius: 4,
height: ITEM_DISPLAY_HEIGHT });
this.actor = new St.BoxLayout({ style_class: "generic-display-item",
reactive: true });
this.actor._delegate = this;
this.actor.connect('button-release-event',
@ -75,52 +64,20 @@ GenericDisplayItem.prototype = {
}));
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
this._infoContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_PADDING });
this.actor.append(this._infoContent, Big.BoxPackFlags.EXPAND);
this._iconBin = new St.Bin();
this.actor.add(this._iconBin);
this._iconBox = new Big.Box();
this._infoContent.append(this._iconBox, Big.BoxPackFlags.NONE);
this._infoText = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: DEFAULT_PADDING });
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
let infoIconUri = "file://" + global.imagedir + "info.svg";
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
infoIconUri,
INFORMATION_BUTTON_SIZE,
INFORMATION_BUTTON_SIZE);
this._informationButton = new Button.iconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
let buttonBox = new Big.Box({ width: INFORMATION_BUTTON_SIZE + 2 * DEFAULT_PADDING,
height: INFORMATION_BUTTON_SIZE,
padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING,
y_align: Big.BoxAlignment.CENTER });
buttonBox.append(this._informationButton.actor, Big.BoxPackFlags.NONE);
this.actor.append(buttonBox, Big.BoxPackFlags.END);
// Connecting to the button-press-event for the information button ensures that the actor,
// which is a draggable actor, does not get the button-press-event and doesn't initiate
// the dragging, which then prevents us from getting the button-release-event for the button.
this._informationButton.actor.connect('button-press-event',
Lang.bind(this,
function() {
return true;
}));
this._informationButton.actor.connect('button-release-event',
Lang.bind(this,
function() {
// Selects the item by highlighting it and displaying its details
this.emit('show-details');
return true;
}));
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
vertical: true });
this.actor.add(this._infoText, { expand: true, y_fill: false });
this._name = null;
this._description = null;
this._icon = null;
this._initialLoadComplete = false;
// An array of details description actors that we create over time for the item.
// It is used for updating the description text inside the details actor when
// the description text for the item is updated.
@ -145,24 +102,10 @@ GenericDisplayItem.prototype = {
//// Public methods ////
// Shows the information button when the item was drawn under the mouse pointer.
onDrawnUnderPointer: function() {
this._informationButton.show();
},
// Highlights the item by setting a different background color than the default
// if isSelected is true, removes the highlighting otherwise.
markSelected: function(isSelected) {
let color;
if (isSelected) {
color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR;
this._informationButton.forceShow(true);
}
else {
color = ITEM_DISPLAY_BACKGROUND_COLOR;
this._informationButton.forceShow(false);
}
this.actor.background_color = color;
this.actor.set_style_pseudo_class(isSelected ? "selected" : null);
},
/*
@ -178,19 +121,14 @@ GenericDisplayItem.prototype = {
spacing: PREVIEW_BOX_SPACING });
// Inner box with name and description
let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PREVIEW_BOX_SPACING });
let detailsName = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans bold 14px",
line_wrap: true,
text: this._name.text });
textDetails.append(detailsName, Big.BoxPackFlags.NONE);
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
vertical: true });
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
text: this._name.text });
textDetails.add(detailsName);
let detailsDescription = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans 14px",
line_wrap: true,
text: this._description.text });
textDetails.append(detailsDescription, Big.BoxPackFlags.NONE);
let detailsDescription = new St.Label({ text: this._description.text });
textDetails.add(detailsDescription);
this._detailsDescriptions.push(detailsDescription);
@ -216,7 +154,7 @@ GenericDisplayItem.prototype = {
// Destroys the item.
destroy: function() {
this.actor.destroy();
this.actor.destroy();
},
//// Pure virtual public methods ////
@ -253,20 +191,15 @@ GenericDisplayItem.prototype = {
}
this._icon = this._createIcon();
this._iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this._iconBin.set_child(this._icon);
this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans 14px",
ellipsize: Pango.EllipsizeMode.END,
text: nameText });
this._infoText.append(this._name, Big.BoxPackFlags.EXPAND);
this._name = new St.Label({ style_class: "generic-display-item-name",
text: nameText });
this._infoText.add(this._name);
this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
font_name: "Sans 12px",
ellipsize: Pango.EllipsizeMode.END,
text: descriptionText ? descriptionText : ""
});
this._infoText.append(this._description, Big.BoxPackFlags.EXPAND);
this._description = new St.Label({ style_class: "generic-display-item-description",
text: descriptionText ? descriptionText : "" });
this._infoText.add(this._description);
},
// Sets the description text for the item, including the description text
@ -298,67 +231,76 @@ GenericDisplayItem.prototype = {
// Returns a preview icon for the item.
_createPreviewIcon: function() {
throw new Error("Not implemented");
},
}
//// Private methods ////
// Hides the information button once the item starts being dragged.
_onDragBegin : function (draggable, time) {
// For some reason, we are not getting leave-event signal when we are dragging an item,
// so we should remove the link manually.
this._informationButton.actor.hide();
}
};
Signals.addSignalMethods(GenericDisplayItem.prototype);
const GenericDisplayFlags = {
DISABLE_VSCROLLING: 1 << 0
}
/* This is a virtual class that represents a display containing a collection of items
* that can be filtered with a search string.
*/
function GenericDisplay() {
this._init();
function GenericDisplay(flags) {
this._init(flags);
}
GenericDisplay.prototype = {
_init : function() {
_init : function(flags) {
let disableVScrolling = (flags & GenericDisplayFlags.DISABLE_VSCROLLING) != 0;
this._search = '';
this._expanded = false;
this._maxItemsPerPage = null;
this._list = new Shell.OverflowList({ spacing: 6.0,
item_height: ITEM_DISPLAY_HEIGHT });
if (disableVScrolling) {
this.actor = this._list = new Shell.OverflowList({ spacing: 6,
item_height: 50 });
} else {
this.actor = new St.ScrollView({ x_fill: true, y_fill: true });
this.actor.get_hscroll_bar().hide();
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
vertical: true });
this.actor.add_actor(this._list);
}
this._list.connect('notify::n-pages', Lang.bind(this, function () {
this._updateDisplayControl(true);
}));
this._list.connect('notify::page', Lang.bind(this, function () {
this._updateDisplayControl(false);
}));
this._pendingRedisplay = RedisplayFlags.NONE;
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
// map<itemId, Object> where Object represents the item info
this._allItems = {};
// an array of itemIds of items that match the current request
// in the order in which the items should be displayed
this._matchedItems = [];
// set<itemId>
this._matchedItems = {};
// sorted array of items matched by search
this._matchedItemKeys = [];
// map<itemId, GenericDisplayItem>
this._displayedItems = {};
this._openDetailIndex = -1;
this._selectedIndex = -1;
// These two are public - .actor is the normal "actor subclass" property,
// but we also expose a .displayControl actor which is separate.
// See also getNavigationArea.
this.actor = this._list;
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
spacing: 12,
orientation: Big.BoxOrientation.HORIZONTAL});
},
//// Public methods ////
// Sets the search string and displays the matching items.
setSearch: function(text) {
this._search = text.toLowerCase();
this._redisplay(true);
let lowertext = text.toLowerCase();
if (lowertext == this._search) {
return;
}
let flags = RedisplayFlags.IMMEDIATE;
if (this._search != '') {
// Because we combine search terms with OR, we have to be sure that no new term
// was introduced before deciding that the new search results will be a subset of
// the existing search results.
if (lowertext.indexOf(this._search) == 0 &&
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
flags |= RedisplayFlags.SUBSEARCH;
}
}
this._search = lowertext;
this._redisplay(flags);
},
// Launches the item that is currently selected, closing the Overview
@ -375,7 +317,7 @@ GenericDisplay.prototype = {
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
// around to the bottom.
selectUp: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
let selectedUp = true;
let prev = this._selectedIndex - 1;
if (this._selectedIndex <= 0) {
@ -390,7 +332,7 @@ GenericDisplay.prototype = {
// to the top one. Returns true if the selection actually moved down, false if it wrapped
// around to the top.
selectDown: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
let selectedDown = true;
let next = this._selectedIndex + 1;
if (this._selectedIndex == count - 1) {
@ -409,7 +351,7 @@ GenericDisplay.prototype = {
// Selects the last item among the displayed items.
selectLastItem: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
if (this.hasItems())
this._selectIndex(count - 1);
},
@ -430,22 +372,24 @@ GenericDisplay.prototype = {
// positive number when this._mathedItems.length is 0
// This can be triggered if a search string is entered for which there are no matches.
// log("this._mathedItems.length: " + this._matchedItems.length + " this._list.displayedCount " + this._list.displayedCount);
return this._matchedItems.length > 0;
return this._matchedItemKeys.length > 0;
},
getMatchedItemsCount: function() {
return this._matchedItems.length;
return this._matchedItemKeys.length;
},
// Load the initial state
load: function() {
this._redisplay(true);
this._redisplay(RedisplayFlags.FULL);
},
// Should be called when the display is closed
resetState: function() {
this._filterReset();
this._openDetailIndex = -1;
if (!(this.actor instanceof Shell.OverflowList))
this.actor.get_vscroll_bar().get_adjustment().value = 0;
},
// Returns an actor which acts as a sidebar; this is used for
@ -459,63 +403,18 @@ GenericDisplay.prototype = {
return item.createDetailsActor();
},
// Displays the page specified by the pageNumber argument.
displayPage: function(pageNumber) {
// Cleanup from the previous selection, but don't unset this._selectedIndex
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}
this._list.page = pageNumber;
},
//// Protected methods ////
/*
* Displays items that match the current request and should show up on the current page.
* Updates the display control to reflect the matched items set and the page selected.
*
* resetDisplayControl - indicates if the display control should be re-created because
* the results or the space allocated for them changed. If it's false,
* the existing display control is used and only the page links are
* updated to reflect the current page selection.
*/
_displayMatchedItems: function(resetDisplayControl) {
// When generating a new list to display, we first remove all the old
// displayed items which will unset the selection. So we need
// to keep a flag which indicates if this display had the selection.
let hadSelected = this.hasSelected();
_recreateDisplayItems: function() {
this._removeAllDisplayItems();
for (let i = 0; i < this._matchedItems.length; i++) {
this._addDisplayItem(this._matchedItems[i]);
this._setDefaultList();
for (let itemId in this._allItems) {
this._addDisplayItem(itemId);
}
if (hadSelected) {
this._selectedIndex = -1;
this.selectFirstItem();
}
// Check if the pointer is over one of the items and display the information button if it is.
// We want to do this between finishing our changes to the display and the point where
// the display is redrawn.
Mainloop.idle_add(Lang.bind(this,
function() {
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor);
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}),
Meta.PRIORITY_BEFORE_REDRAW);
},
// Creates a display item based on the information associated with itemId
// and adds it to the displayed items.
// Creates a display item based on the information associated with itemId
// and adds it to the list of displayed items, but does not yet display it.
_addDisplayItem : function(itemId) {
if (this._displayedItems.hasOwnProperty(itemId)) {
log("Tried adding a display item for " + itemId + ", but an item with this item id is already among displayed items.");
@ -529,14 +428,14 @@ GenericDisplay.prototype = {
Lang.bind(this,
function() {
// update the selection
this._selectIndex(this._list.get_actor_index(displayItem.actor));
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
this.activateSelected();
}));
displayItem.connect('show-details',
Lang.bind(this,
function() {
let index = this._list.get_actor_index(displayItem.actor);
let index = this._list.get_children().indexOf(displayItem.actor);
/* Close the details pane if already open */
if (index == this._openDetailIndex) {
this._openDetailIndex = -1;
@ -546,15 +445,15 @@ GenericDisplay.prototype = {
this.emit('show-details', index);
}
}));
this._list.add_actor(displayItem.actor);
this._displayedItems[itemId] = displayItem;
},
// Removes an item identifed by the itemId from the displayed items.
_removeDisplayItem: function(itemId) {
let count = this._list.displayedCount;
let children = this._list.get_children();
let count = children.length;
let displayItem = this._displayedItems[itemId];
let displayItemIndex = this._list.get_actor_index(displayItem.actor);
let displayItemIndex = children.indexOf(displayItem.actor);
if (this.hasSelected() && count == 1) {
this.unsetSelected();
@ -585,33 +484,120 @@ GenericDisplay.prototype = {
this.unsetSelected();
},
_compareSearchMatch: function(a, b) {
let countA = this._matchedItems[a];
let countB = this._matchedItems[b];
if (countA > countB)
return -1;
else if (countA < countB)
return 1;
else
return this._compareItems(a, b);
},
_setMatches: function(matches) {
this._matchedItems = matches;
this._matchedItemKeys = [];
for (let itemId in this._matchedItems) {
this._matchedItemKeys.push(itemId);
}
this._matchedItemKeys.sort(Lang.bind(this, this._compareSearchMatch));
},
/**
* _redisplaySubSearch:
* A somewhat more optimized function called when we know
* that we're going to be displaying a subset of the items
* we already had, in the same order. In that case, we can
* just hide the actors that shouldn't be shown.
*/
_redisplaySubSearch: function() {
let matches = this._getSearchMatchedItems(true);
// Just hide all from the old set,
// we'll show the ones we want below
for (let itemId in this._displayedItems) {
let item = this._displayedItems[itemId];
item.actor.hide();
}
this._setMatches(matches);
for (let itemId in matches) {
let item = this._displayedItems[itemId];
item.actor.show();
}
this._list.queue_relayout();
},
_redisplayReordering: function() {
if (!this._filterActive()) {
this._setDefaultList();
} else {
this._setMatches(this._getSearchMatchedItems(false));
}
this._list.remove_all();
for (let i = 0; i < this._matchedItemKeys.length; i++) {
let itemId = this._matchedItemKeys[i];
let item = this._displayedItems[itemId];
item.actor.show();
this._list.add_actor(item.actor);
}
},
/*
* Updates the displayed items, applying the search string if one exists.
*
* resetPage - indicates if the page selection should be reset when displaying the matching results.
* We reset the page selection when the change in results was initiated by the user by
* entering a different search criteria or by viewing the results list in a different
* size mode, but we keep the page selection the same if the results got updated on
* their own while the user was browsing through the result pages.
* @flags: Flags controlling redisplay behavior as follows:
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
* one, which implies we only need to re-search through previous results.
* FULL - Indicates that we need recreate all displayed items.
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
* if you want to get the number of matched items and show/hide a section based on
* that number.
*/
_redisplay: function(resetPage) {
this._refreshCache();
if (!this._filterActive())
this._setDefaultList();
else
this._doSearchFilter();
_redisplay: function(flags) {
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
if (!immediate && !this.actor.mapped) {
this._pendingRedisplay |= flags;
return;
}
if (resetPage)
this._list.page = 0;
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
let fullReload = (flags & RedisplayFlags.FULL) != 0;
this._displayMatchedItems(true);
let hadSelected = this.hasSelected();
this.unsetSelected();
if (!this._initialLoadComplete)
fullReload = true;
if (!this._refreshCache())
fullReload = true;
if (fullReload) {
this._recreateDisplayItems();
this._initialLoadComplete = true;
}
if (isSubSearch) {
this._redisplaySubSearch();
} else {
this._redisplayReordering();
}
if (hadSelected) {
this._selectedIndex = -1;
this.selectFirstItem();
}
this.emit('redisplayed');
},
//// Pure virtual protected methods ////
// Performs the steps needed to have the latest information about the items.
// Implementation should return %true if we are up to date, and %false
// if a full reload occurred.
_refreshCache: function() {
throw new Error("Not implemented");
},
@ -622,10 +608,10 @@ GenericDisplay.prototype = {
throw new Error("Not implemented");
},
// Compares items associated with the item ids based on the order in which the
// items should be displayed.
// Intended to be used as a compareFunction for array.sort().
// Returns an integer value indicating the result of the comparison.
// Compares items associated with the item ids based on the order in which the
// items should be displayed.
// Intended to be used as a compareFunction for array.sort().
// Returns an integer value indicating the result of the comparison.
_compareItems: function(itemIdA, itemIdB) {
throw new Error("Not implemented");
},
@ -643,111 +629,50 @@ GenericDisplay.prototype = {
//// Private methods ////
_getSearchMatchedItems: function() {
let matchedItemsForSearch = {};
_getItemSearchScore: function(itemId, terms) {
let item = this._allItems[itemId];
let score = 0;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
if (this._isInfoMatching(item, term)) {
score++;
}
}
return score;
},
_getSearchMatchedItems: function(isSubSearch) {
// Break the search up into terms, and search for each
// individual term. Keep track of the number of terms
// each item matched.
let terms = this._search.split(/\s+/);
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
for (itemId in this._allItems) {
let item = this._allItems[itemId];
if (this._isInfoMatching(item, term)) {
let count = matchedItemsForSearch[itemId];
if (!count)
count = 0;
count += 1;
matchedItemsForSearch[itemId] = count;
}
}
}
return matchedItemsForSearch;
},
let matchScores = {};
// Applies the search string to the list of items to find matches,
// and displays the matching items.
_doSearchFilter: function() {
let matchedItemsForSearch;
if (this._filterActive()) {
matchedItemsForSearch = this._getSearchMatchedItems();
} else {
matchedItemsForSearch = {};
for (let itemId in this._allItems) {
matchedItemsForSearch[itemId] = 1;
}
}
this._matchedItems = [];
for (itemId in matchedItemsForSearch) {
this._matchedItems.push(itemId);
}
this._matchedItems.sort(Lang.bind(this, function (a, b) {
let countA = matchedItemsForSearch[a];
let countB = matchedItemsForSearch[b];
if (countA > countB)
return -1;
else if (countA < countB)
return 1;
else
return this._compareItems(a, b);
}));
},
/*
* Updates the display control to reflect the matched items set and the page selected.
*
* resetDisplayControl - indicates if the display control should be re-created because
* the results or the space allocated for them changed. If it's false,
* the existing display control is used and only the page links are
* updated to reflect the current page selection.
*/
_updateDisplayControl: function(resetDisplayControl) {
if (resetDisplayControl) {
this.displayControl.remove_all();
let nPages = this._list.n_pages;
// Don't show the page indicator if there is only one page.
if (nPages == 1)
return;
let pageNumber = this._list.page;
for (let i = 0; i < nPages; i++) {
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
font_name: "Sans Bold 16px",
text: (i+1) + "",
reactive: (i == pageNumber) ? false : true});
this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE);
// we use pageNumberLocalScope to get the page number right in the callback function
let pageNumberLocalScope = i;
pageControl.connect('clicked',
Lang.bind(this,
function(o, event) {
this.displayPage(pageNumberLocalScope);
}));
if (isSubSearch) {
for (let i = 0; i < this._matchedItemKeys.length; i++) {
let itemId = this._matchedItemKeys[i];
let score = this._getItemSearchScore(itemId, terms);
if (score > 0)
matchScores[itemId] = score;
}
} else {
let pageControlActors = this.displayControl.get_children();
for (let i = 0; i < pageControlActors.length; i++) {
let pageControlActor = pageControlActors[i];
if (i == this._list.page) {
pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR;
pageControlActor.reactive = false;
} else {
pageControlActor.color = ITEM_DISPLAY_DESCRIPTION_COLOR;
pageControlActor.reactive = true;
}
}
}
if (this.hasSelected()) {
this.selectFirstItem();
for (let itemId in this._displayedItems) {
let score = this._getItemSearchScore(itemId, terms);
if (score > 0)
matchScores[itemId] = score;
}
}
return matchScores;
},
// Returns a display item based on its index in the ordering of the
// display children.
_findDisplayedByIndex: function(index) {
let actor = this._list.get_displayed_actor(index);
let actor;
if (this.actor instanceof Shell.OverflowList)
actor = this.actor.get_displayed_actor(index);
else
actor = this._list.get_children()[index];
return this._findDisplayedByActor(actor);
},
@ -779,6 +704,20 @@ GenericDisplay.prototype = {
let item = this._findDisplayedByIndex(index);
item.markSelected(true);
this.emit('selected');
},
_getVisibleCount: function() {
if (this.actor instanceof Shell.OverflowList)
return this._list.displayed_count;
return this._list.get_n_children();
},
_onMappedNotify: function () {
let mapped = this.actor.mapped;
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
this._redisplay(this._pendingRedisplay);
this._pendingRedisplay = RedisplayFlags.NONE;
}
};

158
js/ui/lightbox.js Normal file
View File

@ -0,0 +1,158 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const SHADE_COLOR = new Clutter.Color();
SHADE_COLOR.from_pixel(0x00000044);
/**
* Lightbox:
* @container: parent Clutter.Container
* @inhibitEvents: whether to inhibit events for @container
* @width: (optional) shade actor width
* @height: (optional) shade actor height
*
* Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors
* in @container to highlight by bringing them above the shade. It
* tracks added and removed actors in @container while the lightboxing
* is active, and ensures that all actors are returned to their
* original stacking order when the lightboxing is removed. (However,
* if actors are restacked by outside code while the lightboxing is
* active, the lightbox may later revert them back to their original
* order.)
*
* By default, the shade window will have the height and width of
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height
*/
function Lightbox(container, inhibitEvents, width, height) {
this._init(container, inhibitEvents, width, height);
}
Lightbox.prototype = {
_init : function(container, inhibitEvents, width, height) {
this._container = container;
this._children = container.get_children();
this.actor = new Clutter.Rectangle({ color: SHADE_COLOR,
x: 0,
y: 0,
border_width: 0,
reactive: inhibitEvents });
container.add_actor(this.actor);
this.actor.raise_top();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
if (width && height) {
this.actor.width = width;
this.actor.height = height;
this._allocationChangedSignalId = 0;
} else {
this.actor.width = container.width;
this.actor.height = container.height;
this._allocationChangedSignalId = container.connect('allocation-changed', Lang.bind(this, this._allocationChanged));
}
this._actorAddedSignalId = container.connect('actor-added', Lang.bind(this, this._actorAdded));
this._actorRemovedSignalId = container.connect('actor-removed', Lang.bind(this, this._actorRemoved));
this._highlighted = null;
},
_allocationChanged : function(container, box, flags) {
this.actor.width = this._container.width;
this.actor.height = this._container.height;
},
_actorAdded : function(container, newChild) {
let children = this._container.get_children();
let myIndex = children.indexOf(this.actor);
let newChildIndex = children.indexOf(newChild);
if (newChildIndex > myIndex) {
// The child was added above the shade (presumably it was
// made the new top-most child). Move it below the shade,
// and add it to this._children as the new topmost actor.
newChild.lower(this.actor);
this._children.push(newChild);
} else if (newChildIndex == 0) {
// Bottom of stack
this._children.unshift(newChild);
} else {
// Somewhere else; insert it into the correct spot
let prevChild = this._children.indexOf(children[newChildIndex - 1]);
if (prevChild != -1) // paranoia
this._children.splice(prevChild + 1, 0, newChild);
}
},
_actorRemoved : function(container, child) {
let index = this._children.indexOf(child);
if (index != -1) // paranoia
this._children.splice(index, 1);
if (child == this._highlighted)
this._highlighted = null;
},
/**
* highlight:
* @window: actor to highlight
*
* Highlights the indicated actor and unhighlights any other
* currently-highlighted actor. With no arguments or a false/null
* argument, all actors will be unhighlighted.
*/
highlight : function(window) {
if (this._highlighted == window)
return;
// Walk this._children raising and lowering actors as needed.
// Things get a little tricky if the to-be-raised and
// to-be-lowered actors were originally adjacent, in which
// case we may need to indicate some *other* actor as the new
// sibling of the to-be-lowered one.
let below = this.actor;
for (let i = this._children.length - 1; i >= 0; i--) {
if (this._children[i] == window)
this._children[i].raise_top();
else if (this._children[i] == this._highlighted)
this._children[i].lower(below);
else
below = this._children[i];
}
this._highlighted = window;
},
/**
* destroy:
*
* Destroys the lightbox.
*/
destroy : function() {
this.actor.destroy();
},
/**
* _onDestroy:
*
* This is called when the lightbox' actor is destroyed, either
* by destroying its container or by explicitly calling this.destroy().
*/
_onDestroy: function() {
if (this._allocationChangedSignalId != 0)
this._container.disconnect(this._allocationChangedSignalId);
this._container.disconnect(this._actorAddedSignalId);
this._container.disconnect(this._actorRemovedSignalId);
this.highlight(null);
}
};

View File

@ -3,78 +3,21 @@
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
// Link is a clickable link. Right now it just handles properly capturing
// press and release events and short-circuiting the button handling in
// ClutterText, but more features like different colors for hover/pressed states
// or a different mouse cursor could be implemented.
//
// The properties passed in are forwarded to the Clutter.Text() constructor,
// so can include, 'text', 'font_name', etc.
function Link(props) {
this._init(props);
}
Link.prototype = {
_init : function(props) {
let realProps = { reactive: true };
let realProps = { reactive: true,
style_class: 'shell-link' };
// The user can pass in reactive: false to override the above and get
// a non-reactive link (a link to the current page, perhaps)
Lang.copyProperties(props, realProps);
Lang.copyProperties(props, realProps);
this.actor = new Clutter.Text(realProps);
this.actor._delegate = this;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
this._buttonDown = false;
this._havePointer = false;
},
// Update the text of the link
setText : function(text) {
this.actor.text = text;
},
// We want to react on buttonDown, but if we override button-release-event for
// ClutterText, but not button-press-event, we get a stuck grab. Tracking
// buttonDown and doing the grab isn't really necessary, but doing it makes
// the behavior perfectly correct if the user clicks on one actor, drags
// to another and releases - that should not trigger either actor.
_onButtonPress : function(actor, event) {
this._buttonDown = true;
this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
Clutter.grab_pointer(actor);
return true;
},
_onButtonRelease : function(actor, event) {
if (this._buttonDown) {
this._buttonDown = false;
Clutter.ungrab_pointer(actor);
if (this._havePointer)
this.emit('clicked');
}
return true;
},
_onEnter : function(actor, event) {
if (event.get_source() == actor)
this._havePointer = true;
return false;
},
_onLeave : function(actor, event) {
if (event.get_source() == actor)
this._havePointer = false;
return false;
this.actor = new St.Button(realProps);
}
};

View File

@ -4,26 +4,20 @@ const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const ExtensionSystem = imports.ui.extensionSystem;
const Link = imports.ui.link;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const LG_BORDER_COLOR = new Clutter.Color();
LG_BORDER_COLOR.from_pixel(0x0000aca0);
const LG_BACKGROUND_COLOR = new Clutter.Color();
LG_BACKGROUND_COLOR.from_pixel(0x000000d5);
const GREY = new Clutter.Color();
GREY.from_pixel(0xAFAFAFFF);
const MATRIX_GREEN = new Clutter.Color();
MATRIX_GREEN.from_pixel(0x88ff66ff);
// FIXME pull from GConf
const MATRIX_FONT = 'Monospace 10';
/* Imports...feel free to add here as needed */
/* Imports...feel free to add here as needed */
var commandHeader = "const Clutter = imports.gi.Clutter; " +
"const GLib = imports.gi.GLib; " +
"const Gtk = imports.gi.Gtk; " +
@ -47,32 +41,41 @@ function Notebook() {
Notebook.prototype = {
_init: function() {
this.actor = new Big.Box();
this.actor = new St.BoxLayout({ vertical: true });
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4, padding: 2 });
this.tabControls = new St.BoxLayout({ style_class: "labels" });
this._selectedIndex = -1;
this._tabs = [];
},
appendPage: function(name, child) {
let labelOuterBox = new Big.Box({ padding: 2 });
let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN,
reactive: true });
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
let label = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
text: name });
labelBox.connect('button-press-event', Lang.bind(this, function () {
let labelBox = new St.BoxLayout({ style_class: "notebook-tab" });
let label = new St.Button({ label: name });
label.connect('clicked', Lang.bind(this, function () {
this.selectChild(child);
return true;
}));
labelBox.append(label, Big.BoxPackFlags.EXPAND);
this._tabs.push([child, labelBox]);
child.hide();
this.actor.append(child, Big.BoxPackFlags.EXPAND);
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
labelBox.add(label, { expand: true });
this.tabControls.add(labelBox);
let scrollview = new St.ScrollView({ x_fill: true, y_fill: true });
scrollview.get_hscroll_bar().hide();
scrollview.add_actor(child);
let tabData = { child: child,
labelBox: labelBox,
label: label,
scrollView: scrollview,
_scrollToBottom: false };
this._tabs.push(tabData);
scrollview.hide();
this.actor.add(scrollview, { expand: true });
let vAdjust = scrollview.vscroll.adjustment;
vAdjust.connect('changed', Lang.bind(this, function () { this._onAdjustScopeChanged(tabData); }));
vAdjust.connect('notify::value', Lang.bind(this, function() { this._onAdjustValueChanged(tabData); }));
if (this._selectedIndex == -1)
this.selectIndex(0);
},
@ -80,10 +83,9 @@ Notebook.prototype = {
_unselect: function() {
if (this._selectedIndex < 0)
return;
let [child, labelBox] = this._tabs[this._selectedIndex];
labelBox.padding = 2;
labelBox.border = 0;
child.hide();
let tabData = this._tabs[this._selectedIndex];
tabData.labelBox.set_style_pseudo_class(null);
tabData.scrollView.hide();
this._selectedIndex = -1;
},
@ -95,12 +97,11 @@ Notebook.prototype = {
this.emit('selection', null);
return;
}
let [child, labelBox] = this._tabs[index];
labelBox.padding = 1;
labelBox.border = 1;
child.show();
let tabData = this._tabs[index];
tabData.labelBox.set_style_pseudo_class('selected');
tabData.scrollView.show();
this._selectedIndex = index;
this.emit('selection', child);
this.emit('selection', tabData.child);
},
selectChild: function(child) {
@ -108,13 +109,32 @@ Notebook.prototype = {
this.selectIndex(-1);
else {
for (let i = 0; i < this._tabs.length; i++) {
let [tabChild, labelBox] = this._tabs[i];
if (tabChild == child) {
let tabData = this._tabs[i];
if (tabData.child == child) {
this.selectIndex(i);
return;
}
}
}
},
scrollToBottom: function(index) {
let tabData = this._tabs[index];
tabData._scrollToBottom = true;
},
_onAdjustValueChanged: function (tabData) {
let vAdjust = tabData.scrollView.vscroll.adjustment;
if (vAdjust.value < (vAdjust.upper - vAdjust.lower - 0.5))
tabData._scrolltoBottom = false;
},
_onAdjustScopeChanged: function (tabData) {
if (!tabData._scrollToBottom)
return;
let vAdjust = tabData.scrollView.vscroll.adjustment;
vAdjust.value = vAdjust.upper - vAdjust.page_size;
}
}
Signals.addSignalMethods(Notebook.prototype);
@ -130,20 +150,19 @@ Result.prototype = {
this.actor = new Big.Box();
let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
ellipsize: Pango.EllipsizeMode.END,
text: command });
let cmdTxt = new St.Label({ text: command });
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
let resultTxt = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
ellipsize: Pango.EllipsizeMode.END,
text: "r(" + index + ") = " + o });
let resultTxt = new St.Label({ text: "r(" + index + ") = " + o });
resultTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
let line = new Big.Box({ border_color: GREY,
border_bottom: 1,
height: 8 });
this.actor.append(line, Big.BoxPackFlags.NONE);
let line = new Clutter.Rectangle({ name: "Separator",
height: 1 });
let padBin = new St.Bin({ name: "Separator", x_fill: true, y_fill: true });
padBin.add_actor(line);
this.actor.append(padBin, Big.BoxPackFlags.NONE);
}
}
@ -158,17 +177,14 @@ ActorHierarchy.prototype = {
this._parentList = [];
this.actor = new Big.Box({ spacing: 4,
border: 1,
padding: 4,
border_color: GREY });
this.actor = new St.BoxLayout({ name: "ActorHierarchy", vertical: true });
},
setTarget: function(actor) {
this._previousTarget = this._target;
this.target = actor;
this.actor.remove_all();
this.actor.get_children().forEach(function (child) { child.destroy(); });
if (!(actor instanceof Clutter.Actor))
return;
@ -181,11 +197,9 @@ ActorHierarchy.prototype = {
while ((parent = parent.get_parent()) != null) {
this._parentList.push(parent);
let link = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
reactive: true,
text: "" + parent });
this.actor.append(link, Big.BoxPackFlags.IF_FITS);
let link = new St.Label({ reactive: true,
text: "" + parent });
this.actor.add_actor(link);
let parentTarget = parent;
link.connect('button-press-event', Lang.bind(this, function () {
this._selectByActor(parentTarget);
@ -214,16 +228,13 @@ PropertyInspector.prototype = {
this._parentList = [];
this.actor = new Big.Box({ spacing: 4,
border: 1,
padding: 4,
border_color: GREY });
this.actor = new St.BoxLayout({ name: "PropertyInspector", vertical: true });
},
setTarget: function(actor) {
this.target = actor;
this.actor.remove_all();
this.actor.get_children().forEach(function (child) { child.destroy(); });
for (let propName in actor) {
let valueStr;
@ -233,11 +244,9 @@ PropertyInspector.prototype = {
valueStr = '<error>';
}
let propText = propName + ": " + valueStr;
let propDisplay = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
reactive: true,
text: propText });
this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS);
let propDisplay = new St.Label({ reactive: true,
text: propText });
this.actor.add_actor(propDisplay);
}
}
}
@ -249,20 +258,17 @@ function Inspector() {
Inspector.prototype = {
_init: function() {
let width = 150;
let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
border: 1,
border_color: LG_BORDER_COLOR,
corner_radius: 4,
y: global.stage.height/2,
reactive: true
});
let primary = global.get_primary_monitor();
let eventHandler = new St.BoxLayout({ name: "LookingGlassDialog",
vertical: false,
y: primary.y + Math.floor(primary.height / 2),
reactive: true });
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
eventHandler.x = primary.x + Math.floor((primary.width - eventHandler.width) / 2);
}));
global.stage.add_actor(eventHandler);
let displayText = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT, text: '' });
eventHandler.append(displayText, Big.BoxPackFlags.EXPAND);
let displayText = new St.Label();
eventHandler.add(displayText, { expand: true });
let borderPaintTarget = null;
let borderPaintId = null;
@ -302,6 +308,135 @@ Inspector.prototype = {
Signals.addSignalMethods(Inspector.prototype);
function ErrorLog() {
this._init();
}
ErrorLog.prototype = {
_init: function() {
this.actor = new St.BoxLayout();
this.text = new St.Label();
this.actor.add(this.text);
this.text.clutter_text.line_wrap = true;
this.actor.connect('notify::mapped', Lang.bind(this, this._renderText));
},
_formatTime: function(d){
function pad(n) { return n < 10 ? '0' + n : n };
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'
},
_renderText: function() {
if (!this.actor.mapped)
return;
let text = this.text.text;
let stack = Main._getAndClearErrorStack();
for (let i = 0; i < stack.length; i++) {
let logItem = stack[i];
text += logItem.category + " t=" + this._formatTime(new Date(logItem.timestamp)) + " " + logItem.message + "\n";
}
this.text.text = text;
}
}
function Extensions() {
this._init();
}
Extensions.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
text: _("No extensions installed") });
this._extensionsList = new St.BoxLayout({ vertical: true,
style_class: 'lg-extensions-list' });
this.actor.add(this._extensionsList);
this._loadExtensionList();
},
_loadExtensionList: function() {
let extensions = ExtensionSystem.extensionMeta;
let totalExtensions = 0;
for (let uuid in extensions) {
let extensionDisplay = this._createExtensionDisplay(extensions[uuid]);
this._extensionsList.add(extensionDisplay);
totalExtensions++;
}
if (totalExtensions == 0) {
this._extensionsList.add(this._noExtensions);
}
},
_onViewSource: function (actor) {
let meta = actor._extensionMeta;
let file = Gio.file_new_for_path(meta.path);
let uri = file.get_uri();
Gio.app_info_launch_default_for_uri(uri, global.create_app_launch_context());
Main.lookingGlass.close();
},
_onWebPage: function (actor) {
let meta = actor._extensionMeta;
Gio.app_info_launch_default_for_uri(meta.url, global.create_app_launch_context());
Main.lookingGlass.close();
},
_stateToString: function(extensionState) {
switch (extensionState) {
case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
return _("Error");
case ExtensionSystem.ExtensionState.OUT_OF_DATE:
return _("Out of date");
}
return "Unknown"; // Not translated, shouldn't appear
},
_createExtensionDisplay: function(meta) {
let box = new St.BoxLayout({ style_class: 'lg-extension', vertical: true });
let name = new St.Label({ style_class: 'lg-extension-name',
text: meta.name });
box.add(name, { expand: true });
let description = new St.Label({ style_class: 'lg-extension-description',
text: meta.description });
box.add(description, { expand: true });
let metaBox = new St.BoxLayout();
box.add(metaBox);
let stateString = this._stateToString(meta.state);
let state = new St.Label({ style_class: 'lg-extension-state',
text: this._stateToString(meta.state) });
let actionsContainer = new St.Bin({ x_align: St.Align.END });
metaBox.add(actionsContainer);
let actionsBox = new St.BoxLayout({ style_class: 'lg-extension-actions' });
actionsContainer.set_child(actionsBox);
let viewsource = new Link.Link({ label: _("View Source") });
viewsource.actor._extensionMeta = meta;
viewsource.actor.connect('clicked', Lang.bind(this, this._onViewSource));
actionsBox.add(viewsource.actor);
if (meta.url) {
let webpage = new Link.Link({ label: _("Web Page") });
webpage.actor._extensionMeta = meta;
webpage.actor.connect('clicked', Lang.bind(this, this._onWebPage));
actionsBox.add(webpage.actor);
}
return box;
}
};
function LookingGlass() {
this._init();
}
@ -314,6 +449,10 @@ LookingGlass.prototype = {
this._savedText = null;
this._historyNavIndex = -1;
this._history = [];
this._borderPaintTarget = null;
this._borderPaintId = 0;
this._borderDestroyId = 0;
this._readHistory();
this._open = false;
@ -321,29 +460,26 @@ LookingGlass.prototype = {
this._offset = 0;
this._results = [];
// TODO replace with scrolling or something better
this._maxItems = 10;
// Sort of magic, but...eh.
this._maxItems = 150;
this.actor = new St.BoxLayout({ name: "LookingGlassDialog",
vertical: true,
visible: false });
let gconf = Shell.GConf.get_default();
gconf.watch_directory("/desktop/gnome/interface");
gconf.connect("changed::/desktop/gnome/interface/monospace_font_name",
Lang.bind(this, this._updateFont));
this._updateFont();
this.actor = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
border: 1,
border_color: LG_BORDER_COLOR,
corner_radius: 4,
padding_top: 8,
padding_left: 4,
padding_right: 4,
padding_bottom: 4,
spacing: 4,
visible: false
});
global.stage.add_actor(this.actor);
let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
border: 1, border_color: GREY,
corner_radius: 4 });
this.actor.append(toolbar, Big.BoxPackFlags.NONE);
let toolbar = new St.BoxLayout({ name: "Toolbar" });
this.actor.add_actor(toolbar);
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
24);
toolbar.append(inspectIcon, Big.BoxPackFlags.NONE);
toolbar.add_actor(inspectIcon);
inspectIcon.reactive = true;
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
let inspector = new Inspector();
@ -361,31 +497,27 @@ LookingGlass.prototype = {
}));
let notebook = new Notebook();
this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND);
toolbar.append(notebook.tabControls, Big.BoxPackFlags.END);
this._notebook = notebook;
this.actor.add(notebook.actor, { expand: true });
this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: 4 });
let emptyBox = new St.Bin();
toolbar.add(emptyBox, { expand: true });
toolbar.add_actor(notebook.tabControls);
this._evalBox = new St.BoxLayout({ name: "EvalBox", vertical: true });
notebook.appendPage('Evaluator', this._evalBox);
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: 4 });
this._evalBox.append(this._resultsArea, Big.BoxPackFlags.EXPAND);
this._evalBox.add(this._resultsArea, { expand: true });
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
this._evalBox.append(entryArea, Big.BoxPackFlags.NONE);
this._evalBox.add_actor(entryArea);
let label = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
text: 'js>>> ' });
let label = new St.Label({ text: 'js>>> ' });
entryArea.append(label, Big.BoxPackFlags.NONE);
this._entry = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
editable: true,
activatable: true,
singleLineMode: true,
text: ''});
this._entry = new St.Entry();
/* unmapping the edit box will un-focus it, undo that */
notebook.connect('selection', Lang.bind(this, function (nb, child) {
if (child == this._evalBox)
@ -403,7 +535,13 @@ LookingGlass.prototype = {
notebook.selectIndex(0);
}));
this._entry.connect('activate', Lang.bind(this, function (o, e) {
this._errorLog = new ErrorLog();
notebook.appendPage('Errors', this._errorLog.actor);
this._extensions = new Extensions();
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
let text = o.get_text();
// Ensure we don't get newlines in the command; the history file is
// newline-separated.
@ -416,12 +554,9 @@ LookingGlass.prototype = {
this._historyNavIndex = -1;
return true;
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
} else if (symbol == Clutter.Up) {
if (symbol == Clutter.Up) {
if (this._historyNavIndex >= this._history.length - 1)
return true;
this._historyNavIndex++;
@ -446,6 +581,19 @@ LookingGlass.prototype = {
}));
},
_updateFont: function() {
let gconf = Shell.GConf.get_default();
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
let fontDesc = Pango.Font.description_from_string(fontName);
// We ignore everything but size and style; you'd be crazy to set your system-wide
// monospace font to be bold/oblique/etc. Could easily be added here.
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
},
_readHistory: function () {
if (!this._historyFile.query_exists(null))
return;
@ -475,6 +623,18 @@ LookingGlass.prototype = {
this._results.push(result);
this._resultsArea.append(result.actor, Big.BoxPackFlags.NONE);
this._propInspector.setTarget(obj);
if (this._borderPaintTarget != null) {
this._borderPaintTarget.disconnect(this._borderPaintId);
this._borderPaintTarget = null;
}
if (obj instanceof Clutter.Actor) {
this._borderPaintTarget = obj;
this._borderPaintId = Shell.add_hook_paint_red_border(obj);
this._borderDestroyId = obj.connect('destroy', Lang.bind(this, function () {
this._borderDestroyId = 0;
this._borderPaintTarget = null;
}));
}
let children = this._resultsArea.get_children();
if (children.length > this._maxItems) {
this._results.shift();
@ -482,6 +642,9 @@ LookingGlass.prototype = {
this._offset++;
}
this._it = obj;
// Scroll to bottom
this._notebook.scrollToBottom(0);
},
_evaluate : function(command) {
@ -518,11 +681,11 @@ LookingGlass.prototype = {
},
_resizeTo: function(actor) {
let stage = global.stage;
let myWidth = stage.width * 0.7;
let myHeight = stage.height * 0.7;
let primary = global.get_primary_monitor();
let myWidth = primary.width * 0.7;
let myHeight = primary.height * 0.7;
let [srcX, srcY] = actor.get_transformed_position();
this.actor.x = srcX + (stage.width-myWidth)/2;
this.actor.x = srcX + (primary.width - myWidth) / 2;
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
@ -538,17 +701,32 @@ LookingGlass.prototype = {
this._resizeTo(actor);
},
// Handle key events which are relevant for all tabs of the LookingGlass
_globalKeyPressEvent : function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
}
return false;
},
open : function() {
if (this._open)
return;
if (!Main.pushModal(this.actor))
return;
this._keyPressEventId = global.stage.connect('key-press-event',
Lang.bind(this, this._globalKeyPressEvent));
this.actor.show();
this.actor.lower(Main.chrome.actor);
this._open = true;
Tweener.removeTweens(this.actor);
Main.pushModal(this.actor);
global.stage.set_key_focus(this._entry);
Tweener.addTween(this.actor, { time: 0.5,
@ -561,10 +739,19 @@ LookingGlass.prototype = {
if (!this._open)
return;
if (this._keyPressEventId)
global.stage.disconnect(this._keyPressEventId);
this._historyNavIndex = -1;
this._open = false;
Tweener.removeTweens(this.actor);
if (this._borderPaintTarget != null) {
this._borderPaintTarget.disconnect(this._borderPaintId);
this._borderPaintTarget.disconnect(this._borderDestroyId);
this._borderPaintTarget = null;
}
Main.popModal(this.actor);
Tweener.addTween(this.actor, { time: 0.5,

View File

@ -1,6 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
@ -9,14 +10,21 @@ const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Chrome = imports.ui.chrome;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
const MessageTray = imports.ui.messageTray;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const PlaceDisplay = imports.ui.placeDisplay;
const RunDialog = imports.ui.runDialog;
const LookingGlass = imports.ui.lookingGlass;
const NotificationDaemon = imports.ui.notificationDaemon;
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const ShellDBus = imports.ui.shellDBus;
const Sidebar = imports.ui.sidebar;
const Tweener = imports.ui.tweener;
const WindowManager = imports.ui.windowManager;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
@ -25,13 +33,22 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let chrome = null;
let panel = null;
let sidebar = null;
let placesManager = null;
let overview = null;
let runDialog = null;
let lookingGlass = null;
let wm = null;
let notificationDaemon = null;
let messageTray = null;
let windowAttentionHandler = null;
let recorder = null;
let shellDBusService = null;
let modalCount = 0;
let modalActorFocusStack = [];
let _errorLogStack = [];
let _startDate;
let background = null;
function start() {
// Add a binding for "global" in the global JS namespace; (gjs
@ -39,21 +56,34 @@ function start() {
// called "window".)
window.global = Shell.Global.get();
// Now monkey patch utility functions into the global proxy;
// This is easier and faster than indirecting down into global
// if we want to call back up into JS.
global.logError = _logError;
global.log = _logDebug;
Gio.DesktopAppInfo.set_desktop_env("GNOME");
global.grab_dbus_service();
shellDBusService = new ShellDBus.GnomeShell();
// Force a connection now; dbus.js will do this internally
// if we use its name acquisition stuff but we aren't right
// now; to do so we'd need to convert from its async calls
// back into sync ones.
DBus.session.flush();
Tweener.init();
Environment.init();
// Ensure ShellAppMonitor is initialized; this will
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
// needs to load all the .desktop files, and ShellAppMonitor
// needs to load all the .desktop files, and ShellWindowTracker
// will use those to associate with windows. Right now
// the Monitor doesn't listen for installed app changes
// and recalculate application associations, so to avoid
// races for now we initialize it here. It's better to
// be predictable anyways.
Shell.AppMonitor.get_default();
Shell.WindowTracker.get_default();
Shell.AppUsage.get_default();
// The background color really only matters if there is no desktop
// window (say, nautilus) running. We set it mostly so things look good
@ -66,16 +96,32 @@ function start() {
for (let i = 0; i < children.length; i++)
children[i].destroy();
global.connect('panel-run-dialog', function(panel) {
// Make sure not more than one run dialog is shown.
getRunDialog().open();
let themeContext = St.ThemeContext.get_for_stage (global.stage);
let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
themeContext.set_theme (theme);
let shellwm = global.window_manager;
shellwm.takeover_keybinding("panel_main_menu");
shellwm.connect("keybinding::panel_main_menu", function () {
overview.toggle();
});
shellwm.takeover_keybinding("panel_run_dialog");
shellwm.connect("keybinding::panel_run_dialog", function () {
getRunDialog().open();
});
placesManager = new PlaceDisplay.PlacesManager();
overview = new Overview.Overview();
chrome = new Chrome.Chrome();
panel = new Panel.Panel();
sidebar = new Sidebar.Sidebar();
wm = new WindowManager.WindowManager();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
messageTray = new MessageTray.MessageTray();
_startDate = new Date();
global.screen.connect('toggle-recording', function() {
if (recorder == null) {
@ -85,26 +131,97 @@ function start() {
if (recorder.is_recording()) {
recorder.pause();
} else {
//read the parameters from GConf always in case they have changed
let gconf = Shell.GConf.get_default();
recorder.set_framerate(gconf.get_int("recorder/framerate"));
recorder.set_filename("shell-%d%u-%c." + gconf.get_string("recorder/file_extension"));
let pipeline = gconf.get_string("recorder/pipeline");
if (!pipeline.match(/^\s*$/))
recorder.set_pipeline(pipeline);
else
recorder.set_pipeline(null);
recorder.record();
}
});
_relayout();
background = global.create_root_pixmap_actor();
global.stage.add_actor(background);
background.lower_bottom();
global.connect('screen-size-changed', _relayout);
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
panel.startupAnimation();
let display = global.screen.get_display();
display.connect('overlay-key', Lang.bind(overview, overview.toggle));
global.connect('panel-main-menu', Lang.bind(overview, overview.toggle));
global.stage.connect('captured-event', _globalKeyPressHandler);
_log('info', 'loaded at ' + _startDate);
log('GNOME Shell started at ' + _startDate);
Mainloop.idle_add(_removeUnusedWorkspaces);
}
/**
* _log:
* @category: string message type ('info', 'error')
* @msg: A message string
* ...: Any further arguments are converted into JSON notation,
* and appended to the log message, separated by spaces.
*
* Log a message into the LookingGlass error
* stream. This is primarily intended for use by the
* extension system as well as debugging.
*/
function _log(category, msg) {
let text = msg;
if (arguments.length > 2) {
text += ': ';
for (let i = 2; i < arguments.length; i++) {
text += JSON.stringify(arguments[i]);
if (i < arguments.length - 1)
text += " ";
}
}
_errorLogStack.push({timestamp: new Date().getTime(),
category: category,
message: text });
}
function _logError(msg) {
return _log('error', msg);
}
function _logDebug(msg) {
return _log('debug', msg);
}
// Used by the error display in lookingGlass.js
function _getAndClearErrorStack() {
let errors = _errorLogStack;
_errorLogStack = [];
return errors;
}
function _relayout() {
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
let primary = global.get_primary_monitor();
panel.actor.set_position(primary.x, primary.y);
panel.actor.set_size(primary.width, Panel.PANEL_HEIGHT);
overview.relayout();
background.set_size(global.screen_width, global.screen_height);
// To avoid updating the position and size of the workspaces
// in the overview, we just hide the overview. The positions
// will be updated when it is next shown. We do the same for
// the calendar popdown.
overview.hide();
panel.hideCalendar();
}
// metacity-clutter currently uses the same prefs as plain metacity,
@ -175,7 +292,7 @@ function _globalKeyPressHandler(actor, event) {
overview.hide();
return true;
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
} else if (symbol == Clutter.F2 && (Shell.get_event_state(event) & Clutter.ModifierType.MOD1_MASK)) {
getRunDialog().open();
}
}
@ -205,9 +322,18 @@ function _findModal(actor) {
* Next, record the current Clutter keyboard focus on a stack. If the modal stack
* returns to this actor, reset the focus to the actor which was focused
* at the time pushModal() was invoked.
*
* Returns: true iff we successfully acquired a grab or already had one
*/
function pushModal(actor) {
let timestamp = global.screen.get_display().get_current_time();
if (modalCount == 0) {
if (!global.begin_modal(global.get_current_time())) {
log("pushModal: invocation of begin_modal failed");
return false;
}
}
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
modalCount += 1;
actor.connect('destroy', function() {
@ -225,14 +351,7 @@ function pushModal(actor) {
}
modalActorFocusStack.push([actor, curFocus]);
if (modalCount > 1)
return;
if (!global.begin_modal(timestamp)) {
log("pushModal: invocation of begin_modal failed");
return;
}
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
return true;
}
/**
@ -244,8 +363,6 @@ function pushModal(actor) {
* previous focus at the time when pushModal() was invoked.
*/
function popModal(actor) {
let timestamp = global.screen.get_display().get_current_time();
modalCount -= 1;
let focusIndex = _findModal(actor);
if (focusIndex >= 0) {
@ -263,7 +380,7 @@ function popModal(actor) {
if (modalCount > 0)
return;
global.end_modal(timestamp);
global.end_modal(global.get_current_time());
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
}
@ -282,16 +399,145 @@ function getRunDialog() {
return runDialog;
}
function createAppLaunchContext() {
let screen = global.screen;
let display = screen.get_display();
/**
* activateWindow:
* @window: the Meta.Window to activate
* @time: (optional) current event time
* @workspaceNum: (optional) window's workspace number
*
* Activates @window, switching to its workspace first if necessary,
* and switching out of the overview if it's currently active
*/
function activateWindow(window, time, workspaceNum) {
let activeWorkspaceNum = global.screen.get_active_workspace_index();
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
let context = new Gdk.AppLaunchContext();
context.set_timestamp(display.get_current_time());
if (!time)
time = global.get_current_time();
// Make sure that the app is opened on the current workspace even if
// the user switches before it starts
context.set_desktop(screen.get_active_workspace_index());
if (windowWorkspaceNum != activeWorkspaceNum) {
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
workspace.activate_with_focus(window, time);
} else {
window.activate(time);
}
return context;
overview.hide();
}
// TODO - replace this timeout with some system to guess when the user might
// be e.g. just reading the screen and not likely to interact.
const DEFERRED_TIMEOUT_SECONDS = 20;
var _deferredWorkData = {};
// Work scheduled for some point in the future
var _deferredWorkQueue = [];
// Work we need to process before the next redraw
var _beforeRedrawQueue = [];
// Counter to assign work ids
var _deferredWorkSequence = 0;
var _deferredTimeoutId = 0;
function _runDeferredWork(workId) {
if (!_deferredWorkData[workId])
return;
let index = _deferredWorkQueue.indexOf(workId);
if (index < 0)
return;
_deferredWorkQueue.splice(index, 1);
_deferredWorkData[workId].callback();
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
Mainloop.source_remove(_deferredTimeoutId);
_deferredTimeoutId = 0;
}
}
function _runAllDeferredWork() {
while (_deferredWorkQueue.length > 0)
_runDeferredWork(_deferredWorkQueue[0]);
}
function _runBeforeRedrawQueue() {
for (let i = 0; i < _beforeRedrawQueue.length; i++) {
let workId = _beforeRedrawQueue[i];
_runDeferredWork(workId);
}
_beforeRedrawQueue = [];
}
function _queueBeforeRedraw(workId) {
_beforeRedrawQueue.push(workId);
if (_beforeRedrawQueue.length == 1) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function () {
_runBeforeRedrawQueue();
return false;
}, null);
}
}
/**
* initializeDeferredWork:
* @actor: A #ClutterActor
* @callback: Function to invoke to perform work
*
* This function sets up a callback to be invoked when either the
* given actor is mapped, or after some period of time when the machine
* is idle. This is useful if your actor isn't always visible on the
* screen (for example, all actors in the overview), and you don't want
* to consume resources updating if the actor isn't actually going to be
* displaying to the user.
*
* Note that queueDeferredWork is called by default immediately on
* initialization as well, under the assumption that new actors
* will need it.
*
* Returns: A string work identifer
*/
function initializeDeferredWork(actor, callback, props) {
// Turn into a string so we can use as an object property
let workId = "" + (++_deferredWorkSequence);
_deferredWorkData[workId] = { 'actor': actor,
'callback': callback };
actor.connect('notify::mapped', function () {
if (!(actor.mapped && _deferredWorkQueue.indexOf(workId) >= 0))
return;
_queueBeforeRedraw(workId);
});
actor.connect('destroy', function() {
let index = _deferredWorkQueue.indexOf(workId);
if (index >= 0)
_deferredWorkQueue.splice(index, 1);
delete _deferredWorkData[workId];
});
queueDeferredWork(workId);
return workId;
}
/**
* queueDeferredWork:
* @workId: work identifier
*
* Ensure that the work identified by @workId will be
* run on map or timeout. You should call this function
* for example when data being displayed by the actor has
* changed.
*/
function queueDeferredWork(workId) {
let data = _deferredWorkData[workId];
if (!data) {
global.logError("invalid work id ", workId);
return;
}
if (_deferredWorkQueue.indexOf(workId) < 0)
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, function () {
_runAllDeferredWork();
_deferredTimeoutId = 0;
return false;
});
}
}

761
js/ui/messageTray.js Normal file
View File

@ -0,0 +1,761 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const ANIMATION_TIME = 0.2;
const NOTIFICATION_TIMEOUT = 4;
const SUMMARY_TIMEOUT = 1;
const MESSAGE_TRAY_TIMEOUT = 0.2;
const ICON_SIZE = 24;
const State = {
HIDDEN: 0,
SHOWING: 1,
SHOWN: 2,
HIDING: 3
};
function _cleanMarkup(text) {
// Support &amp;, &quot;, &apos;, &lt; and &gt;, escape all other
// occurrences of '&'.
let _text = text.replace(/&(?!amp;|quot;|apos;|lt;|gt;)/g, "&amp;");
// Support <b>, <i>, and <u>, escape anything else
// so it displays as raw markup.
return _text.replace(/<(\/?[^biu]>|[^>\/][^>])/g, "&lt;$1");
}
// Notification:
// @id: the notification's id
// @source: the notification's Source
// @title: the title
// @banner: the banner text
// @bannerBody: whether or not to promote the banner to the body on overflow
//
// Creates a notification. In banner mode, it will show
// @source's icon, @title (in bold) and @banner, all on a single line
// (with @banner ellipsized if necessary).
//
// Additional notification details can be added via addBody(),
// addAction(), and addActor(). If any of these are called, then the
// notification will expand to show the additional actors (while
// hiding the @banner) if the pointer is moved into it while it is
// visible.
//
// If @bannerBody is %true, then @banner will also be used as the body
// of the notification (as with addBody()) when the banner is expanded.
// In this case, if @banner is too long to fit in the single-line mode,
// the notification will be made expandable automatically.
function Notification(id, source, title, banner, bannerBody) {
this._init(id, source, title, banner, bannerBody);
}
Notification.prototype = {
_init: function(id, source, title, banner, bannerBody) {
this.id = id;
this.source = source;
this._bannerBody = bannerBody;
source.connect('clicked', Lang.bind(this,
function() {
this.emit('dismissed');
}));
this.actor = new St.Table({ name: 'notification' });
this.update(title, banner, true);
},
// update:
// @title: the new title
// @banner: the new banner
// @clear: whether or not to clear out extra actors
//
// Updates the notification by regenerating its icon and updating
// the title/banner. If @clear is %true, it will also remove any
// additional actors/action buttons previously added.
update: function(title, banner, clear) {
let children = this.actor.get_children();
for (let i = 0; i < children.length; i++) {
let meta = this.actor.get_child_meta(children[i]);
if (clear || meta.row == 0 || (this._bannerBody && meta.row == 1))
children[i].destroy();
}
if (clear) {
this.actions = {};
this._actionBox = null;
}
let icon = this.source.createIcon(ICON_SIZE);
icon.reactive = true;
this.actor.add(icon, { row: 0,
col: 0,
x_expand: false,
y_expand: false,
y_fill: false });
icon.connect('button-release-event', Lang.bind(this,
function () {
this.source.clicked();
}));
// The first line should have the title, followed by the
// banner text, but ellipsized if they won't both fit. We can't
// make St.Table or St.BoxLayout do this the way we want (don't
// show banner at all if title needs to be ellipsized), so we
// use Shell.GenericContainer.
this._bannerBox = new Shell.GenericContainer();
this._bannerBox.connect('get-preferred-width', Lang.bind(this, this._bannerBoxGetPreferredWidth));
this._bannerBox.connect('get-preferred-height', Lang.bind(this, this._bannerBoxGetPreferredHeight));
this._bannerBox.connect('allocate', Lang.bind(this, this._bannerBoxAllocate));
this.actor.add(this._bannerBox, { row: 0,
col: 1,
y_expand: false,
y_fill: false });
this._titleLabel = new St.Label();
title = title ? _cleanMarkup(title.replace(/\n/g, ' ')) : '';
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
this._bannerBox.add_actor(this._titleLabel);
if (this._bannerBody)
this._bannerBodyText = banner;
else
this._bannerBodyText = null;
this._bannerLabel = new St.Label();
banner = banner ? _cleanMarkup(banner.replace(/\n/g, ' ')) : '';
this._bannerLabel.clutter_text.set_markup(banner);
this._bannerBox.add_actor(this._bannerLabel);
},
// addActor:
// @actor: actor to add to the notification
// @props: (optional) child properties
//
// Adds @actor to the notification's St.Table, using @props.
//
// If @props does not specify a %row, then @actor will be added
// to the bottom of the notification (unless there are action
// buttons present, in which case it will be added above them).
//
// If @props does not specify a %col, it will default to column 1.
// (Normally only the icon is in column 0.)
//
// If @props specifies an already-occupied cell, then the existing
// contents of the table will be shifted down to make room for it.
addActor: function(actor, props) {
if (!props)
props = {};
if (!('col' in props))
props.col = 1;
if ('row' in props) {
let children = this.actor.get_children();
let i, meta, collision = false;
for (i = 0; i < children.length; i++) {
meta = this.actor.get_child_meta(children[i]);
if (meta.row == props.row && meta.col == props.col) {
collision = true;
break;
}
}
if (collision) {
for (i = 0; i < children.length; i++) {
meta = this.actor.get_child_meta(children[i]);
if (meta.row >= props.row)
meta.row++;
}
}
} else {
if (this._actionBox) {
props.row = this.actor.row_count - 1;
this.actor.get_child_meta(this._actionBox).row++;
} else {
props.row = this.actor.row_count;
}
}
this.actor.add(actor, props);
},
// addBody:
// @text: the text
// @props: (optional) properties for addActor()
//
// Adds a multi-line label containing @text to the notification.
addBody: function(text, props) {
let body = new St.Label();
body.clutter_text.line_wrap = true;
body.clutter_text.line_wrap_mode = Pango.WrapMode.WORD_CHAR;
body.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
text = text ? _cleanMarkup(text) : '';
body.clutter_text.set_markup(text);
this.addActor(body, props);
},
_addBannerBody: function() {
this.addBody(this._bannerBodyText, { row: 1 });
this._bannerBodyText = null;
},
// addAction:
// @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
addAction: function(id, label) {
if (!this._actionBox) {
if (this._bannerBodyText)
this._addBannerBody();
let box = new St.BoxLayout({ name: 'notification-actions' });
this.addActor(box, { x_expand: false,
x_fill: false,
x_align: St.Align.END });
this._actionBox = box;
}
let button = new St.Button({ style_class: 'notification-button',
label: label });
this._actionBox.add(button);
button.connect('clicked', Lang.bind(this, function() { this.emit('action-invoked', id); }));
},
_bannerBoxGetPreferredWidth: function(actor, forHeight, alloc) {
let [titleMin, titleNat] = this._titleLabel.get_preferred_width(forHeight);
let [bannerMin, bannerNat] = this._bannerLabel.get_preferred_width(forHeight);
let [has_spacing, spacing] = this.actor.get_theme_node().get_length('spacing-columns', false);
alloc.min_size = titleMin;
alloc.natural_size = titleNat + (has_spacing ? spacing : 0) + bannerNat;
},
_bannerBoxGetPreferredHeight: function(actor, forWidth, alloc) {
[alloc.min_size, alloc.natural_size] =
this._titleLabel.get_preferred_height(forWidth);
},
_bannerBoxAllocate: function(actor, box, flags) {
let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(-1);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(-1);
let [has_spacing, spacing] = this.actor.get_theme_node().get_length('spacing-columns', false);
if (!has_spacing)
spacing = 0;
let availWidth = box.x2 - box.x1;
let titleBox = new Clutter.ActorBox();
titleBox.x1 = titleBox.y1 = 0;
titleBox.x2 = Math.min(titleNatW, availWidth);
titleBox.y2 = titleNatH;
this._titleLabel.allocate(titleBox, flags);
let overflow = false;
if (titleBox.x2 + spacing > availWidth) {
this._bannerLabel.hide();
overflow = true;
} else {
let bannerBox = new Clutter.ActorBox();
bannerBox.x1 = titleBox.x2 + spacing;
bannerBox.y1 = 0;
bannerBox.x2 = Math.min(bannerBox.x1 + bannerNatW, availWidth);
bannerBox.y2 = titleNatH;
this._bannerLabel.show();
this._bannerLabel.allocate(bannerBox, flags);
if (bannerBox.x2 < bannerBox.x1 + bannerNatW)
overflow = true;
}
if (this._bannerBodyText &&
(overflow || this._bannerBodyText.indexOf('\n') > -1))
this._addBannerBody();
},
popOut: function() {
if (this.actor.row_count <= 1)
return false;
Tweener.addTween(this._bannerLabel,
{ opacity: 0,
time: ANIMATION_TIME,
transition: "easeOutQuad" });
return true;
},
popIn: function() {
if (this.actor.row_count <= 1)
return false;
Tweener.addTween(this._bannerLabel,
{ opacity: 255,
time: ANIMATION_TIME,
transition: "easeOutQuad" });
return true;
},
destroy: function() {
this.emit('destroy');
}
};
Signals.addSignalMethods(Notification.prototype);
function Source(id, createIcon) {
this._init(id, createIcon);
}
Source.prototype = {
_init: function(id, createIcon) {
this.id = id;
this.text = null;
if (createIcon)
this.createIcon = createIcon;
this.handleReplacing = true;
},
// This can be overridden by a subclass, or by the createIcon
// parameter to _init()
createIcon: function(size) {
throw new Error('no implementation of createIcon in ' + this);
},
notify: function(notification) {
this.emit('notify', notification);
},
clicked: function() {
this.emit('clicked');
},
destroy: function() {
this.emit('destroy');
}
};
Signals.addSignalMethods(Source.prototype);
function MessageTray() {
this._init();
}
MessageTray.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ name: 'message-tray',
reactive: true });
this._notificationBin = new St.Bin({ reactive: true,
x_align: St.Align.MIDDLE });
this.actor.add(this._notificationBin);
this._notificationBin.hide();
this._notificationQueue = [];
this._notification = null;
this._summaryBin = new St.BoxLayout();
this.actor.add(this._summaryBin);
this._summary = new St.BoxLayout({ name: 'summary-mode',
reactive: true });
this._summaryBin.add(this._summary, { x_align: St.Align.END,
x_fill: false,
expand: true });
this._summary.connect('enter-event',
Lang.bind(this, this._onSummaryEntered));
this._summary.connect('leave-event',
Lang.bind(this, this._onSummaryLeft));
this._summaryBin.opacity = 0;
this.actor.connect('enter-event', Lang.bind(this, this._onTrayEntered));
this.actor.connect('leave-event', Lang.bind(this, this._onTrayLeft));
this._trayState = State.HIDDEN;
this._trayLeftTimeoutId = 0;
this._pointerInTray = false;
this._summaryState = State.HIDDEN;
this._summaryTimeoutId = 0;
this._pointerInSummary = false;
this._notificationState = State.HIDDEN;
this._notificationTimeoutId = 0;
this._overviewVisible = false;
this._notificationRemoved = false;
this.actor.show();
Main.chrome.addActor(this.actor, { affectsStruts: false,
visibleInOverview: true });
Main.chrome.trackActor(this._notificationBin, { affectsStruts: false });
global.connect('screen-size-changed',
Lang.bind(this, this._setSizePosition));
this._setSizePosition();
Main.overview.connect('showing', Lang.bind(this,
function() {
this._overviewVisible = true;
this._updateState();
}));
Main.overview.connect('hiding', Lang.bind(this,
function() {
this._overviewVisible = false;
this._updateState();
}));
this._sources = {};
this._icons = {};
},
_setSizePosition: function() {
let primary = global.get_primary_monitor();
this.actor.x = primary.x;
this.actor.y = primary.y + primary.height - 1;
this.actor.width = primary.width;
this._notificationBin.x = this._summaryBin.x = 0;
this._notificationBin.width = this._summaryBin.width = primary.width;
},
contains: function(source) {
return this._sources.hasOwnProperty(source.id);
},
add: function(source) {
if (this.contains(source)) {
log('Trying to re-add source ' + source.id);
return;
}
let iconBox = new St.Bin({ reactive: true });
iconBox.child = source.createIcon(ICON_SIZE);
this._summary.insert_actor(iconBox, 0);
this._summaryNeedsToBeShown = true;
this._icons[source.id] = iconBox;
this._sources[source.id] = source;
source.connect('notify', Lang.bind(this, this._onNotify));
iconBox.connect('button-release-event', Lang.bind(this,
function () {
source.clicked();
}));
source.connect('destroy', Lang.bind(this,
function () {
this.removeSource(source);
}));
},
removeSource: function(source) {
if (!this.contains(source))
return;
// remove all notifications with this source from the queue
let newNotificationQueue = [];
for (let i = 0; i < this._notificationQueue.length; i++) {
if (this._notificationQueue[i].source != source)
newNotificationQueue.push(this._notificationQueue[i]);
}
this._notificationQueue = newNotificationQueue;
this._summary.remove_actor(this._icons[source.id]);
if (this._summary.get_children().length > 0)
this._summaryNeedsToBeShown = true;
else
this._summaryNeedsToBeShown = false;
delete this._icons[source.id];
delete this._sources[source.id];
if (this._notification && this._notification.source == source) {
if (this._notificationTimeoutId) {
Mainloop.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0;
}
this._notificationRemoved = true;
this._updateState();
}
},
removeNotification: function(notification) {
if (this._notification == notification && (this._notificationState == State.SHOWN || this._notificationState == State.SHOWING)) {
if (this._notificationTimeoutId) {
Mainloop.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0;
}
this._notificationRemoved = true;
this._updateState();
return;
}
let index = this._notificationQueue.indexOf(notification);
if (index != -1)
this._notificationQueue.splice(index, 1);
},
getSource: function(id) {
return this._sources[id];
},
_getNotification: function(id, source) {
if (this._notification && this._notification.id == id)
return this._notification;
for (let i = 0; i < this._notificationQueue.length; i++) {
if (this._notificationQueue[i].id == id && this._notificationQueue[i].source == source)
return this._notificationQueue[i];
}
return null;
},
_onNotify: function(source, notification) {
if (!notification.source.handleReplacing || this._getNotification(notification.id, source) == null) {
notification.connect('destroy',
Lang.bind(this, this.removeNotification));
this._notificationQueue.push(notification);
}
this._updateState();
},
_onSummaryEntered: function() {
this._pointerInSummary = true;
this._updateState();
},
_onSummaryLeft: function() {
this._pointerInSummary = false;
this._updateState();
},
_onTrayEntered: function() {
if (this._trayLeftTimeoutId) {
Mainloop.source_remove(this._trayLeftTimeoutId);
this._trayLeftTimeoutId = 0;
return;
}
this._pointerInTray = true;
this._updateState();
},
_onTrayLeft: function() {
// We wait just a little before hiding the message tray in case the
// user quickly moves the mouse back into it.
let timeout = MESSAGE_TRAY_TIMEOUT * 1000;
this._trayLeftTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, this._onTrayLeftTimeout));
},
_onTrayLeftTimeout: function() {
this._trayLeftTimeoutId = 0;
this._pointerInTray = false;
this._pointerInSummary = false;
this._updateState();
return false;
},
// All of the logic for what happens when occurs here; the various
// event handlers merely update variables such as
// "this._pointerInTray", "this._summaryState", etc, and
// _updateState() figures out what (if anything) needs to be done
// at the present time.
_updateState: function() {
// Notifications
let notificationsPending = this._notificationQueue.length > 0;
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
let notificationExpanded = this._notificationBin.y < 0;
let notificationExpired = (this._notificationTimeoutId == 0 && !this._pointerInTray) || this._notificationRemoved;
if (this._notificationState == State.HIDDEN) {
if (notificationsPending)
this._showNotification();
} else if (this._notificationState == State.SHOWN) {
if (notificationExpired)
this._hideNotification();
else if (notificationPinned && !notificationExpanded)
this._expandNotification();
}
// Summary
let summarySummoned = this._pointerInSummary || this._overviewVisible;
let summaryPinned = this._summaryTimeoutId != 0 || this._pointerInTray || summarySummoned;
let notificationsVisible = (this._notificationState == State.SHOWING ||
this._notificationState == State.SHOWN);
let notificationsDone = !notificationsVisible && !notificationsPending;
if (this._summaryState == State.HIDDEN) {
if (notificationsDone && this._summaryNeedsToBeShown)
this._showSummary(true);
else if (!notificationsVisible && summarySummoned)
this._showSummary(false);
} else if (this._summaryState == State.SHOWN) {
if (!summaryPinned)
this._hideSummary();
}
// Tray itself
let trayIsVisible = (this._trayState == State.SHOWING ||
this._trayState == State.SHOWN);
let trayShouldBeVisible = (!notificationsDone ||
this._summaryState == State.SHOWING ||
this._summaryState == State.SHOWN);
if (!trayIsVisible && trayShouldBeVisible)
this._showTray();
else if (trayIsVisible && !trayShouldBeVisible)
this._hideTray();
},
_tween: function(actor, statevar, value, params) {
let onComplete = params.onComplete;
let onCompleteScope = params.onCompleteScope;
let onCompleteParams = params.onCompleteParams;
params.onComplete = this._tweenComplete;
params.onCompleteScope = this;
params.onCompleteParams = [statevar, value, onComplete, onCompleteScope, onCompleteParams];
Tweener.addTween(actor, params);
let valuing = (value == State.SHOWN) ? State.SHOWING : State.HIDING;
this[statevar] = valuing;
},
_tweenComplete: function(statevar, value, onComplete, onCompleteScope, onCompleteParams) {
this[statevar] = value;
if (onComplete)
onComplete.apply(onCompleteScope, onCompleteParams);
this._updateState();
},
_showTray: function() {
let primary = global.get_primary_monitor();
this._tween(this.actor, "_trayState", State.SHOWN,
{ y: primary.y + primary.height - this.actor.height,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
},
_hideTray: function() {
let primary = global.get_primary_monitor();
this._tween(this.actor, "_trayState", State.HIDDEN,
{ y: primary.y + primary.height - 1,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
},
_showNotification: function() {
this._notification = this._notificationQueue.shift();
this._notificationBin.child = this._notification.actor;
this._notificationBin.opacity = 0;
this._notificationBin.y = this.actor.height;
this._notificationBin.show();
this._tween(this._notificationBin, "_notificationState", State.SHOWN,
{ y: 0,
opacity: 255,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._showNotificationCompleted,
onCompleteScope: this
});
},
_showNotificationCompleted: function() {
this._notificationTimeoutId =
Mainloop.timeout_add(NOTIFICATION_TIMEOUT * 1000,
Lang.bind(this, this._notificationTimeout));
},
_notificationTimeout: function() {
this._notificationTimeoutId = 0;
this._updateState();
return false;
},
_hideNotification: function() {
this._notificationRemoved = false;
this._notification.popIn();
this._tween(this._notificationBin, "_notificationState", State.HIDDEN,
{ y: this.actor.height,
opacity: 0,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._hideNotificationCompleted,
onCompleteScope: this
});
},
_hideNotificationCompleted: function() {
this._notificationBin.hide();
this._notificationBin.child = null;
this._notification = null;
},
_expandNotification: function() {
if (this._notification && this._notification.popOut()) {
this._tween(this._notificationBin, "_notificationState", State.SHOWN,
{ y: this.actor.height - this._notificationBin.height,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
}
},
_showSummary: function(withTimeout) {
let primary = global.get_primary_monitor();
this._summaryBin.opacity = 0;
this._summaryBin.y = this.actor.height;
this._tween(this._summaryBin, "_summaryState", State.SHOWN,
{ y: 0,
opacity: 255,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._showSummaryCompleted,
onCompleteScope: this,
onCompleteParams: [withTimeout]
});
},
_showSummaryCompleted: function(withTimeout) {
this._summaryNeedsToBeShown = false;
if (withTimeout) {
this._summaryTimeoutId =
Mainloop.timeout_add(SUMMARY_TIMEOUT * 1000,
Lang.bind(this, this._summaryTimeout));
}
},
_summaryTimeout: function() {
this._summaryTimeoutId = 0;
this._updateState();
return false;
},
_hideSummary: function() {
this._tween(this._summaryBin, "_summaryState", State.HIDDEN,
{ opacity: 0,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this._summaryNeedsToBeShown = false;
}
};

367
js/ui/notificationDaemon.js Normal file
View File

@ -0,0 +1,367 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
const EMPATHY = 'Empathy';
let nextNotificationId = 1;
// Should really be defined in dbus.js
const BusIface = {
name: 'org.freedesktop.DBus',
methods: [{ name: 'GetConnectionUnixProcessID',
inSignature: 's',
outSignature: 'i' }]
}
const Bus = function () {
this._init();
}
Bus.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
}
DBus.proxifyPrototype(Bus.prototype, BusIface);
const NotificationDaemonIface = {
name: 'org.freedesktop.Notifications',
methods: [{ name: 'Notify',
inSignature: 'susssasa{sv}i',
outSignature: 'u'
},
{ name: 'CloseNotification',
inSignature: 'u',
outSignature: ''
},
{ name: 'GetCapabilities',
inSignature: '',
outSignature: 'as'
},
{ name: 'GetServerInformation',
inSignature: '',
outSignature: 'ssss'
}],
signals: [{ name: 'NotificationClosed',
inSignature: 'uu' },
{ name: 'ActionInvoked',
inSignature: 'us' }]
};
const NotificationClosedReason = {
EXPIRED: 1,
DISMISSED: 2,
APP_CLOSED: 3,
UNDEFINED: 4
};
const Urgency = {
LOW: 0,
NORMAL: 1,
CRITICAL: 2
};
const rewriteRules = {
'XChat': [
{ pattern: /^XChat: Private message from: (\S*) \(.*\)$/,
replacement: '&lt;$1&gt;' },
{ pattern: /^XChat: New public message from: (\S*) \((.*)\)$/,
replacement: '$2 &lt;$1&gt;' },
{ pattern: /^XChat: Highlighted message from: (\S*) \((.*)\)$/,
replacement: '$2 &lt;$1&gt;' }
]
};
function NotificationDaemon() {
this._init();
}
NotificationDaemon.prototype = {
_init: function() {
DBus.session.exportObject('/org/freedesktop/Notifications', this);
this._everAcquiredName = false;
DBus.session.acquire_name('org.freedesktop.Notifications',
// We pass MANY_INSTANCES so that if
// notification-daemon is running, we'll
// get queued behind it and then get the
// name after killing it below
DBus.MANY_INSTANCES,
Lang.bind(this, this._acquiredName),
Lang.bind(this, this._lostName));
this._currentNotifications = {};
},
_acquiredName: function() {
this._everAcquiredName = true;
},
_lostName: function() {
if (this._everAcquiredName)
log('Lost name org.freedesktop.Notifications!');
else if (GLib.getenv('GNOME_SHELL_NO_REPLACE'))
log('Failed to acquire org.freedesktop.Notifications');
else {
log('Failed to acquire org.freedesktop.Notifications; trying again');
// kill the notification-daemon. pkill is more portable
// than killall, but on Linux at least it won't match if
// you pass more than 15 characters of the process name...
// However, if you use the "-f" flag to match the entire
// command line, it will work, but we have to be careful
// in that case that we don't match "gedit
// notification-daemon.c" or whatever...
let p = new Shell.Process({ args: ['pkill', '-f',
'^([^ ]*/)?(notification-daemon|notify-osd)$']});
p.run();
}
},
_sourceId: function(id) {
return 'source-' + id;
},
Notify: function(appName, replacesId, icon, summary, body,
actions, hints, timeout) {
let notification, id;
// We associate each application with a source and set the source id to be based on
// the appName. We support application updates by creating a new Notification object
// only if replacesId was not specified or if we no longer have the notification with
// the specified replacesId.
//
// We are planning to add Empathy-specific features in the message tray, but in the
// meantime we handle Empathy notifications received through the notification daemon
// differently from other notifications.
// 1) We display different people sending messages as different sources. So we use
// notification id instead of the appName when creating id for the source.
// 2) We queue notification with different messages to show them one after another,
// rather than replace the notification on the spot. So we create a new Notification
// object each time, disregarding the fact that we might already have another
// notification with the same replacesId.
// Empathy uses replacesId for all the notifications from the same window until the
// notification with that id is dismissed. Notifications from different people in
// different tabs have the same replacesId. So while being closer to the eventual design,
// our special-handling of Empathy notifications is somewhat buggy. The user might end up
// with multiple icons for the same person if the user dismisses the window for that person
// (which doesn't result in removing the icon) or the user might not get the icon for
// the person after a new notification in one of the tabs of the chat window for which
// another person's icon is already displayed.
let isEmpathy = appName == EMPATHY;
if (replacesId != 0) {
id = replacesId;
if (!isEmpathy)
notification = this._currentNotifications[id];
} else {
id = nextNotificationId++;
}
let sourceId = this._sourceId(isEmpathy ? id : appName);
let source = Main.messageTray.getSource(sourceId);
// Source may be null if we have never received a notification from
// this app or if all notifications from this app have been acknowledged.
if (source == null) {
source = new Source(sourceId, icon, hints);
Main.messageTray.add(source);
source.connect('clicked', Lang.bind(this,
function() {
source.destroy();
}));
let sender = DBus.getCurrentMessageContext().sender;
let busProxy = new Bus();
busProxy.GetConnectionUnixProcessIDRemote(sender, function (result, excp) {
let app = Shell.WindowTracker.get_default().get_app_from_pid(result);
source.setApp(app);
});
} else {
source.update(icon, hints);
}
summary = GLib.markup_escape_text(summary, -1);
let rewrites = rewriteRules[appName];
if (rewrites) {
for (let i = 0; i < rewrites.length; i++) {
let rule = rewrites[i];
if (summary.search(rule.pattern) != -1)
summary = summary.replace(rule.pattern, rule.replacement);
}
}
if (notification == null) {
notification = new MessageTray.Notification(id, source, summary, body, true);
// This will result in us keeping only the latest Empathy notification with the given
// id in this._currentNotifications, which will only affect not being able to close all
// the Empathy notifications with a given id in CloseNotification(). Since this not a
// a likely scenario and this special-casing of Empathy in the notification daemon is
// temporary, it doesn't seem worthwhile to change this._currentNotifications to
// {id, [array of notifications]} just for that case.
this._currentNotifications[id] = notification;
notification.connect('dismissed', Lang.bind(this,
function(n) {
n.destroy();
this._emitNotificationClosed(n.id, NotificationClosedReason.DISMISSED);
}));
} else {
// passing in true as the last parameter will clear out extra actors,
// such as actions
notification.update(summary, body, true);
}
if (actions.length) {
for (let i = 0; i < actions.length - 1; i += 2)
notification.addAction(actions[i], actions[i + 1]);
notification.connect('action-invoked', Lang.bind(this, this._actionInvoked, source, id));
}
source.notify(notification);
return id;
},
CloseNotification: function(id) {
let notification = this._currentNotifications[id];
if (notification)
notification.destroy();
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
},
GetCapabilities: function() {
return [
'actions',
'body',
// 'body-hyperlinks',
// 'body-images',
'body-markup',
// 'icon-multi',
'icon-static'
// 'sound',
];
},
GetServerInformation: function() {
return [
'GNOME Shell',
'GNOME',
'0.1', // FIXME, get this from somewhere
'1.0'
];
},
_actionInvoked: function(notification, action, source, id) {
this._emitActionInvoked(id, action);
source.destroy();
},
_emitNotificationClosed: function(id, reason) {
delete this._currentNotifications[id];
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'NotificationClosed', 'uu',
[id, reason]);
},
_emitActionInvoked: function(id, action) {
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'ActionInvoked', 'us',
[id, action]);
}
};
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
function Source(sourceId, icon, hints) {
this._init(sourceId, icon, hints);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(sourceId, icon, hints) {
MessageTray.Source.prototype._init.call(this, sourceId);
this.update(icon, hints);
},
update: function(icon, hints) {
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
this._icon = icon;
this._iconData = hints.icon_data;
this._urgency = hints.urgency;
this.app = null;
this._openAppRequested = false;
},
createIcon: function(size) {
let textureCache = Shell.TextureCache.get_default();
if (this._icon) {
if (this._icon.substr(0, 7) == 'file://')
return textureCache.load_uri_async(this._icon, size, size);
else if (this._icon[0] == '/') {
let uri = GLib.filename_to_uri(this._icon, null);
return textureCache.load_uri_async(uri, size, size);
} else
return textureCache.load_icon_name(this._icon, size);
} else if (this._iconData) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = this._iconData;
return textureCache.load_from_raw(data, data.length, hasAlpha,
width, height, rowStride, size);
} else {
let stockIcon;
switch (this._urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'gtk-dialog-info';
break;
case Urgency.CRITICAL:
stockIcon = 'gtk-dialog-error';
break;
}
return textureCache.load_icon_name(stockIcon, size);
}
},
clicked: function() {
this.openApp();
MessageTray.Source.prototype.clicked.call(this);
},
setApp: function(app) {
this.app = app;
if (this._openAppRequested)
this.openApp();
if (app.get_name() == EMPATHY)
this.handleReplacing = false;
},
openApp: function() {
if (this.app == null) {
this._openAppRequested = true;
return;
}
let windows = this.app.get_windows();
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.activateWindow(mostRecentWindow);
}
this._openAppRequested = false;
}
};

View File

@ -8,19 +8,18 @@ const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay;
const GenericDisplay = imports.ui.genericDisplay;
const Link = imports.ui.link;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Dash = imports.ui.dash;
const Tweener = imports.ui.tweener;
const Workspaces = imports.ui.workspaces;
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
const WorkspacesView = imports.ui.workspacesView;
// Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25;
@ -39,6 +38,10 @@ const ANIMATION_TIME = 0.25;
// will take up the remaining sections of the display.
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
// A common netbook resolution is 1024x600, which trips the widescreen
// ratio. However that leaves way too few pixels for the dash. So
// just treat this as a regular screen.
const WIDE_SCREEN_MINIMUM_HEIGHT = 768;
const COLUMNS_REGULAR_SCREEN = 4;
const ROWS_REGULAR_SCREEN = 8;
@ -70,10 +73,117 @@ const SHADOW_WIDTH = 6;
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
const INFO_BAR_HIDE_TIMEOUT = 30;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
let addRemoveButtonSize = null;
function InfoBar() {
this._init();
}
InfoBar.prototype = {
_init: function() {
this.actor = new St.Bin({ style_class: 'info-bar-panel',
x_fill: true,
y_fill: false });
this._label = new St.Label();
this._undo = new St.Button({ label: _("Undo"),
style_class: 'info-bar-link-button' });
let bin = new St.Bin({ x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.actor.set_child(bin);
let box = new St.BoxLayout({ style_class: 'info-bar' });
bin.set_child(box);
this._timeoutId = 0;
box.add(this._label, {'y-fill' : false, 'y-align' : St.Align.MIDDLE});
box.add(this._undo);
this.actor.set_opacity(0);
this._undoCallback = null;
this._undo.connect('clicked', Lang.bind(this, this._onUndoClicked));
this._overviewWasHidden = false;
this._hidingOverviewId = 0;
},
_onUndoClicked: function() {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
if (this._undoCallback)
this._undoCallback();
this.actor.set_opacity(0);
this._undoCallback = null;
},
_hideDone: function() {
this._undoCallback = null;
},
_hide: function() {
this._overviewWasHidden = false;
Tweener.addTween(this.actor,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onCompleteScope: this
});
},
_onTimeout: function() {
this._timeoutId = 0;
if (this._overviewWasHidden)
this._hide();
return false;
},
_onOverviewHiding: function() {
if (this._timeoutId == 0)
this._hide();
else
this._overviewWasHidden = true;
},
setMessage: function(text, undoCallback) {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
if (this._hidingOverviewId == 0) {
// Set here, because when constructor is called, overview is null.
if (!Main.overview)
return;
// We don't actually use the ID, it's just a way of tracking whether we've hooked up the signal
this._hidingOverviewId = Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
}
this._timeout = false;
this._overviewWasHidden = false;
this._label.text = text;
Tweener.addTween(this.actor,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME
});
this._timeoutId = Mainloop.timeout_add_seconds(INFO_BAR_HIDE_TIMEOUT, Lang.bind(this, this._onTimeout));
this._undoCallback = undoCallback;
if (undoCallback)
this._undo.show();
else
this._undo.hide();
}
};
function Overview() {
this._init();
@ -81,9 +191,15 @@ function Overview() {
Overview.prototype = {
_init : function() {
this._group = new Clutter.Group();
this._group = new St.BoxLayout({ style_class: 'overview' });
this._group._delegate = this;
this.infoBar = new InfoBar();
this._group.add_actor(this.infoBar.actor);
this._workspacesViewSwitch = new WorkspacesView.WorkspacesViewSwitch();
this._workspacesViewSwitch.connect('view-changed', Lang.bind(this, this._onViewChanged));
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
@ -107,7 +223,7 @@ Overview.prototype = {
this._group.add_actor(this._transparentBackground);
// Background color for the Overview
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERVIEW_COLOR });
this._backOver = new St.Label();
this._group.add_actor(this._backOver);
this._group.hide();
@ -118,9 +234,7 @@ Overview.prototype = {
this._group.add_actor(this._dash.actor);
// Container to hold popup pane chrome.
this._paneContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 6
});
this._paneContainer = new St.BoxLayout({ style_class: 'overview-pane' });
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
// inside the notify::visible handler on panes.
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
@ -130,78 +244,127 @@ Overview.prototype = {
this._group.add_actor(this._paneContainer);
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._paneContainer.hide();
this._coverPane.lower_bottom();
this._workspaces = null;
},
_createControlsBar: function() {
this._workspacesBar = new St.BoxLayout({ 'pack-start': true,
style_class: 'workspaces-bar' });
this._workspacesBar.move_by(this._workspacesBarX, this._workspacesBarY);
let controlsBar = this._workspacesViewSwitch.createControlsBar();
let bar = this._workspaces.createControllerBar();
this._workspacesBar.add(bar, { expand: true, 'x-fill': true, 'y-fill': true,
y_align: St.Align.MIDDLE, x_align: St.Align.START });
this._workspacesBar.add(controlsBar, {x_align: St.Align.END});
this._workspacesBar.width = this._workspacesBarWidth;
this._group.add_actor(this._workspacesBar);
this._workspacesBar.raise(this._workspaces.actor);
},
_onViewChanged: function() {
if (!this.visible)
return;
//Remove old worspacesView
this._group.remove_actor(this._workspacesBar);
this._workspaces.hide();
this._group.remove_actor(this._workspaces.actor);
this._workspaces.destroy();
this._workspacesBar.destroy();
this._workspaces = this._workspacesViewSwitch.createCurrentWorkspaceView(this._workspacesWidth, this._workspacesHeight,
this._workspacesX, this._workspacesY, false);
//Show new workspacesView
this._group.add_actor(this._workspaces.actor);
this._dash.actor.raise(this._workspaces.actor);
this._createControlsBar();
// Set new position and scale to workspaces.
this.emit('showing');
},
_recalculateGridSizes: function () {
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
let primary = global.get_primary_monitor();
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
(primary.height >= WIDE_SCREEN_MINIMUM_HEIGHT);
// We divide the screen into an imaginary grid which helps us determine the layout of
// different visual components.
if (wideScreen) {
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_WIDE_SCREEN);
displayGridRowHeight = Math.floor(primary.height / ROWS_WIDE_SCREEN);
} else {
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_REGULAR_SCREEN);
displayGridRowHeight = Math.floor(primary.height / ROWS_REGULAR_SCREEN);
}
},
relayout: function () {
let screenHeight = global.screen_height;
let screenWidth = global.screen_width;
let primary = global.get_primary_monitor();
this._recalculateGridSizes();
this._group.set_position(primary.x, primary.y);
let contentY = Panel.PANEL_HEIGHT;
let contentHeight = screenHeight - contentY;
let contentHeight = primary.height - contentY;
this._coverPane.set_position(0, contentY);
this._coverPane.set_size(screenWidth, contentHeight);
this._coverPane.set_size(primary.width, contentHeight);
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
- WORKSPACE_GRID_PADDING * 2;
// We scale the vertical padding by (screenHeight / screenWidth)
// We scale the vertical padding by (primary.height / primary.width)
// so that the workspace preserves its aspect ratio.
this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
- WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
this._workspacesHeight = Math.floor(displayGridRowHeight * workspaceRowsUsed
- WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2);
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width));
this._dash.actor.set_position(0, contentY);
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
this._dash.searchArea.height = this._workspacesY - contentY;
this._dash.sectionArea.height = this._workspacesHeight;
this._dash.searchResults.actor.height = this._workspacesHeight;
this.infoBar.actor.set_position(displayGridColumnWidth, Panel.PANEL_HEIGHT);
this.infoBar.actor.set_size(primary.width - displayGridColumnWidth, this._workspacesY - Panel.PANEL_HEIGHT);
this.infoBar.actor.raise_top();
// place the 'Add Workspace' button in the bottom row of the grid
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
this._workspacesBarX = this._workspacesX;
this._workspacesBarWidth = primary.width - this._workspacesBarX - WORKSPACE_GRID_PADDING;
this._workspacesBarY = primary.height - displayGridRowHeight;
this._backOver.set_position(0, contentY);
this._backOver.set_size(global.screen_width, contentHeight);
// The parent (this._group) is positioned at the top left of the primary monitor
// while this._backOver occupies the entire screen.
this._backOver.set_position(- primary.x, - primary.y);
this._backOver.set_size(global.screen_width, global.screen_height);
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
contentY);
this._workspacesY);
// Dynamic width
this._paneContainer.height = contentHeight;
this._paneContainer.height = this._workspacesHeight;
this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
this._transparentBackground.set_size(global.screen_width - this._paneContainer.x,
this._transparentBackground.set_size(primary.width - this._paneContainer.x,
this._paneContainer.height);
if (this._activeDisplayPane != null)
this._activeDisplayPane.actor.width = displayGridColumnWidth * 2;
},
addPane: function (pane) {
this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
this._paneContainer.add(pane.actor, { expand: true, y_fill: false, y_align: St.Align.START });
// When a pane is displayed, we raise the transparent background to the top
// and connect to button-release-event on it, then raise the pane above that.
// The idea here is that clicking anywhere outside the pane should close it.
@ -209,16 +372,17 @@ Overview.prototype = {
let backgroundEventId = null;
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (isOpen) {
pane.actor.width = displayGridColumnWidth * 2;
this._activeDisplayPane = pane;
this._transparentBackground.raise_top();
this._paneContainer.raise_top();
this._paneContainer.show();
if (backgroundEventId != null)
this._transparentBackground.disconnect(backgroundEventId);
backgroundEventId = this._transparentBackground.connect('button-release-event', Lang.bind(this, function () {
this._activeDisplayPane.close();
return true;
}));
this._workspaces.actor.opacity = 64;
} else if (pane == this._activeDisplayPane) {
this._activeDisplayPane = null;
if (backgroundEventId != null) {
@ -226,7 +390,8 @@ Overview.prototype = {
backgroundEventId = null;
}
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._paneContainer.hide();
this._workspaces.actor.opacity = 255;
}
}));
},
@ -238,7 +403,7 @@ Overview.prototype = {
// This allows the user to place the item on any workspace.
handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem
|| source instanceof AppDisplay.BaseWellItem) {
|| source instanceof AppDisplay.AppIcon) {
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
return true;
@ -277,7 +442,8 @@ Overview.prototype = {
show : function() {
if (this.visible)
return;
Main.pushModal(this._dash.actor);
if (!Main.pushModal(this._dash.actor))
return;
this.visible = true;
this.animationInProgress = true;
@ -285,8 +451,8 @@ Overview.prototype = {
this._dash.show();
/* TODO: make this stuff dynamic */
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
this._workspacesX, this._workspacesY);
this._workspaces = this._workspacesViewSwitch.createCurrentWorkspaceView(this._workspacesWidth, this._workspacesHeight,
this._workspacesX, this._workspacesY, true);
this._group.add_actor(this._workspaces.actor);
// The workspaces actor is as big as the screen, so we have to raise the dash above it
@ -294,11 +460,7 @@ Overview.prototype = {
// be as big as the screen.
this._dash.actor.raise(this._workspaces.actor);
// Create (+) button
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
this._group.add_actor(this._addButton.actor);
this._addButton.actor.raise(this._workspaces.actor);
this._createControlsBar();
// All the the actors in the window group are completely obscured,
// hiding the group holding them while the Overview is displayed greatly
@ -316,9 +478,10 @@ Overview.prototype = {
// The opposite transition is used in hide().
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
[this._group.x, this._group.y] = this.getZoomedInPosition();
let primary = global.get_primary_monitor();
Tweener.addTween(this._group,
{ x: 0,
y: 0,
{ x: primary.x,
y: primary.y,
scaleX: 1,
scaleY: 1,
transition: 'easeOutQuad',
@ -349,6 +512,9 @@ Overview.prototype = {
this._activeDisplayPane.close();
this._workspaces.hide();
this._workspacesBar.destroy();
this._workspacesBar = null;
// Create a zoom in effect by transforming the Overview group so that
// the active workspace fills up the whole screen. The opposite
// transition is used in show().
@ -395,20 +561,6 @@ Overview.prototype = {
return this._workspaces;
},
/**
* activateWindow:
* @metaWindow: A #MetaWindow
* @time: Event timestamp integer
*
* Make the given MetaWindow be the focus window, switching
* to the workspace it's on if necessary. This function
* should only be used when the Overview is currently active;
* outside of that, use the relevant methods on MetaDisplay.
*/
activateWindow: function (metaWindow, time) {
this._workspaces.activateWindowFromOverview(metaWindow, time);
},
//// Private methods ////
_showDone: function() {
@ -430,7 +582,7 @@ Overview.prototype = {
this._dash.hide();
this._group.hide();
this.visible = false;
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
@ -438,43 +590,6 @@ Overview.prototype = {
Main.popModal(this._dash.actor);
this.emit('hidden');
},
_addNewWorkspace: function() {
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
},
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
this._addNewWorkspace();
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
}
};
Signals.addSignalMethods(Overview.prototype);
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
}
AddWorkspaceButton.prototype = {
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
this.actor = new Clutter.Group({ x: buttonX,
y: buttonY,
width: global.screen_width - buttonX,
height: global.screen_height - buttonY,
reactive: true });
this.actor._delegate = this;
this._acceptDropCallback = acceptDropCallback;
let plus = new Clutter.Texture({ x: 0,
y: 0,
width: buttonSize,
height: buttonSize });
plus.set_from_file(global.imagedir + 'add-workspace.svg');
this.actor.add_actor(plus);
},
// Draggable target interface
acceptDrop: function(source, actor, x, y, time) {
return this._acceptDropCallback(source, actor, x, y, time);
}
};

View File

@ -7,45 +7,23 @@ const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Tweener = imports.ui.tweener;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Button = imports.ui.button;
const AppDisplay = imports.ui.appDisplay;
const Calendar = imports.ui.calendar;
const Main = imports.ui.main;
const StatusMenu = imports.ui.statusMenu;
const PANEL_HEIGHT = 26;
const TRAY_HEIGHT = PANEL_HEIGHT - 1;
const DEFAULT_PADDING = 4;
const PANEL_ICON_SIZE = 24;
const BACKGROUND_TOP = new Clutter.Color();
BACKGROUND_TOP.from_pixel(0x161616ff);
const BACKGROUND_BOTTOM = new Clutter.Color();
BACKGROUND_BOTTOM.from_pixel(0x000000ff);
const PANEL_FOREGROUND_COLOR = new Clutter.Color();
PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
const SN_BACKGROUND_COLOR = new Clutter.Color();
SN_BACKGROUND_COLOR.from_pixel(0xffff00a0);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
// Don't make the mouse hover effect visible to the user for a menu feel.
const PANEL_BUTTON_COLOR = new Clutter.Color();
PANEL_BUTTON_COLOR.from_pixel(0x00000000);
// Lighten pressed buttons; darkening has no effect on a black background.
const PRESSED_BUTTON_BACKGROUND_COLOR = new Clutter.Color();
PRESSED_BUTTON_BACKGROUND_COLOR.from_pixel(0x324c6ffa);
const DEFAULT_FONT = 'Sans 16px';
const TRAY_PADDING = 0;
// See comments around _recomputeTraySize
const TRAY_SPACING = 14;
const TRAY_SPACING_MIN = 8;
@ -53,13 +31,115 @@ const TRAY_SPACING_MIN = 8;
// Used for the tray icon container with gtk pre-2.16, which doesn't
// fully support tray icon transparency
const TRAY_BACKGROUND_COLOR = new Clutter.Color();
TRAY_BACKGROUND_COLOR.from_pixel(0xefefefff);
TRAY_BACKGROUND_COLOR.from_pixel(0x0b0b0bff);
const TRAY_BORDER_COLOR = new Clutter.Color();
TRAY_BORDER_COLOR.from_pixel(0x00000033);
const TRAY_CORNER_RADIUS = 5;
const TRAY_BORDER_WIDTH = 0;
const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STANDARD_TRAY_ICON_ORDER = ['keyboard', 'volume', 'bluetooth', 'network', 'battery']
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'bluetooth-applet': 'bluetooth',
'gnome-volume-control-applet': 'volume',
'nm-applet': 'network',
'gnome-power-manager': 'battery'
};
function TextShadower() {
this._init();
}
TextShadower.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._label = new St.Label();
this.actor.add_actor(this._label);
for (let i = 0; i < 4; i++) {
let actor = new St.Label({ style_class: 'label-shadow' });
this.actor.add_actor(actor);
}
this._label.raise_top();
},
setText: function(text) {
let children = this.actor.get_children();
for (let i = 0; i < children.length; i++)
children[i].set_text(text);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [minWidth, natWidth] = this._label.get_preferred_width(forHeight);
alloc.min_size = minWidth;
alloc.natural_size = natWidth;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [minHeight, natHeight] = this._label.get_preferred_height(forWidth);
alloc.min_size = minHeight;
alloc.natural_size = natHeight;
},
_allocate: function(actor, box, flags) {
let children = this.actor.get_children();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [minChildWidth, minChildHeight, natChildWidth, natChildHeight] =
this._label.get_preferred_size();
let childWidth = Math.min(natChildWidth, availWidth);
let childHeight = Math.min(natChildHeight, availHeight);
for (let i = 0; i < children.length; i++) {
let child = children[i];
let childBox = new Clutter.ActorBox();
// The order of the labels here is arbitrary, except
// we know the "real" label is at the end because Clutter.Group
// sorts by Z order
switch (i) {
case 0: // top
childBox.x1 = 1;
childBox.y1 = 0;
break;
case 1: // right
childBox.x1 = 2;
childBox.y1 = 1;
break;
case 2: // bottom
childBox.x1 = 1;
childBox.y1 = 2;
break;
case 3: // left
childBox.x1 = 0;
childBox.y1 = 1;
break;
case 4: // center
childBox.x1 = 1;
childBox.y1 = 1;
break;
}
childBox.x2 = childBox.x1 + childWidth;
childBox.y2 = childBox.y1 + childHeight;
child.allocate(childBox, flags);
}
}
}
/**
* AppPanelMenu:
*
* This class manages the "application menu" component. It tracks the
* currently focused application. However, when an app is launched,
* this menu also handles startup notification for it. So when we
* have an active startup notification, we switch modes to display that.
*/
function AppPanelMenu() {
this._init();
}
@ -72,24 +152,15 @@ AppPanelMenu.prototype = {
this._activeSequence = null;
this._startupSequences = {};
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_PADDING,
y_align: Big.BoxAlignment.CENTER });
this._iconBox = new Big.Box({ width: PANEL_ICON_SIZE, height: PANEL_ICON_SIZE,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER });
this.actor.append(this._iconBox, Big.BoxPackFlags.NONE);
let labelBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
this._label = new Clutter.Text({ font_name: DEFAULT_FONT,
color: PANEL_FOREGROUND_COLOR,
text: "" });
labelBox.append(this._label, Big.BoxPackFlags.EXPAND);
this.actor.append(labelBox, Big.BoxPackFlags.NONE);
this.actor = new St.BoxLayout({ name: 'appMenu' });
this._iconBox = new Shell.Slicer({ name: 'appMenuIcon' });
this.actor.add(this._iconBox);
this._label = new TextShadower();
this.actor.add(this._label.actor, { expand: true, y_fill: true });
this.actor.connect('notify::allocation', Lang.bind(this, this._repositionLabel));
this._startupBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
this.actor.append(this._startupBox, Big.BoxPackFlags.NONE);
this._startupBox = new St.BoxLayout();
this.actor.add(this._startupBox);
Main.overview.connect('hiding', Lang.bind(this, function () {
this.actor.opacity = 255;
@ -98,34 +169,36 @@ AppPanelMenu.prototype = {
this.actor.opacity = 192;
}));
this._metaDisplay.connect('notify::focus-window', Lang.bind(this, this._sync));
let appMonitor = Shell.AppMonitor.get_default();
appMonitor.connect('startup-sequence-changed', Lang.bind(this, this._sync));
// For now just resync on application add/remove; this is mainly to handle
let tracker = Shell.WindowTracker.get_default();
tracker.connect('notify::focus-app', Lang.bind(this, this._sync));
tracker.connect('startup-sequence-changed', Lang.bind(this, this._sync));
// For now just resync on all running state changes; this is mainly to handle
// cases where the focused window's application changes without the focus
// changing. An example case is how we map Firefox based on the window
// title which is a dynamic property.
appMonitor.connect('app-added', Lang.bind(this, this._sync));
appMonitor.connect('app-removed', Lang.bind(this, this._sync));
tracker.connect('app-running-changed', Lang.bind(this, this._sync));
this._sync();
},
_sync: function() {
let appMonitor = Shell.AppMonitor.get_default();
_repositionLabel: function() {
this._label.actor.x = Math.floor(AppDisplay.APPICON_SIZE / 2);
let actorAlloc = this.actor.allocation;
let actorHeight = actorAlloc.y2 - actorAlloc.y1;
let labelAlloc = this._label.actor.allocation;
let labelHeight = labelAlloc.y2 - labelAlloc.y1;
this._label.actor.y = Math.floor((actorHeight - labelHeight) / 2);
this._label.actor.fixed_position_set = true;
},
let focusWindow = this._metaDisplay.get_focus_window();
let focusedApp;
if (focusWindow == null) {
focusedApp = null;
} else {
focusedApp = appMonitor.get_window_app(focusWindow);
}
_sync: function() {
let tracker = Shell.WindowTracker.get_default();
let focusedApp = tracker.focus_app;
let lastSequence = null;
if (focusedApp == null) {
let sequences = appMonitor.get_startup_sequences();
let sequences = tracker.get_startup_sequences();
if (sequences.length > 0)
lastSequence = sequences[sequences.length - 1];
}
@ -141,20 +214,27 @@ AppPanelMenu.prototype = {
this._focusedApp = focusedApp;
this._activeSequence = lastSequence;
this._iconBox.remove_all();
if (this._iconBox.child != null)
this._iconBox.child.destroy();
this._iconBox.hide();
this._label.text = '';
this._label.setText('');
let icon;
if (this._focusedApp != null) {
let icon = focusedApp.create_icon_texture(PANEL_ICON_SIZE);
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
this._iconBox.show();
this._label.text = focusedApp.get_name();
icon = this._focusedApp.create_icon_texture(AppDisplay.APPICON_SIZE);
this._label.setText(this._focusedApp.get_name());
} else if (this._activeSequence != null) {
let icon = this._activeSequence.create_icon(PANEL_ICON_SIZE);
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
this._iconBox.show();
this._label.text = this._activeSequence.get_name();
icon = this._activeSequence.create_icon(AppDisplay.APPICON_SIZE);
this._label.setText(this._activeSequence.get_name());
} else {
icon = null;
}
if (icon != null) {
let faded = Shell.fade_app_icon(icon); /* TODO consider caching */
this._iconBox.set_child(faded);
this._iconBox.show();
}
this._repositionLabel();
this.emit('changed');
}
@ -169,30 +249,17 @@ function Panel() {
Panel.prototype = {
_init : function() {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
});
let backgroundGradient = Shell.create_vertical_gradient(BACKGROUND_TOP,
BACKGROUND_BOTTOM);
this.actor.connect('notify::allocation', Lang.bind(this, function () {
let [width, height] = this.actor.get_size();
backgroundGradient.set_size(width, height);
}));
this.actor.add_actor(backgroundGradient);
this.actor = new St.BoxLayout({ name: 'panel' });
this.actor._delegate = this;
this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
spacing: DEFAULT_PADDING,
padding_right: DEFAULT_PADDING });
this._centerBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
padding_left: DEFAULT_PADDING });
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this._rightBox = new St.BoxLayout({ name: 'panelRight' });
/* This box container ensures that the centerBox is positioned in the *absolute*
* center, but can be pushed aside if necessary. */
this._boxContainer = new Shell.GenericContainer();
this.actor.append(this._boxContainer, Big.BoxPackFlags.EXPAND);
this.actor.add(this._boxContainer, { expand: true });
this._boxContainer.add_actor(this._leftBox);
this._boxContainer.add_actor(this._centerBox);
this._boxContainer.add_actor(this._rightBox);
@ -264,13 +331,16 @@ Panel.prototype = {
this._rightBox.allocate(childBox, flags);
}));
/* left side */
/* Button on the left side of the panel. */
/* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */
let label = new St.Label({ text: _("Activities") });
this.button = new St.Clickable({ name: 'panelActivities',
style_class: 'panel-button',
reactive: true });
this.button.set_child(label);
this.button.height = PANEL_HEIGHT;
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
this.button.actor.height = PANEL_HEIGHT;
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
this._leftBox.add(this.button);
// We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding
@ -278,16 +348,22 @@ Panel.prototype = {
// multiple times due to an accidental jitter.
this._hotCornerEntered = false;
this._hotCornerEnvirons = new Clutter.Rectangle({ width: 3,
this._hotCornerEnvirons = new Clutter.Rectangle({ x: 0,
y: 0,
width: 3,
height: 3,
opacity: 0,
reactive: true });
this._hotCorner = new Clutter.Rectangle({ width: 1,
this._hotCorner = new Clutter.Rectangle({ x: 0,
y: 0,
width: 1,
height: 1,
opacity: 0,
reactive: true });
this._hotCornerActivationTime = 0;
this._hotCornerEnvirons.connect('leave-event',
Lang.bind(this, this._onHotCornerEnvironsLeft));
// Clicking on the hot corner environs should result in the same bahavior
@ -305,29 +381,36 @@ Panel.prototype = {
this._hotCorner.connect('leave-event',
Lang.bind(this, this._onHotCornerLeft));
this._leftBox.append(this._hotCornerEnvirons, Big.BoxPackFlags.FIXED);
this._leftBox.append(this._hotCorner, Big.BoxPackFlags.FIXED);
this._leftBox.add(this._hotCornerEnvirons);
this._leftBox.add(this._hotCorner);
let appMenu = new AppPanelMenu();
this._leftBox.append(appMenu.actor, Big.BoxPackFlags.NONE);
this._leftBox.add(appMenu.actor);
/* center */
this._clock = new Clutter.Text({ font_name: DEFAULT_FONT,
color: PANEL_FOREGROUND_COLOR,
text: "" });
this._centerBox.append(this._clock, Big.BoxPackFlags.NONE);
let clockButton = new St.Button({ style_class: "panel-button",
toggle_mode: true,
x_fill: true,
y_fill: true });
this._centerBox.add(clockButton, { y_fill: false });
clockButton.connect('clicked', Lang.bind(this, this._toggleCalendar));
this._clock = new St.Label();
clockButton.set_child(this._clock);
this._clockButton = clockButton;
this._calendarPopup = null;
/* right */
// The tray icons live in trayBox within trayContainer.
// The trayBox is hidden when there are no tray icons.
let trayContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.START });
this._rightBox.append(trayContainer, Big.BoxPackFlags.NONE);
y_align: Big.BoxAlignment.CENTER });
this._rightBox.add(trayContainer);
let trayBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
height: TRAY_HEIGHT,
padding: TRAY_PADDING,
height: PANEL_ICON_SIZE,
spacing: TRAY_SPACING });
this._trayBox = trayBox;
@ -345,14 +428,7 @@ Panel.prototype = {
trayContainer.append(trayBox, Big.BoxPackFlags.NONE);
this._traymanager = new Shell.TrayManager({ bg_color: TRAY_BACKGROUND_COLOR });
this._traymanager.connect('tray-icon-added',
Lang.bind(this, function(o, icon) {
trayBox.append(icon, Big.BoxPackFlags.NONE);
// Make sure the trayBox is shown.
trayBox.show();
this._recomputeTraySize();
}));
this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._traymanager.connect('tray-icon-removed',
Lang.bind(this, function(o, icon) {
trayBox.remove_actor(icon);
@ -363,63 +439,60 @@ Panel.prototype = {
}));
this._traymanager.manage_stage(global.stage);
let statusbox = new Big.Box();
let statusmenu = this._statusmenu = new Shell.StatusMenu();
statusmenu.get_icon().hide();
statusmenu.get_name().fontName = DEFAULT_FONT;
statusmenu.get_name().color = PANEL_FOREGROUND_COLOR;
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
let statusbutton = new Button.Button(statusbox,
PANEL_BUTTON_COLOR,
PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR);
statusbutton.actor.height = PANEL_HEIGHT;
statusbutton.actor.connect('button-press-event', function (b, e) {
if (e.get_button() == 1 && e.get_click_count() == 1) {
statusmenu.toggle(e);
// The statusmenu might not pop up if it couldn't get a pointer grab
if (statusmenu.is_active())
statusbutton.actor.active = true;
return true;
} else {
return false;
}
let statusmenu = this._statusmenu = new StatusMenu.StatusMenu();
let statusbutton = new St.Clickable({ name: 'panelStatus',
style_class: 'panel-button',
reactive: true });
statusbutton.set_child(statusmenu.actor);
statusbutton.height = PANEL_HEIGHT;
statusbutton.connect('clicked', function (b, event) {
statusmenu.toggle(event);
// The statusmenu might not pop up if it couldn't get a pointer grab
if (statusmenu.isActive())
statusbutton.active = true;
return true;
});
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
this._rightBox.add(statusbutton);
// We get a deactivated event when the popup disappears
this._statusmenu.connect('deactivated', function (sm) {
statusbutton.actor.active = false;
statusbutton.active = false;
});
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
// to switch to.
this.button.actor.connect('button-press-event', function(b, e) {
if (e.get_button() == 1 && e.get_click_count() == 1) {
Main.overview.toggle();
this.button.connect('clicked', Lang.bind(this, function(b, event) {
if (!Main.overview.animationInProgress) {
this._maybeToggleOverviewOnClick();
return true;
} else {
return false;
}
});
}));
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
// and to be released when it is exited regardless of how it was triggered.
Main.overview.connect('showing', Lang.bind(this, function() {
this.button.actor.active = true;
this.button.active = true;
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
this.button.actor.active = false;
this.button.active = false;
}));
Main.chrome.addActor(this.actor);
Main.chrome.setVisibleInOverview(this.actor, true);
Main.chrome.addActor(this.actor, { visibleInOverview: true });
// Start the clock
this._updateClock();
},
hideCalendar: function() {
if (this._calendarPopup != null) {
this._clockButton.checked = false;
this._calendarPopup.actor.hide();
}
},
startupAnimation: function() {
this.actor.y = -this.actor.height;
Tweener.addTween(this.actor,
@ -429,6 +502,38 @@ Panel.prototype = {
});
},
_onTrayIconAdded: function(o, icon, wmClass) {
let role = STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass];
if (!role) {
// Unknown icons go first in undefined order
this._trayBox.prepend(icon, Big.BoxPackFlags.NONE);
} else {
icon._role = role;
// Figure out the index in our well-known order for this icon
let position = STANDARD_TRAY_ICON_ORDER.indexOf(role);
icon._rolePosition = position;
let children = this._trayBox.get_children();
let i;
// Walk children backwards, until we find one that isn't
// well-known, or one where we should follow
for (i = children.length - 1; i >= 0; i--) {
let rolePosition = children[i]._rolePosition;
if (!rolePosition || position > rolePosition) {
this._trayBox.insert_after(icon, children[i], Big.BoxPackFlags.NONE);
break;
}
}
if (i == -1) {
// If we didn't find a position, we must be first
this._trayBox.prepend(icon, Big.BoxPackFlags.NONE);
}
}
// Make sure the trayBox is shown.
this._trayBox.show();
this._recomputeTraySize();
},
// By default, tray icons have a spacing of TRAY_SPACING. However this
// starts to fail if we have too many as can sadly happen; just jump down
// to a spacing of 8 if we're over 6.
@ -448,16 +553,70 @@ Panel.prototype = {
displayDate.setMinutes(displayDate.getMinutes() + 1);
msecRemaining += 60000;
}
/* Translators: This is a time format. */
this._clock.set_text(displayDate.toLocaleFormat(_("%a %l:%M %p")));
/* If there is no am or pm, time format is 24h */
let isTime24h = displayDate.toLocaleFormat("x%p") == "x";
if (isTime24h) {
/* Translators: This is the time format used in 24-hour mode. */
this._clock.set_text(displayDate.toLocaleFormat(_("%a %R")));
} else {
/* Translators: This is a time format used for AM/PM. */
this._clock.set_text(displayDate.toLocaleFormat(_("%a %l:%M %p")));
}
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClock));
return false;
},
_toggleCalendar: function(clockButton) {
if (clockButton.checked) {
if (this._calendarPopup == null)
this._calendarPopup = new CalendarPopup();
this._calendarPopup.show();
} else {
this._calendarPopup.hide();
}
},
_addRipple : function(delay, time, startScale, startOpacity, finalScale, finalOpacity) {
// We draw a ripple by using a source image and animating it scaling
// outwards and fading away. We want the ripples to move linearly
// or it looks unrealistic, but if the opacity of the ripple goes
// linearly to zero it fades away too quickly, so we use Tweener's
// 'onUpdate' to give a non-linear curve to the fade-away and make
// it more visible in the middle section.
let [x, y] = this._hotCorner.get_transformed_position();
let ripple = new St.BoxLayout({ style_class: 'ripple-box',
opacity: 255 * Math.sqrt(startOpacity),
scale_x: startScale,
scale_y: startScale,
x: x,
y: y });
ripple._opacity = startOpacity;
Tweener.addTween(ripple, { _opacity: finalOpacity,
scale_x: finalScale,
scale_y: finalScale,
delay: delay,
time: time,
transition: 'linear',
onUpdate: function() { ripple.opacity = 255 * Math.sqrt(ripple._opacity); },
onComplete: function() { ripple.destroy(); } });
global.stage.add_actor(ripple);
},
_onHotCornerEntered : function() {
if (!this._hotCornerEntered) {
this._hotCornerEntered = true;
if (!Main.overview.animationInProgress) {
this._hotCornerActivationTime = Date.now() / 1000;
// Show three concentric ripples expanding outwards; the exact
// parameters were found by trial and error, so don't look
// for them to make perfect sense mathematically
// delay time scale opacity => scale opacity
this._addRipple(0.0, 0.83, 0.25, 1.0, 1.5, 0.0);
this._addRipple(0.05, 1.0, 0.0, 0.7, 1.25, 0.0);
this._addRipple(0.35, 1.0, 0.0, 0.3, 1, 0.0);
Main.overview.toggle();
}
}
@ -466,7 +625,7 @@ Panel.prototype = {
_onHotCornerClicked : function() {
if (!Main.overview.animationInProgress) {
Main.overview.toggle();
this._maybeToggleOverviewOnClick();
}
return false;
},
@ -483,5 +642,61 @@ Panel.prototype = {
this._hotCornerEntered = false;
}
return false;
},
// Toggles the overview unless this is the first click on the Activities button within the HOT_CORNER_ACTIVATION_TIMEOUT time
// of the hot corner being triggered. This check avoids opening and closing the overview if the user both triggered the hot corner
// and clicked the Activities button.
_maybeToggleOverviewOnClick: function() {
if (this._hotCornerActivationTime == 0 || Date.now() / 1000 - this._hotCornerActivationTime > HOT_CORNER_ACTIVATION_TIMEOUT)
Main.overview.toggle();
this._hotCornerActivationTime = 0;
}
};
function CalendarPopup() {
this._init();
}
CalendarPopup.prototype = {
_init: function() {
let panelActor = Main.panel.actor;
this.actor = new St.BoxLayout({ name: 'calendarPopup' });
this.calendar = new Calendar.Calendar();
this.actor.add(this.calendar.actor);
Main.chrome.addActor(this.actor, { visibleInOverview: true,
affectsStruts: false });
this.actor.y = (panelActor.y + panelActor.height - this.actor.height);
},
show: function() {
let panelActor = Main.panel.actor;
// Reset the calendar to today's date
this.calendar.setDate(new Date());
this.actor.x = Math.round(panelActor.x + (panelActor.width - this.actor.width) / 2);
this.actor.lower(panelActor);
this.actor.show();
Tweener.addTween(this.actor,
{ y: panelActor.y + panelActor.height,
time: 0.2,
transition: "easeOutQuad"
});
},
hide: function() {
let panelActor = Main.panel.actor;
Tweener.addTween(this.actor,
{ y: panelActor.y + panelActor.height - this.actor.height,
time: 0.2,
transition: "easeOutQuad",
onComplete: function() { this.actor.hide(); },
onCompleteScope: this
});
}
};

584
js/ui/placeDisplay.js Normal file
View File

@ -0,0 +1,584 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Search = imports.ui.search;
const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences';
const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir';
const PLACES_ICON_SIZE = 16;
/**
* Represents a place object, which is most normally a bookmark entry,
* a mount/volume, or a special place like the Home Folder, Computer, and Network.
*
* @name: String title
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
* @launch: A JavaScript callback to launch the entry
*/
function PlaceInfo(id, name, iconFactory, launch) {
this._init(id, name, iconFactory, launch);
}
PlaceInfo.prototype = {
_init: function(id, name, iconFactory, launch) {
this.id = id;
this.name = name;
this._lowerName = name.toLowerCase();
this.iconFactory = iconFactory;
this.launch = launch;
},
matchTerms: function(terms) {
let mtype = Search.MatchType.NONE;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
let idx = this._lowerName.indexOf(term);
if (idx == 0)
return Search.MatchType.PREFIX;
else if (idx > 0)
mtype = Search.MatchType.SUBSTRING;
}
return mtype;
},
isRemovable: function() {
return false;
}
}
function PlaceDeviceInfo(mount) {
this._init(mount);
}
PlaceDeviceInfo.prototype = {
__proto__: PlaceInfo.prototype,
_init: function(mount) {
this._mount = mount;
this.name = mount.get_name();
this._lowerName = this.name.toLowerCase();
this.id = "mount:" + mount.get_root().get_uri();
},
iconFactory: function(size) {
let icon = this._mount.get_icon();
return Shell.TextureCache.get_default().load_gicon(icon, size);
},
launch: function() {
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
global.create_app_launch_context());
},
isRemovable: function() {
return this._mount.can_unmount();
},
remove: function() {
if (!this.isRemovable())
return;
this._mount.unmount(0, null, Lang.bind(this, this._removeFinish), null);
},
_removeFinish: function(o, res, data) {
this._mount.unmount_finish(res);
}
}
function PlacesManager() {
this._init();
}
PlacesManager.prototype = {
_init: function() {
let gconf = Shell.GConf.get_default();
gconf.watch_directory(NAUTILUS_PREFS_DIR);
this._defaultPlaces = [];
this._mounts = [];
this._bookmarks = [];
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
let homeUri = homeFile.get_uri();
let homeLabel = Shell.util_get_label_for_uri (homeUri);
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
this._home = new PlaceInfo('special:home', homeLabel,
function(size) {
return Shell.TextureCache.get_default().load_gicon(homeIcon, size);
},
function() {
Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context());
});
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
let desktopFile = Gio.file_new_for_path (desktopPath);
let desktopUri = desktopFile.get_uri();
let desktopLabel = Shell.util_get_label_for_uri (desktopUri);
let desktopIcon = Shell.util_get_icon_for_uri (desktopUri);
this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel,
function(size) {
return Shell.TextureCache.get_default().load_gicon(desktopIcon, size);
},
function() {
Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context());
});
this._connect = new PlaceInfo('special:connect', _("Connect to..."),
function (size) {
return Shell.TextureCache.get_default().load_icon_name("applications-internet", size);
},
function () {
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
});
let networkApp = null;
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
} catch(e) {
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
} catch(e) {
log("Cannot create \"Network\" item, .desktop file not found or corrupt.");
}
}
if (networkApp != null) {
this._network = new PlaceInfo('special:network', networkApp.get_name(),
function(size) {
return networkApp.create_icon_texture(size);
},
function () {
networkApp.launch();
});
}
this._defaultPlaces.push(this._home);
this._desktopMenuIndex = this._defaultPlaces.length;
if (!this._isDesktopHome)
this._defaultPlaces.push(this._desktopMenu);
if (this._network)
this._defaultPlaces.push(this._network);
this._defaultPlaces.push(this._connect);
/*
* Show devices, code more or less ported from nautilus-places-sidebar.c
*/
this._volumeMonitor = Gio.VolumeMonitor.get();
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
this._updateDevices();
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), ".gtk-bookmarks"]);
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._bookmarkTimeoutId = 0;
monitor.connect('changed', Lang.bind(this, function () {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
}));
}));
this._reloadBookmarks();
gconf.connect('changed::' + DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
},
_updateDevices: function() {
this._mounts = [];
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for(let j = 0; j < volumes.length; j++) {
let mount = volumes[j].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
}
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
continue;
let mount = volumes[i].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
continue;
if(mounts[i].get_volume())
continue;
this._addMount(mounts[i]);
}
/* We emit two signals, one for a generic 'all places' update
* and the other for one specific to mounts. We do this because
* clients like PlaceDisplay may only care about places in general
* being updated while clients like DashPlaceDisplay care which
* specific type of place got updated.
*/
this.emit('mounts-updated');
this.emit('places-updated');
},
_reloadBookmarks: function() {
this._bookmarks = [];
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
return;
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
if (!success)
return;
let bookmarks = bookmarksContent.split('\n');
let bookmarksToLabel = {};
let bookmarksOrder = [];
for (let i = 0; i < bookmarks.length; i++) {
let bookmarkLine = bookmarks[i];
let components = bookmarkLine.split(' ');
let bookmark = components[0];
if (bookmark in bookmarksToLabel)
continue;
let label = null;
if (components.length > 1)
label = components.slice(1).join(' ');
bookmarksToLabel[bookmark] = label;
bookmarksOrder.push(bookmark);
}
for (let i = 0; i < bookmarksOrder.length; i++) {
let bookmark = bookmarksOrder[i];
let label = bookmarksToLabel[bookmark];
let file = Gio.file_new_for_uri(bookmark);
if (!file.query_exists(null))
continue;
if (label == null)
label = Shell.util_get_label_for_uri(bookmark);
if (label == null)
continue;
let icon = Shell.util_get_icon_for_uri(bookmark);
let item = new PlaceInfo('bookmark:' + bookmark, label,
function(size) {
return Shell.TextureCache.get_default().load_gicon(icon, size);
},
function() {
Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context());
});
this._bookmarks.push(item);
}
/* See comment in _updateDevices for explanation why there are two signals. */
this.emit('bookmarks-updated');
this.emit('places-updated');
},
_updateDesktopMenuVisibility: function() {
let gconf = Shell.GConf.get_default();
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
if (this._isDesktopHome)
this._removeById(this._defaultPlaces, "special:desktop");
else
this._defaultPlaces.splice(this._desktopMenuIndex, 0,
this._desktopMenu);
/* See comment in _updateDevices for explanation why there are two signals. */
this.emit('defaults-updated');
this.emit('places-updated');
},
_addMount: function(mount) {
let devItem = new PlaceDeviceInfo(mount);
this._mounts.push(devItem);
},
getAllPlaces: function () {
return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts());
},
getDefaultPlaces: function () {
return this._defaultPlaces;
},
getBookmarks: function () {
return this._bookmarks;
},
getMounts: function () {
return this._mounts;
},
_lookupIndexById: function(sourceArray, id) {
for (let i = 0; i < sourceArray.length; i++) {
let place = sourceArray[i];
if (place.id == id)
return i;
}
return -1;
},
lookupPlaceById: function(id) {
let colonIdx = id.indexOf(':');
let type = id.substring(0, colonIdx);
let sourceArray = null;
if (type == 'special')
sourceArray = this._defaultPlaces;
else if (type == 'mount')
sourceArray = this._mounts;
else if (type == 'bookmark')
sourceArray = this._bookmarks;
return sourceArray[this._lookupIndexById(sourceArray, id)];
},
_removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
}
};
Signals.addSignalMethods(PlacesManager.prototype);
/**
* An entry in the places menu.
* @info The corresponding PlaceInfo to populate this entry.
*/
function DashPlaceDisplayItem(info) {
this._init(info);
}
DashPlaceDisplayItem.prototype = {
_init: function(info) {
this.name = info.name;
this._info = info;
this._icon = info.iconFactory(PLACES_ICON_SIZE);
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4 });
let text = new St.Button({ style_class: 'places-item',
label: info.name,
x_align: St.Align.START });
text.connect('clicked', Lang.bind(this, this._onClicked));
let iconBox = new St.Bin({ child: this._icon, reactive: true });
iconBox.connect('button-release-event',
Lang.bind(this, this._onClicked));
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
this.actor.append(text, Big.BoxPackFlags.EXPAND);
if (info.isRemovable()) {
let removeIcon = Shell.TextureCache.get_default().load_icon_name ('media-eject', PLACES_ICON_SIZE);
let removeIconBox = new St.Button({ child: removeIcon,
reactive: true });
this.actor.append(removeIconBox, Big.BoxPackFlags.NONE);
removeIconBox.connect('clicked',
Lang.bind(this, function() {
this._info.remove();
}));
}
this.actor._delegate = this;
let draggable = DND.makeDraggable(this.actor);
},
_onClicked: function(b) {
this._info.launch();
Main.overview.hide();
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
return this._info.iconFactory(PLACES_ICON_SIZE);
},
//// Drag and drop methods ////
shellWorkspaceLaunch: function() {
this._info.launch();
}
};
function DashPlaceDisplay() {
this._init();
}
DashPlaceDisplay.prototype = {
_init: function() {
// Places is divided semi-arbitrarily into left and right; a grid would
// look better in that there would be an even number of items left+right,
// but it seems like we want some sort of differentiation between actions
// like "Connect to server..." and regular folders
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4 });
this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
this.actor.append(this._leftBox, Big.BoxPackFlags.EXPAND);
this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
this.actor.append(this._rightBox, Big.BoxPackFlags.EXPAND);
// Subdivide left into actions and devices
this._actionsBox = new St.BoxLayout({ style_class: 'places-actions',
vertical: true });
this._devBox = new St.BoxLayout({ style_class: 'places-actions',
name: 'placesDevices',
vertical: true });
this._dirsBox = new St.BoxLayout({ style_class: 'places-actions',
vertical: true });
this._leftBox.append(this._actionsBox, Big.BoxPackFlags.NONE);
this._leftBox.append(this._devBox, Big.BoxPackFlags.NONE);
this._rightBox.append(this._dirsBox, Big.BoxPackFlags.NONE);
Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults));
Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks));
Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts));
this._updateDefaults();
this._updateMounts();
this._updateBookmarks();
},
_updateDefaults: function() {
this._actionsBox.destroy_children();
let places = Main.placesManager.getDefaultPlaces();
for (let i = 0; i < places.length; i++)
this._actionsBox.add(new DashPlaceDisplayItem(places[i]).actor);
},
_updateMounts: function() {
this._devBox.destroy_children();
let places = Main.placesManager.getMounts();
for (let i = 0; i < places.length; i++)
this._devBox.add(new DashPlaceDisplayItem(places[i]).actor);
},
_updateBookmarks: function() {
this._dirsBox.destroy_children();
let places = Main.placesManager.getBookmarks();
for (let i = 0; i < places.length; i ++)
this._dirsBox.add(new DashPlaceDisplayItem(places[i]).actor);
}
};
Signals.addSignalMethods(DashPlaceDisplay.prototype);
function PlaceSearchProvider() {
this._init();
}
PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
},
getResultMeta: function(resultId) {
let placeInfo = Main.placesManager.lookupPlaceById(resultId);
if (!placeInfo)
return null;
return { 'id': resultId,
'name': placeInfo.name,
'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) };
},
activateResult: function(id) {
let placeInfo = Main.placesManager.lookupPlaceById(id);
placeInfo.launch();
},
_compareResultMeta: function (idA, idB) {
let infoA = Main.placesManager.lookupPlaceById(idA);
let infoB = Main.placesManager.lookupPlaceById(idB);
return infoA.name.localeCompare(infoB.name);
},
_searchPlaces: function(places, terms) {
let multipleResults = [];
let prefixResults = [];
let substringResults = [];
terms = terms.map(String.toLowerCase);
for (let i = 0; i < places.length; i++) {
let place = places[i];
let mtype = place.matchTerms(terms);
if (mtype == Search.MatchType.MULTIPLE)
multipleResults.push(place.id);
else if (mtype == Search.MatchType.PREFIX)
prefixResults.push(place.id);
else if (mtype == Search.MatchType.SUBSTRING)
substringResults.push(place.id);
}
multipleResults.sort(this._compareResultMeta);
prefixResults.sort(this._compareResultMeta);
substringResults.sort(this._compareResultMeta);
return multipleResults.concat(prefixResults.concat(substringResults));
},
getInitialResultSet: function(terms) {
let places = Main.placesManager.getAllPlaces();
return this._searchPlaces(places, terms);
},
getSubsearchResultSet: function(previousResults, terms) {
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
return this._searchPlaces(places, terms);
}
}

View File

@ -1,278 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const GenericDisplay = imports.ui.genericDisplay;
const PLACES_VSPACING = 8;
const PLACES_ICON_SIZE = 16;
/**
* An entry in the places menu.
* @name: String title
* @iconFactory: A JavaScript callback which will create an icon texture
* @onActivate: A JavaScript callback to launch the entry
*/
function PlaceDisplay(name, iconFactory, onActivate) {
this._init(name, iconFactory, onActivate);
}
PlaceDisplay.prototype = {
_init : function(name, iconFactory, onActivate) {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
reactive: true,
spacing: 4 });
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
onActivate(this);
Main.overview.hide();
}));
let text = new Clutter.Text({ font_name: "Sans 14px",
ellipsize: Pango.EllipsizeMode.END,
color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
text: name });
let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
this._icon = iconFactory();
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
this.actor.append(text, Big.BoxPackFlags.EXPAND);
this._iconFactory = iconFactory;
this._onActivate = onActivate;
this.actor._delegate = this;
let draggable = DND.makeDraggable(this.actor);
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
return this._iconFactory();
},
//// Drag and drop methods ////
shellWorkspaceLaunch : function() {
this._onActivate();
}
};
Signals.addSignalMethods(PlaceDisplay.prototype);
function Places() {
this._init();
}
Places.prototype = {
_init : function() {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4 });
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
let homeUri = homeFile.get_uri();
let homeLabel = Shell.util_get_label_for_uri (homeUri);
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
let home = new PlaceDisplay(homeLabel,
function() {
return Shell.TextureCache.get_default().load_gicon(homeIcon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(homeUri, Main.createAppLaunchContext());
});
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
/*
* Show devices, code more or less ported from nautilus-places-sidebar.c
*/
this._menuBox.append(this._devBox, Big.BoxPackFlags.NONE);
this._volumeMonitor = Gio.VolumeMonitor.get();
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
this._updateDevices();
let networkApp = null;
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
} catch(e) {
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
} catch(e) {
log("Cannot create \"Network\" item, .desktop file not found or corrupt.");
}
}
if (networkApp != null) {
let network = new PlaceDisplay(networkApp.get_name(),
function() {
return networkApp.create_icon_texture(PLACES_ICON_SIZE);
},
function () {
networkApp.launch();
});
this._menuBox.append(network.actor, Big.BoxPackFlags.NONE);
}
let connect = new PlaceDisplay('Connect to...',
function () {
return Shell.TextureCache.get_default().load_icon_name("applications-internet", PLACES_ICON_SIZE);
},
function () {
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
});
this._menuBox.append(connect.actor, Big.BoxPackFlags.NONE);
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), ".gtk-bookmarks"]);
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._bookmarkTimeoutId = 0;
monitor.connect('changed', Lang.bind(this, function () {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
}));
}));
this._reloadBookmarks();
},
_reloadBookmarks: function() {
this._dirsBox.remove_all();
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
return;
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
if (!success)
return;
let bookmarks = bookmarksContent.split('\n');
let bookmarksToLabel = {};
let bookmarksOrder = [];
for (let i = 0; i < bookmarks.length; i++) {
let bookmarkLine = bookmarks[i];
let components = bookmarkLine.split(' ');
let bookmark = components[0];
if (bookmark in bookmarksToLabel)
continue;
let label = null;
if (components.length > 1)
label = components.slice(1).join(' ');
bookmarksToLabel[bookmark] = label;
bookmarksOrder.push(bookmark);
}
for (let i = 0; i < bookmarksOrder.length; i++) {
let bookmark = bookmarksOrder[i];
let label = bookmarksToLabel[bookmark];
let file = Gio.file_new_for_uri(bookmark);
if (!file.query_exists(null))
continue;
if (label == null)
label = Shell.util_get_label_for_uri(bookmark);
if (label == null)
continue;
let icon = Shell.util_get_icon_for_uri(bookmark);
let item = new PlaceDisplay(label,
function() {
return Shell.TextureCache.get_default().load_gicon(icon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(bookmark, Main.createAppLaunchContext());
});
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
}
},
_updateDevices: function() {
this._devBox.remove_all();
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for(let j = 0; j < volumes.length; j++) {
let mount = volumes[j].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
}
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
continue;
let mount = volumes[i].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
continue;
if(mounts[i].get_volume())
continue;
this._addMount(mounts[i]);
}
},
_addMount: function(mount) {
let mountLabel = mount.get_name();
let mountIcon = mount.get_icon();
let root = mount.get_root();
let mountUri = root.get_uri();
let devItem = new PlaceDisplay(mountLabel,
function() {
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
});
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
}
};
Signals.addSignalMethods(Places.prototype);

View File

@ -2,6 +2,7 @@
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
@ -11,11 +12,9 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const OVERLAY_COLOR = new Clutter.Color();
OVERLAY_COLOR.from_pixel(0x00000044);
const BOX_BACKGROUND_COLOR = new Clutter.Color();
BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
@ -26,6 +25,154 @@ const DIALOG_WIDTH = 320;
const DIALOG_PADDING = 6;
const ICON_SIZE = 24;
const ICON_BOX_SIZE = 36;
const MAX_FILE_DELETED_BEFORE_INVALID = 10;
function CommandCompleter() {
this._init();
}
CommandCompleter.prototype = {
_init : function() {
this._changedCount = 0;
this._paths = GLib.getenv('PATH').split(':');
this._valid = false;
this._updateInProgress = false;
this._childs = new Array(this._paths.length);
this._monitors = new Array(this._paths.length);
for (let i = 0; i < this._paths.length; i++) {
this._childs[i] = [];
let file = Gio.file_new_for_path(this._paths[i]);
let info;
try {
info = file.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
// FIXME catchall
this._paths[i] = null;
continue;
}
if (info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_STANDARD_TYPE) != Gio.FileType.DIRECTORY)
continue;
this._paths[i] = file.get_path();
this._monitors[i] = file.monitor_directory(Gio.FileMonitorFlags.NONE, null);
if (this._monitors[i] != null) {
this._monitors[i].connect("changed", Lang.bind(this, this._onChanged));
}
}
this._paths = this._paths.filter(function(a) {
return a != null;
});
this._update(0);
},
_onGetEnumerateComplete : function(obj, res) {
this._enumerator = obj.enumerate_children_finish(res);
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete), null);
},
_onNextFileComplete : function(obj, res) {
let files = obj.next_files_finish(res);
for (let i = 0; i < files.length; i++) {
this._childs[this._i].push(files[i].get_name());
}
if (files.length) {
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete), null);
} else {
this._enumerator.close(null);
this._enumerator = null;
this._update(this._i + 1);
}
},
update : function() {
if (this._valid)
return;
this._update(0);
},
_update : function(i) {
if (i == 0 && this._updateInProgress)
return;
this._updateInProgress = true;
this._changedCount = 0;
this._i = i;
if (i >= this._paths.length) {
this._valid = true;
this._updateInProgress = false;
return;
}
let file = Gio.file_new_for_path(this._paths[i]);
this._childs[this._i] = [];
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onGetEnumerateComplete), null);
},
_onChanged : function(m, f, of, type) {
if (!this._valid)
return;
let path = f.get_parent().get_path();
let k = undefined;
for (let i = 0; i < this._paths.length; i++) {
if (this._paths[i] == path)
k = i;
}
if (k === undefined) {
return;
}
if (type == Gio.FileMonitorEvent.CREATED) {
this._childs[k].push(f.get_basename());
}
if (type == Gio.FileMonitorEvent.DELETED) {
this._changedCount++;
if (this._changedCount > MAX_FILE_DELETED_BEFORE_INVALID) {
this._valid = false;
}
let name = f.get_basename();
this._childs[k] = this._childs[k].filter(function(e) {
return e != name;
});
}
if (type == Gio.FileMonitorEvent.UNMOUNTED) {
this._childs[k] = [];
}
},
getCompletion: function(text) {
let common = "";
let notInit = true;
if (!this._valid) {
this._update(0);
return common;
}
function _getCommon(s1, s2) {
let k = 0;
for (; k < s1.length && k < s2.length; k++) {
if (s1[k] != s2[k])
break;
}
if (k == 0)
return "";
return s1.substr(0, k);
}
function _hasPrefix(s1, prefix) {
return s1.indexOf(prefix) == 0;
}
for (let i = 0; i < this._childs.length; i++) {
for (let k = 0; k < this._childs[i].length; k++) {
if (!_hasPrefix(this._childs[i][k], text))
continue;
if (notInit) {
common = this._childs[i][k];
notInit = false;
}
common = _getCommon(common, this._childs[i][k]);
}
}
if (common.length)
return common.substr(text.length);
return common;
}
};
function RunDialog() {
this._init();
@ -36,9 +183,8 @@ RunDialog.prototype = {
this._isOpen = false;
let gconf = Shell.GConf.get_default();
gconf.connect('changed', Lang.bind(this, function (gconf, key) {
if (key == 'development_tools')
this._enableInternalCommands = gconf.get_bool('development_tools');
gconf.connect('changed::development_tools', Lang.bind(this, function () {
this._enableInternalCommands = gconf.get_boolean('development_tools');
}));
this._enableInternalCommands = gconf.get_boolean('development_tools');
@ -63,28 +209,26 @@ RunDialog.prototype = {
// All actors are inside _group. We create it initially
// hidden then show it in show()
this._group = new Clutter.Group({ visible: false });
this._group = new Clutter.Group({ visible: false,
x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height });
global.stage.add_actor(this._group);
this._overlay = new Clutter.Rectangle({ color: OVERLAY_COLOR,
width: global.screen_width,
height: global.screen_height,
border_width: 0,
reactive: true });
this._group.add_actor(this._overlay);
let lightbox = new Lightbox.Lightbox(this._group, true);
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
width: global.screen_width,
height: global.screen_height });
this._boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER });
this._group.add_actor(boxH);
this._group.add_actor(this._boxH);
lightbox.highlight(this._boxH);
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
boxH.append(boxV, Big.BoxPackFlags.NONE);
this._boxH.append(boxV, Big.BoxPackFlags.NONE);
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
@ -94,7 +238,7 @@ RunDialog.prototype = {
padding: DIALOG_PADDING,
width: DIALOG_WIDTH });
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
this._boxH.append(dialogBox, Big.BoxPackFlags.NONE);
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans',
@ -142,17 +286,57 @@ RunDialog.prototype = {
this.close();
}));
this._pathCompleter = new Gio.FilenameCompleter();
this._commandCompleter = new CommandCompleter();
this._group.connect('notify::visible', Lang.bind(this._commandCompleter, this._commandCompleter.update));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
}
if (symbol == Clutter.slash) {
// Need preload data before get completion. GFilenameCompleter load content of parent directory.
// Parent directory for /usr/include/ is /usr/. So need to add fake name('a').
let text = o.get_text().concat('/a');
let prefix;
if (text.lastIndexOf(' ') == -1)
prefix = text;
else
prefix = text.substr(text.lastIndexOf(' ') + 1);
this._getCompletion(prefix);
return false;
}
if (symbol == Clutter.Tab) {
let text = o.get_text();
let prefix;
if (text.lastIndexOf(' ') == -1)
prefix = text;
else
prefix = text.substr(text.lastIndexOf(' ') + 1);
let postfix = this._getCompletion(prefix);
if (postfix != null && postfix.length > 0) {
o.insert_text(postfix, -1);
o.set_cursor_position(text.length + postfix.length);
if (postfix[postfix.length - 1] == '/')
this._getCompletion(text + postfix + 'a');
}
return true;
}
return false;
}));
},
_getCompletion : function(text) {
if (text.indexOf('/') != -1) {
return this._pathCompleter.get_completion_suffix(text);
} else {
return this._commandCompleter.getCompletion(text);
}
},
_run : function(command) {
this._commandError = false;
let f;
if (this._enableInternalCommands)
f = this._internalCommands[command];
@ -162,7 +346,6 @@ RunDialog.prototype = {
f();
} else if (command) {
try {
this._commandError = false;
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
p.run();
@ -175,7 +358,7 @@ RunDialog.prototype = {
* We are only interested in the actual error, so parse that out.
*/
let m = /.+\((.+)\)/.exec(e);
let errorStr = "Execution of '" + command + "' failed:\n" + m[1];
let errorStr = _("Execution of '%s' failed:").format(command) + "\n" + m[1];
this._errorMessage.set_text(errorStr);
this._errorBox.show();
}
@ -186,10 +369,18 @@ RunDialog.prototype = {
if (this._isOpen) // Already shown
return;
if (!Main.pushModal(this._group))
return;
// Position the dialog on the current monitor
let monitor = global.get_focus_monitor();
this._boxH.set_position(monitor.x, monitor.y);
this._boxH.set_size(monitor.width, monitor.height);
this._isOpen = true;
this._group.show();
Main.pushModal(this._group);
global.stage.set_key_focus(this._entry);
},
@ -203,7 +394,7 @@ RunDialog.prototype = {
this._commandError = false;
this._group.hide();
this._entry.text = '';
this._entry.set_text('');
Main.popModal(this._group);
}

272
js/ui/search.js Normal file
View File

@ -0,0 +1,272 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Signals = imports.signals;
const St = imports.gi.St;
const RESULT_ICON_SIZE = 24;
// Not currently referenced by the search API, but
// this enumeration can be useful for provider
// implementations.
const MatchType = {
NONE: 0,
MULTIPLE: 1,
PREFIX: 2,
SUBSTRING: 3
};
function SearchResultDisplay(provider) {
this._init(provider);
}
SearchResultDisplay.prototype = {
_init: function(provider) {
this.provider = provider;
this.actor = null;
this.selectionIndex = -1;
},
/**
* renderResults:
* @results: List of identifier strings
* @terms: List of search term strings
*
* Display the given search matches which resulted
* from the given terms. It's expected that not
* all results will fit in the space for the container
* actor; in this case, show as many as makes sense
* for your result type.
*
* The terms are useful for search match highlighting.
*/
renderResults: function(results, terms) {
throw new Error("not implemented");
},
/**
* clear:
* Remove all results from this display and reset the selection index.
*/
clear: function() {
this.actor.get_children().forEach(function (actor) { actor.destroy(); });
this.selectionIndex = -1;
},
/**
* getSelectionIndex:
*
* Returns the index of the selected actor, or -1 if none.
*/
getSelectionIndex: function() {
return this.selectionIndex;
},
/**
* getVisibleResultCount:
*
* Returns: The number of actors visible.
*/
getVisibleResultCount: function() {
throw new Error("not implemented");
},
/**
* selectIndex:
* @index: Integer index
*
* Move selection to the given index.
* Return true if successful, false if no more results
* available.
*/
selectIndex: function() {
throw new Error("not implemented");
}
};
/**
* SearchProvider:
*
* Subclass this object to add a new result type
* to the search system, then call registerProvider()
* in SearchSystem with an instance.
*/
function SearchProvider(title) {
this._init(title);
}
SearchProvider.prototype = {
_init: function(title) {
this.title = title;
},
/**
* getInitialResultSet:
* @terms: Array of search terms, treated as logical OR
*
* Called when the user first begins a search (most likely
* therefore a single term of length one or two), or when
* a new term is added.
*
* Should return an array of result identifier strings representing
* items which match the given search terms. This
* is expected to be a substring match on the metadata for a given
* item. Ordering of returned results is up to the discretion of the provider,
* but you should follow these heruistics:
*
* * Put items which match multiple search terms before single matches
* * Put items which match on a prefix before non-prefix substring matches
*
* This function should be fast; do not perform unindexed full-text searches
* or network queries.
*/
getInitialResultSet: function(terms) {
throw new Error("not implemented");
},
/**
* getSubsearchResultSet:
* @previousResults: Array of item identifiers
* @newTerms: Updated search terms
*
* Called when a search is performed which is a "subsearch" of
* the previous search; i.e. when every search term has exactly
* one corresponding term in the previous search which is a prefix
* of the new term.
*
* This allows search providers to only search through the previous
* result set, rather than possibly performing a full re-query.
*/
getSubsearchResultSet: function(previousResults, newTerms) {
throw new Error("not implemented");
},
/**
* getResultInfo:
* @id: Result identifier string
*
* Return an object with 'id', 'name', (both strings) and 'icon' (Clutter.Texture)
* properties which describe the given search result.
*/
getResultMeta: function(id) {
throw new Error("not implemented");
},
/**
* createResultContainer:
*
* Search providers may optionally override this to render their
* results in a custom fashion. The default implementation
* will create a vertical list.
*
* Returns: An instance of SearchResultDisplay.
*/
createResultContainerActor: function() {
return null;
},
/**
* createResultActor:
* @resultMeta: Object with result metadata
* @terms: Array of search terms, should be used for highlighting
*
* Search providers may optionally override this to render a
* particular serch result in a custom fashion. The default
* implementation will show the icon next to the name.
*
* The actor should be an instance of St.Widget, with the style class
* 'dash-search-result-content'.
*/
createResultActor: function(resultMeta, terms) {
return null;
},
/**
* activateResult:
* @id: Result identifier string
*
* Called when the user chooses a given result.
*/
activateResult: function(id) {
throw new Error("not implemented");
},
/**
* expandSearch:
*
* Called when the user clicks on the header for this
* search section. Should typically launch an external program
* displaying search results for that item type.
*/
expandSearch: function(terms) {
throw new Error("not implemented");
}
}
Signals.addSignalMethods(SearchProvider.prototype);
function SearchSystem() {
this._init();
}
SearchSystem.prototype = {
_init: function() {
this._providers = [];
this.reset();
},
registerProvider: function (provider) {
this._providers.push(provider);
},
getProviders: function() {
return this._providers;
},
getTerms: function() {
return this._previousTerms;
},
reset: function() {
this._previousTerms = [];
this._previousResults = [];
},
updateSearch: function(searchString) {
searchString = searchString.replace(/^\s+/g, "").replace(/\s+$/g, "");
if (searchString == '')
return null;
let terms = searchString.split(/\s+/);
let isSubSearch = terms.length == this._previousTerms.length;
if (isSubSearch) {
for (let i = 0; i < terms.length; i++) {
if (terms[i].indexOf(this._previousTerms[i]) != 0) {
isSubSearch = false;
break;
}
}
}
let results = [];
if (isSubSearch) {
for (let i = 0; i < this._previousResults.length; i++) {
let [provider, previousResults] = this._previousResults[i];
let providerResults = provider.getSubsearchResultSet(previousResults, terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
}
} else {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
let providerResults = provider.getInitialResultSet(terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
}
}
this._previousTerms = terms;
this._previousResults = results;
return results;
}
}
Signals.addSignalMethods(SearchSystem.prototype);

75
js/ui/shellDBus.js Normal file
View File

@ -0,0 +1,75 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const GnomeShellIface = {
name: "org.gnome.Shell",
methods: [{ name: "Eval",
inSignature: "s",
outSignature: "bs"
}
],
signals: [],
properties: [{ name: "OverviewActive",
signature: "b",
access: "readwrite" }]
};
function GnomeShell() {
this._init();
}
GnomeShell.prototype = {
_init: function() {
DBus.session.exportObject('/org/gnome/Shell', this);
},
/**
* Eval:
* @code: A string containing JavaScript code
*
* This function executes arbitrary code in the main
* loop, and returns a boolean success and
* JSON representation of the object as a string.
*
* If evaluation completes without throwing an exception,
* then the return value will be [true, JSON.stringify(result)].
* If evaluation fails, then the return value will be
* [false, JSON.stringify(exception)];
*
*/
Eval: function(code) {
let returnValue;
let success;
try {
returnValue = JSON.stringify(eval(code));
// A hack; DBus doesn't have null/undefined
if (returnValue == undefined)
returnValue = "";
success = true;
} catch (e) {
returnValue = JSON.stringify(e);
success = false;
}
return [success, returnValue];
},
get OverviewActive() {
return Main.overview.visible;
},
set OverviewActive(visible) {
if (visible)
Main.overview.show();
else
Main.overview.hide();
}
};
DBus.conformExport(GnomeShell.prototype, GnomeShellIface);

View File

@ -4,6 +4,7 @@ const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
@ -58,6 +59,8 @@ Sidebar.prototype = {
if (this._visible)
Main.chrome.addActor(this.actor);
this._hidden = false;
this._hideTimeoutId = 0;
this._widgets = [];
this.addWidget(new ToggleWidget());
@ -69,6 +72,14 @@ Sidebar.prototype = {
Lang.bind(this, this._expandedChanged));
this._gconf.connect('changed::sidebar/visible',
Lang.bind(this, this._visibleChanged));
this._gconf.connect('changed::sidebar/autohide',
Lang.bind(this, this._autohideChanged));
this.actor.connect('enter-event',Lang.bind(this,this._restoreHidden));
this.actor.connect('leave-event',Lang.bind(this,this._startHideTimeout));
this._adjustPosition();
this._autohideChanged();
},
addWidget: function(widget) {
@ -82,6 +93,14 @@ Sidebar.prototype = {
this.box.append(widgetBox.actor, Big.BoxPackFlags.NONE);
this._widgets.push(widgetBox);
this._adjustPosition();
},
_adjustPosition: function() {
let primary=global.get_primary_monitor();
this.actor.y = Math.floor(Math.max(primary.y + Panel.PANEL_HEIGHT,primary.height/2 - this.actor.height/2));
this.actor.x = primary.x;
},
_visibleChanged: function() {
@ -108,6 +127,21 @@ Sidebar.prototype = {
this._collapse();
},
_autohideChanged: function() {
let autohide = this._gconf.get_boolean("sidebar/autohide");
if (autohide == this._autohide)
return;
this._autohide = autohide;
if (autohide) {
this.actor.set_reactive(true);
this._hide();
} else {
this.actor.set_reactive(false);
this._restore();
}
},
_expand: function() {
this._expanded = true;
for (let i = 0; i < this._widgets.length; i++)
@ -125,16 +159,70 @@ Sidebar.prototype = {
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].collapse();
// Updated the strut/stage area after the animation completes
// Update the strut/stage area after the animation completes
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
onComplete: function () {
onComplete: Lang.bind(this, function () {
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
} });
}) });
},
_hide: function() {
if (!this._expanded) {
this._hidden = true;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].hide();
// Update the strut/stage area after the animation completes
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME / 2,
onComplete: Lang.bind(this, function () {
this.actor.width = Math.floor(WidgetBox.WIDGETBOX_PADDING * 2 + SIDEBAR_PADDING);
}) });
}
},
_restore: function() {
if (!this._expanded) {
this._hidden = false;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].restore();
// Updated the strut/stage area after the animation completes
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME / 2,
onComplete: function () {
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
} });
}
},
_restoreHidden: function(actor, event) {
this._cancelHideTimeout();
if (this._hidden)
this._restore();
return false;
},
_startHideTimeout: function(actor, event) {
if (!this._expanded) {
this._cancelHideTimeout();
this._hideTimeoutId = Mainloop.timeout_add_seconds(2, Lang.bind(this,this._hideTimeoutFunc));
}
return false;
},
_cancelHideTimeout: function() {
if (this._hideTimeoutId != 0) {
Mainloop.source_remove(this._hideTimeoutId);
this._hideTimeoutId = 0;
}
},
_hideTimeoutFunc: function() {
this._hide();
return false;
},
destroy: function() {
this.hide();
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].destroy();
this.actor.destroy();

297
js/ui/statusMenu.js Normal file
View File

@ -0,0 +1,297 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const Gdm = imports.gi.Gdm;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Panel = imports.ui.panel;
// Adapted from gdm/gui/user-switch-applet/applet.c
//
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
// Copyright (C) 2008,2009 Red Hat, Inc.
const SIDEBAR_VISIBLE_KEY = 'sidebar/visible';
function StatusMenu() {
this._init();
}
StatusMenu.prototype = {
_init: function() {
this._gdm = Gdm.UserManager.ref_default();
this._user = this._gdm.get_user(GLib.get_user_name());
this._presence = new GnomeSessionPresence();
this.actor = new St.BoxLayout({ name: 'statusMenu' });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._iconBox = new St.Bin();
this.actor.add(this._iconBox, { y_align: St.Align.MIDDLE });
let textureCache = Shell.TextureCache.get_default();
// FIXME: these icons are all wrong (likewise in createSubMenu)
this._availableIcon = textureCache.load_icon_name('gtk-yes', 16);
this._busyIcon = textureCache.load_icon_name('gtk-no', 16);
this._invisibleIcon = textureCache.load_icon_name('gtk-close', 16);
this._idleIcon = textureCache.load_icon_name('gtk-media-pause', 16);
this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon));
this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon));
this._name = new St.Label({ text: this._user.get_real_name() });
this.actor.add(this._name, { expand: true, y_align: St.Align.MIDDLE });
this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName));
this._createSubMenu();
this._gdm.connect('users-loaded', Lang.bind(this, this._updateSwitchUser));
this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser));
this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser));
},
_onDestroy: function() {
this._user.disconnect(this._userNameChangedId);
},
_updateUserName: function() {
this._name.set_text(this._user.get_real_name());
},
_updateSwitchUser: function() {
let users = this._gdm.list_users();
if (users.length > 1)
this._loginScreenItem.show();
else
this._loginScreenItem.hide();
},
_updatePresenceIcon: function(presence, status) {
if (status == GnomeSessionPresenceStatus.AVAILABLE)
this._iconBox.child = this._availableIcon;
else if (status == GnomeSessionPresenceStatus.BUSY)
this._iconBox.child = this._busyIcon;
else if (status == GnomeSessionPresenceStatus.INVISIBLE)
this._iconBox.child = this._invisibleIcon;
else
this._iconBox.child = this._idleIcon;
},
// The menu
_createImageMenuItem: function(label, iconName, forceIcon) {
let image = new Gtk.Image();
let item = new Gtk.ImageMenuItem({ label: label,
image: image,
always_show_image: forceIcon == true });
item.connect('style-set', Lang.bind(this,
function() {
image.set_from_icon_name(iconName, Gtk.IconSize.MENU);
}));
return item;
},
_createSubMenu: function() {
this._menu = new Gtk.Menu();
this._menu.connect('deactivate', Lang.bind(this, function() { this.emit('deactivated'); }));
let item;
item = this._createImageMenuItem(_("Available"), 'gtk-yes', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.AVAILABLE));
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Busy"), 'gtk-no', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.BUSY));
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Invisible"), 'gtk-close', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.INVISIBLE));
this._menu.append(item);
item.show();
item = new Gtk.SeparatorMenuItem();
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Account Information..."), 'user-info');
item.connect('activate', Lang.bind(this, this._onAccountInformationActivate));
this._menu.append(item);
item.show();
let gconf = Shell.GConf.get_default();
item = new Gtk.CheckMenuItem({ label: _("Sidebar"),
active: gconf.get_boolean(SIDEBAR_VISIBLE_KEY) });
item.connect('activate', Lang.bind(this,
function() {
gconf.set_boolean(SIDEBAR_VISIBLE_KEY, this._sidebarItem.active);
}));
this._menu.append(item);
item.show();
this._sidebarItem = item;
item = this._createImageMenuItem(_("System Preferences..."), 'preferences-desktop');
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this._menu.append(item);
item.show();
item = new Gtk.SeparatorMenuItem();
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Lock Screen"), 'system-lock-screen');
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Switch User"), 'system-users');
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
this._menu.append(item);
item.show();
this._loginScreenItem = item;
item = this._createImageMenuItem(_("Log Out..."), 'system-log-out');
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_("Shut Down..."), 'system-shutdown');
item.connect('activate', Lang.bind(this, this._onShutDownActivate));
this._menu.append(item);
item.show();
},
_setPresenceStatus: function(item, status) {
this._presence.setStatus(status);
},
_onAccountInformationActivate: function() {
this._spawn(['gnome-about-me']);
},
_onPreferencesActivate: function() {
this._spawn(['gnome-control-center']);
},
_onLockScreenActivate: function() {
this._spawn(['gnome-screensaver-command', '--lock']);
},
_onLoginScreenActivate: function() {
this._gdm.goto_login_session();
this._onLockScreenActivate();
},
_onQuitSessionActivate: function() {
this._spawn(['gnome-session-save', '--logout-dialog']);
},
_onShutDownActivate: function() {
this._spawn(['gnome-session-save', '--shutdown-dialog']);
},
_spawn: function(args) {
// FIXME: once Shell.Process gets support for signalling
// errors we should pop up an error dialog or something here
// on failure
let p = new Shell.Process({'args' : args});
p.run();
},
// shell_status_menu_toggle:
// @event: event causing the toggle
//
// If the menu is not currently up, pops it up. Otherwise, hides it.
// Popping up may fail if another grab is already active; check with
// isActive().
toggle: function(event) {
if (this._menu.visible)
this._menu.popdown();
else {
// We don't want to overgrab a Mutter grab with the grab
// that GTK+ uses on menus.
if (global.display_is_grabbed())
return;
let [menuWidth, menuHeight] = this._menu.get_size_request ();
let panel;
for (panel = this.actor; panel; panel = panel.get_parent()) {
if (panel._delegate instanceof Panel.Panel)
break;
}
let [panelX, panelY] = panel.get_transformed_position();
let [panelWidth, panelHeight] = panel.get_transformed_size();
let menuX = Math.round(panelX + panelWidth - menuWidth);
let menuY = Math.round(panelY + panelHeight);
Shell.popup_menu(this._menu, event.get_button(), event.get_time(),
menuX, menuY);
}
},
// isActive:
//
// Gets whether the menu is currently popped up
//
// Return value: %true if the menu is currently popped up
isActive: function() {
return this._menu.visible;
}
};
Signals.addSignalMethods(StatusMenu.prototype);
const GnomeSessionPresenceIface = {
name: 'org.gnome.SessionManager.Presence',
methods: [{ name: 'SetStatus',
inSignature: 'u' }],
properties: [{ name: 'status',
signature: 'u',
access: 'readwrite' }],
signals: [{ name: 'StatusChanged',
inSignature: 'u' }]
};
const GnomeSessionPresenceStatus = {
AVAILABLE: 0,
INVISIBLE: 1,
BUSY: 2,
IDLE: 3
};
function GnomeSessionPresence() {
this._init();
}
GnomeSessionPresence.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
this.connect('StatusChanged', Lang.bind(this, function (proxy, status) { this.status = status; }));
},
getStatus: function(callback) {
this.GetRemote('status', Lang.bind(this,
function(status, ex) {
if (!ex)
callback(this, status);
}));
},
setStatus: function(status) {
this.SetStatusRemote(status);
}
};
DBus.proxifyPrototype(GnomeSessionPresence.prototype, GnomeSessionPresenceIface);

View File

@ -178,7 +178,7 @@ function resumeTweens() {
function registerSpecialProperty(name, getFunction, setFunction,
parameters, preProcessFunction) {
Tweener.registerSpecialProperty(name, getFunction, setFunction,
parameters, preProcessFunction);
parameters, preProcessFunction);
}
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {

View File

@ -12,6 +12,7 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppFavorites = imports.ui.appFavorites;
const DocInfo = imports.misc.docInfo;
const COLLAPSED_WIDTH = 24;
@ -318,12 +319,9 @@ AppsWidget.prototype = {
this.collapsedActor = new Big.Box({ spacing: 2});
let appSystem = Shell.AppSystem.get_default();
let apps = appSystem.get_favorites();
let apps = AppFavorites.getAppFavorites().getFavorites();
for (let i = 0; i < apps.length; i++) {
let app = appSystem.lookup_cached_app(apps[i]);
if (!app)
continue;
this.addItem(new AppsWidgetInfo(app));
this.addItem(new AppsWidgetInfo(apps[i]));
}
}
};
@ -356,8 +354,7 @@ RecentDocsWidget.prototype = {
for (i = 0; i < docs.length; i++) {
let docInfo = new DocInfo.DocInfo (docs[i]);
if (docInfo.exists())
items.push(docInfo);
items.push(docInfo);
}
items.sort(function (a,b) { return b.timestamp - a.timestamp; });

View File

@ -27,13 +27,13 @@ WidgetBox.prototype = {
_init: function(widget, expanded) {
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
if (widget instanceof Widget.Widget) {
this._widget = widget;
if (widget instanceof Widget.Widget) {
this._widget = widget;
this._widget.state = this.state;
} else {
let ctor = this._ctorFromName(widget);
} else {
let ctor = this._ctorFromName(widget);
this._widget = new ctor(this.state);
}
}
if (!this._widget.actor)
throw new Error("widget has no actor");
@ -331,7 +331,7 @@ WidgetBox.prototype = {
onCompleteScope: this });
this.state = this._widget.state = Widget.STATE_POPPING_OUT;
Main.chrome.addInputRegionActor(this._hbox);
Main.chrome.trackActor(this._hbox, { affectsStruts: false });
},
_popOutComplete: function() {
@ -370,7 +370,21 @@ WidgetBox.prototype = {
this._egroup.hide();
this._ebox.x = 0;
Main.chrome.removeInputRegionActor(this._hbox);
Main.chrome.untrackActor(this._hbox);
},
hide: function() {
if (this.state == Widget.STATE_COLLAPSED)
Tweener.addTween(this._cbox, { x: -Widget.COLLAPSED_WIDTH,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad" });
},
restore: function() {
if (this.state == Widget.STATE_COLLAPSED)
Tweener.addTween(this._cbox, { x: 0,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad" });
},
destroy: function() {

View File

@ -0,0 +1,109 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Meta = imports.gi.Meta;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
function WindowAttentionHandler() {
this._init();
}
WindowAttentionHandler.prototype = {
_init : function() {
let display = global.screen.get_display();
display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
let tracker = Shell.WindowTracker.get_default();
this._startupIds = {};
tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
},
_onStartupSequenceChanged : function(tracker) {
let sequences = tracker.get_startup_sequences();
this._startupIds = {};
for(let i = 0; i < sequences.length; i++) {
this._startupIds[sequences[i].get_id()] = true;
}
},
_sourceId : function(appId) {
return 'attention-' + appId;
},
_getTitle : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return app.get_name();
else
return window.title;
},
_getBanner : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return _("%s has finished starting").format(app.get_name());
else
return _("'%s' is ready").format(window.title);
},
_onWindowDemandsAttention : function(display, window) {
// We don't want to show the notification when the window is already focused,
// because this is rather pointless.
// Some apps (like GIMP) do things like setting the urgency hint on the
// toolbar windows which would result into a notification even though GIMP itself is
// focused.
// We are just ignoring the hint on skip_taskbar windows for now.
// (Which is the same behaviour as with metacity + panel)
if (!window || window.has_focus() || window.is_skip_taskbar())
return;
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_window_app(window);
let source = Main.messageTray.getSource(this._sourceId(app.get_id()));
if (source == null) {
source = new Source(this._sourceId(app.get_id()), app, window);
Main.messageTray.add(source);
source.connect('clicked', Lang.bind(this, function() { source.destroy(); }));
}
let notification = new MessageTray.Notification(window.get_startup_id(), source, this._getTitle(app, window), this._getBanner(app, window), true);
source.notify(notification);
window.connect('notify::title', Lang.bind(this, function(win) {
notification.update(this._getTitle(app, win), this._getBanner(app, win), false);
}));
window.connect('notify::demands-attention', Lang.bind(this, function() { source.destroy() }));
window.connect('focus', Lang.bind(this, function() { source.destroy() }));
window.connect('unmanaged', Lang.bind(this, function() { source.destroy() }));
}
}
function Source(sourceId, app, window) {
this._init(sourceId, app, window);
}
Source.prototype = {
__proto__ : MessageTray.Source.prototype,
_init: function(sourceId, app, window) {
MessageTray.Source.prototype._init.call(this, sourceId);
this._window = window;
this._app = app;
},
createIcon : function(size) {
return this._app.create_icon_texture(size);
},
clicked : function() {
Main.activateWindow(this._window);
MessageTray.Source.prototype.clicked.call(this);
}
}

View File

@ -4,8 +4,10 @@ const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const AltTab = imports.ui.altTab;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -39,7 +41,19 @@ WindowManager.prototype = {
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
shellwm.connect('begin-alt-tab', Lang.bind(this, this._beginAltTab));
shellwm.takeover_keybinding('switch_windows');
shellwm.connect('keybinding::switch_windows', Lang.bind(this, this._startAppSwitcher));
this._workspaceSwitcherPopup = null;
shellwm.takeover_keybinding('switch_to_workspace_left');
shellwm.takeover_keybinding('switch_to_workspace_right');
shellwm.takeover_keybinding('switch_to_workspace_up');
shellwm.takeover_keybinding('switch_to_workspace_down');
shellwm.connect('keybinding::switch_to_workspace_left', Lang.bind(this, this._showWorkspaceSwitcher));
shellwm.connect('keybinding::switch_to_workspace_right', Lang.bind(this, this._showWorkspaceSwitcher));
shellwm.connect('keybinding::switch_to_workspace_up', Lang.bind(this, this._showWorkspaceSwitcher));
shellwm.connect('keybinding::switch_to_workspace_down', Lang.bind(this, this._showWorkspaceSwitcher));
},
_shouldAnimate : function(actor) {
@ -72,9 +86,14 @@ WindowManager.prototype = {
* maybe TODO: get icon geometry passed through and move the window towards it?
*/
this._minimizing.push(actor);
let primary = global.get_primary_monitor();
Tweener.addTween(actor,
{ scale_x: 0.0,
scale_y: 0.0,
x: primary.x,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._minimizeWindowDone,
@ -161,41 +180,10 @@ WindowManager.prototype = {
},
_destroyWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) {
shellwm.completed_destroy(actor);
return;
}
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
/* anachronistic 'tv-like' effect - squash on y axis, leave x alone */
this._destroying.push(actor);
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 0.0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
shellwm.completed_destroy(actor);
},
_destroyWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
shellwm.completed_destroy(actor);
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
}
},
_destroyWindowOverwrite : function(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
shellwm.completed_destroy(actor);
}
},
_switchWorkspace : function(shellwm, from, to, direction) {
@ -300,12 +288,46 @@ WindowManager.prototype = {
shellwm.completed_switch_workspace();
},
_beginAltTab : function(shellwm, handler) {
let popup = new AltTab.AltTabPopup();
_startAppSwitcher : function(shellwm, binding, window, backwards) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide();
handler.connect('window-added', function(handler, window) { popup.addWindow(window); });
handler.connect('show', function(handler, initialSelection) { popup.show(initialSelection); });
handler.connect('destroy', function() { popup.destroy(); });
handler.connect('notify::selected', function() { popup.select(handler.selected); });
}
let tabPopup = new AltTab.AltTabPopup();
if (!tabPopup.show(backwards))
tabPopup.destroy();
},
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
/* We don't support this kind of layout */
if (binding == "switch_to_workspace_up" || binding == "switch_to_workspace_down")
return;
if (global.screen.n_workspaces == 1)
return;
if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
if (binding == "switch_to_workspace_left") {
if (activeWorkspaceIndex > 0) {
global.screen.get_workspace_by_index(activeWorkspaceIndex - 1).activate(global.get_current_time());
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex - 1);
}
else
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex);
}
if (binding == "switch_to_workspace_right") {
if (activeWorkspaceIndex < global.screen.n_workspaces - 1) {
global.screen.get_workspace_by_index(activeWorkspaceIndex + 1).activate(global.get_current_time());
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex + 1);
}
else
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex);
}
}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Tweener = imports.ui.tweener;
const ANIMATION_TIME = 0.075;
const DISPLAY_TIMEOUT = 600;
const LEFT = -1;
const RIGHT = 1;
function WorkspaceSwitcherPopup() {
this._init();
}
WorkspaceSwitcherPopup.prototype = {
_init : function() {
this.actor = new Clutter.Group({ reactive: true,
x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height });
global.stage.add_actor(this.actor);
this._scaleWidth = global.screen_width / global.screen_height;
this._container = new St.BoxLayout({ style_class: "workspace-switcher-container" });
this._list = new St.BoxLayout({ style_class: "workspace-switcher" });
this._container.add(this._list);
this.actor.add_actor(this._container);
this._redraw();
this._position();
this.actor.show();
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
},
_redraw : function(direction, activeWorkspaceIndex) {
this._list.destroy_children();
for (let i = 0; i < global.screen.n_workspaces; i++) {
let indicator = null;
if (i == activeWorkspaceIndex && direction == LEFT)
indicator = new St.Bin({ style_class: 'ws-switcher-active-left' });
else if(i == activeWorkspaceIndex && direction == RIGHT)
indicator = new St.Bin({ style_class: 'ws-switcher-active-right' });
else
indicator = new St.Bin({ style_class: 'ws-switcher-box' });
this._list.add(indicator);
indicator.set_width(Math.round(indicator.get_height() * this._scaleWidth));
if (i < global.screen.n_workspaces - 1) {
let spacer = new St.Bin({ style_class: 'ws-switcher-spacer' });
this._list.add(spacer);
}
}
},
_position: function() {
let focus = global.get_focus_monitor();
this._container.x = focus.x + Math.floor((focus.width - this._container.width) / 2);
this._container.y = focus.y + Math.floor((focus.height - this._container.height) / 2);
},
_show : function() {
Tweener.addTween(this._container, { opacity: 255,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this._position();
this.actor.show();
},
display : function(direction, activeWorkspaceIndex) {
this._redraw(direction, activeWorkspaceIndex);
if (this._timeoutId != 0)
Mainloop.source_remove(this._timeoutId);
this._timeoutId = Mainloop.timeout_add(DISPLAY_TIMEOUT, Lang.bind(this, this._onTimeout));
this._show();
},
_onTimeout : function() {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
Tweener.addTween(this._container, { opacity: 0.0,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: function() { this.actor.hide() },
onCompleteScope: this
});
}
};

1037
js/ui/workspacesView.js Normal file

File diff suppressed because it is too large Load Diff

1
man/Makefile.am Normal file
View File

@ -0,0 +1 @@
dist_man_MANS = gnome-shell.1

99
man/gnome-shell.1 Normal file
View File

@ -0,0 +1,99 @@
.\" Copyright (c) 2009, Marcelo Jorge Vieira (metal) <metal@alucinados.com>
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 2 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, write to the Free
.\" Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
.\" Boston, MA 02111-1301 USA.
.TH GNOME-SHELL 1
.SH NAME
gnome-shell \- Graphical shell for the GNOME desktop
.SH SYNOPSIS
.B gnome-shell [options]
.SH DESCRIPTION
GNOME Shell provides core user interface functions for the GNOME 3
desktop, like switching to windows and launching applications. GNOME
Shell takes advantage of the capabilities of modern graphics hardware
and introduces innovative user interface concepts to provide a
visually attractive and easy to use experience.
.SH OPTIONS
.TP
.B \-r, \-\-replace
Replace the running metacity/gnome-panel
.br
.TP
.B \-v, \-\-verbose
Shows details about the results of running `gnome-shell'.
.br
.TP
.B \-g, \-\-debug
Run under a debugger
.br
.TP
.B \-\-debug\-command
Command to use for debugging (defaults to 'gdb \-\-args')
.br
.TP
.B \-\-sync
.br
Make X calls synchronously, useful when debugging down X errors
.br
.TP
.B \-\-xephyr
Run a debugging instance inside Xephyr
.br
.TP
.B \-\-geometry
Specify Xephyr screen geometry
.br
.TP
.B \-w, \-\-wide
Use widescreen (1280x800) with Xephyr
.br
.TP
.B \-\-create\-extension
Create a new GNOME Shell extension
.TP
.B \-\-eval\-file
Evaluate the contents of the given JavaScript file
.br
.SH BUGS
The bug tracker can be reached by visiting the website
\fIhttps://bugzilla.gnome.org/buglist.cgi?product=gnome-shell\fR
Before sending a bug report, please verify that you have the latest
version of gnome-shell. Many bugs (major and minor) are fixed at each
release, and if yours is out of date, the problem may already have
been solved.
.SH ADDITIONAL INFORMATION
For further information, visit the website \fIhttp://live.gnome.org/GnomeShell\fR

View File

@ -1,12 +1,17 @@
ar
bg
ca
cs
da
de
el
en_GB
es
fi
fr
ga
gl
he
hu
it
ko
@ -15,6 +20,12 @@ nl
pa
pl
pt_BR
ro
ru
sl
sr
sr@latin
sv
tr
vi
zh_CN

View File

@ -1,9 +1,15 @@
data/gnome-shell.desktop.in.in
js/ui/panel.js
js/ui/appDisplay.js
js/ui/appFavorites.js
js/ui/dash.js
js/ui/docDisplay.js
js/ui/lookingGlass.js
js/ui/overview.js
js/ui/panel.js
js/ui/placeDisplay.js
js/ui/runDialog.js
js/ui/statusMenu.js
js/ui/widget.js
src/gdmuser/gdm-user.c
src/shell-global.c
src/shell-status-menu.c
src/shell-uri-util.c

236
po/ar.po Normal file
View File

@ -0,0 +1,236 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Khaled Hosny <khaledhosny@eglug.org>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-01-17 11:29+0200\n"
"PO-Revision-Date: 2010-01-17 11:29+0300\n"
"Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n"
"Language-Team: Arabic <doc@arabeyes.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ar\n"
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
"X-Generator: Virtaal 0.5.1\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "صدفة جنوم"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "إدارة النوافذ وإطلاق التطبيقات"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "التطبيقات"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "التفضيلات"
#: ../js/ui/appDisplay.js:644
msgid "New Window"
msgstr "نافذة جديدة"
#: ../js/ui/appDisplay.js:648
msgid "Remove from Favorites"
msgstr "أزِل من المفضّلة"
#: ../js/ui/appDisplay.js:649
msgid "Add to Favorites"
msgstr "أضِف إلى المفضّلة"
#: ../js/ui/appDisplay.js:1001
msgid "Drag here to add favorites"
msgstr "اسحب إلى هنا ليضاف إلى المفضّلة"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "ابحث..."
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "يبحث..."
#: ../js/ui/dash.js:507
msgid "No matching results."
msgstr "لا نتائج مطابقة."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "الأماكن والأجهزة"
#. **** Documents ****
#: ../js/ui/dash.js:892
msgid "RECENT ITEMS"
msgstr "العناصر الحديثة"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "الأنشطة"
#. Translators: This is a time format.
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%A %Ol:%OM %p"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "اتّصل ب‍..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "من فضلك اكتب أمرا:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "فشل تنفيذ '%s':"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%OH:%OM"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "التطبيقات"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "المستندات الحديثة"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "منذ أقل من دقيقة"
#: ../src/shell-global.c:894
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "منذ أقل من دقيقة"
msgstr[1] "منذ دقيقة"
msgstr[2] "منذ دقيقتين"
msgstr[3] "منذ %d دقائق"
msgstr[4] "منذ %d دقيقة"
msgstr[5] "منذ %d دقيقة"
#: ../src/shell-global.c:899
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "منذ أقل من ساعة"
msgstr[1] "منذ ساعة"
msgstr[2] "منذ ساعتين"
msgstr[3] "منذ %d ساعات"
msgstr[4] "منذ %d ساعة"
msgstr[5] "منذ %d ساعة"
#: ../src/shell-global.c:904
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "منذ أقل من يوم"
msgstr[1] "منذ يوم"
msgstr[2] "منذ يومين"
msgstr[3] "منذ %d أيام"
msgstr[4] "منذ %d يوما"
msgstr[5] "منذ %d يوم"
#: ../src/shell-global.c:909
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "منذ أقل من أسبوع"
msgstr[1] "منذ أسبوع"
msgstr[2] "منذ أسبوعين"
msgstr[3] "منذ %d أسابيع"
msgstr[4] "منذ %d أسبوعا"
msgstr[5] "منذ %d أسبوع"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "مجلد المنزل"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "نظام الملفات"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "ابحث"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Frequent"
#~ msgstr "متكرر"
#~ msgid "More"
#~ msgstr "المزيد"
#~ msgid "(see all)"
#~ msgstr "(انظر الكل)"
#~ msgid "PLACES"
#~ msgstr "الأماكن"
#~ msgid "SEARCH RESULTS"
#~ msgstr "نتائج البحث"
#~ msgid "Unknown"
#~ msgstr "مجهول"
#~ msgid "Can't lock screen: %s"
#~ msgstr "تعذّر إيصاد الشاشة: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr "تعذّر ضبك حافظة الشاشة مؤقتا لتكون شاشة خالية: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "تعذّر الخروج: %s"
#~ msgid "Account Information..."
#~ msgstr "معلومات الحساب..."
#~ msgid "Sidebar"
#~ msgstr "الشريط الجانبي"
#~ msgid "System Preferences..."
#~ msgstr "تفضيلات النظام..."
#~ msgid "Lock Screen"
#~ msgstr "أوصد الشاشة"
#~ msgid "Switch User"
#~ msgstr "بدّل المستخدم"
#~ msgid "Log Out..."
#~ msgstr "اخرج..."
#~ msgid "Shut Down..."
#~ msgstr "أطفئ..."
#~ msgid "Browse"
#~ msgstr "استعرض"

254
po/bg.po Normal file
View File

@ -0,0 +1,254 @@
# Bulgarian translation of gnome-shell po-file.
# Copyright (C) 2010 Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
# Ivaylo Valkov <ivaylo@e-valkov.org>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-02-20 14:29+0200\n"
"PO-Revision-Date: 2010-02-16 21:13+0200\n"
"Last-Translator: Ivaylo Valkov <ivaylo@e-valkov.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Обвивка на GNOME"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Управление на прозорци и стартиране на програми"
#. **** Applications ****
#: ../js/ui/appDisplay.js:177 ../js/ui/dash.js:881
msgid "APPLICATIONS"
msgstr "ПРОГРАМИ"
#: ../js/ui/appDisplay.js:201
msgid "PREFERENCES"
msgstr "ПРЕДПОЧИТАНИЯ"
#: ../js/ui/appDisplay.js:579
msgid "New Window"
msgstr "Нов прозорец"
#: ../js/ui/appDisplay.js:583
msgid "Remove from Favorites"
msgstr "Премахване от „Любими“"
#: ../js/ui/appDisplay.js:584
msgid "Add to Favorites"
msgstr "Добавяне в „Любими“"
#: ../js/ui/appDisplay.js:936
msgid "Drag here to add favorites"
msgstr "Довлачете до тук обектите за да ги добавите към „Любими“"
#: ../js/ui/appFavorites.js:89
#, c-format
msgid "%s has been added to your favorites."
msgstr "Програмата „%s“ беше добавена в „Любими“"
#: ../js/ui/appFavorites.js:107
#, c-format
msgid "%s has been removed from your favorites."
msgstr "Програмата „%s“ беше премахната от „Любими“"
#: ../js/ui/dash.js:235
msgid "Find..."
msgstr "Търсене…"
#: ../js/ui/dash.js:505
msgid "Searching..."
msgstr "Търсене…"
#: ../js/ui/dash.js:519
msgid "No matching results."
msgstr "Няма съвпадения."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "МЕСТА И УСТРОЙСТВА"
#. **** Documents ****
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "СКОРО ОТВАРЯНИ"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "Няма инсталирани разширения"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Включено"
#: ../js/ui/lookingGlass.js:395
msgid "Disabled"
msgstr "Изключено"
#: ../js/ui/lookingGlass.js:397
msgid "Error"
msgstr "Грешка"
#: ../js/ui/lookingGlass.js:399
msgid "Out of date"
msgstr "Остаряло"
#: ../js/ui/lookingGlass.js:424
msgid "View Source"
msgstr "Преглед на програмния код"
#: ../js/ui/lookingGlass.js:430
msgid "Web Page"
msgstr "Домашна страница"
#: ../js/ui/overview.js:92
msgid "Undo"
msgstr "Отмяна"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Дейности"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a, %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Свързване към…"
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Въведете команда:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Неуспешно изпълнение на „%s“:"
#: ../js/ui/statusMenu.js:107
msgid "Available"
msgstr "Налично"
#: ../js/ui/statusMenu.js:112
msgid "Busy"
msgstr "Заето"
#: ../js/ui/statusMenu.js:117
msgid "Invisible"
msgstr "Невидимо"
#: ../js/ui/statusMenu.js:126
msgid "Account Information..."
msgstr "Информация за настройките на потребителя…"
#: ../js/ui/statusMenu.js:132
msgid "Sidebar"
msgstr "Странична лента"
#: ../js/ui/statusMenu.js:142
msgid "System Preferences..."
msgstr "Системни настройки…"
#: ../js/ui/statusMenu.js:151
msgid "Lock Screen"
msgstr "Заключване на екрана"
#: ../js/ui/statusMenu.js:156
msgid "Switch User"
msgstr "Смяна на потребител"
#: ../js/ui/statusMenu.js:162
msgid "Log Out..."
msgstr "Изход…"
#: ../js/ui/statusMenu.js:167
msgid "Shut Down..."
msgstr "Изключване на компютъра…"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Програми"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Скоро отваряни документи"
#: ../src/shell-global.c:960
msgid "Less than a minute ago"
msgstr "Преди по-малко от минута"
#: ../src/shell-global.c:964
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "преди %d минута"
msgstr[1] "преди %d минути"
#: ../src/shell-global.c:969
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "преди %d час"
msgstr[1] "преди %d часа"
#: ../src/shell-global.c:974
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "преди %d ден"
msgstr[1] "преди %d дни"
#: ../src/shell-global.c:979
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "преди %d седмица"
msgstr[1] "преди %d седмици"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Домашна папка"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Файлова система"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Търсене"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

105
po/ca.po
View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
"POT-Creation-Date: 2009-10-10 20:19+0200\n"
"PO-Revision-Date: 2009-10-10 20:22+0100\n"
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@ -24,82 +24,126 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Gestió de finestres i execució d'aplicacions"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Activitats"
#: ../js/ui/appDisplay.js:335
msgid "Frequent"
msgstr "Freqüent"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/appIcon.js:462
msgid "New Window"
msgstr "Finestra nova"
#: ../js/ui/dash.js:256
#: ../js/ui/appIcon.js:475
msgid "Remove from Favorites"
msgstr "Elimina dels preferits"
#: ../js/ui/appIcon.js:476
msgid "Add to Favorites"
msgstr "Afegeix als preferits"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Cerca..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Navega"
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Més"
#: ../js/ui/dash.js:451
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(mostra tot)"
#. **** Applications ****
#: ../js/ui/dash.js:633
#: ../js/ui/dash.js:681
#: ../js/ui/dash.js:763
#: ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "APLICACIONS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
#: ../js/ui/dash.js:783
msgid "PLACES"
msgstr "LLOCS"
#. **** Documents ****
#: ../js/ui/dash.js:660
#: ../js/ui/dash.js:692
#: ../js/ui/dash.js:790
#: ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTS RECENTS"
#. **** Search Results ****
#: ../js/ui/dash.js:679
#: ../js/ui/dash.js:815
#: ../js/ui/dash.js:955
msgid "SEARCH RESULTS"
msgstr "RESULTATS DE LA CERCA"
#: ../js/ui/runDialog.js:82
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "PREFERÈNCIES"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:272
msgid "Activities"
msgstr "Activitats"
#. Translators: This is a time format.
#: ../js/ui/panel.js:464
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "Connecta a..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Introduïu una ordre:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "No s'ha pogut executar «%s»:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:162
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:316
msgid "Applications"
msgstr "Aplicacions"
#: ../js/ui/widget.js:341
msgid "Recent Documents"
msgstr "Documents recents"
#: ../src/shell-global.c:812
msgid "Less than a minute ago"
msgstr "Fa menys d'un minut"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:815
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Fa %d minut"
msgstr[1] "Fa %d minuts"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:818
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Fa %d hora"
msgstr[1] "Fa %d hores"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:821
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Fa %d dia"
msgstr[1] "Fa %d dies"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:824
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -180,10 +224,3 @@ msgstr "Cerca"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Cerca aplicacions o documents"
#~ msgid "Manager"
#~ msgstr "Gestor"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."

228
po/cs.po
View File

@ -1,20 +1,21 @@
# Czech translation of gnome-shell.
# Copyright (C) 2009 the author(s) of gnome-shell.
# Copyright (C) 2009, 2010 the author(s) of gnome-shell.
# This file is distributed under the same license as the gnome-shell package.
# Andre Klapper <ak-47@gmx.net>, 2009.
# Petr Kovar <pknbe@volny.cz>, 2009.
# Petr Kovar <pknbe@volny.cz>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-30 17:37+0200\n"
"PO-Revision-Date: 2009-08-30 17:33+0200\n"
"POT-Creation-Date: 2010-01-12 21:58+0100\n"
"PO-Revision-Date: 2010-01-12 21:57+0100\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Lokalize 1.0\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
@ -24,59 +25,97 @@ msgstr "Prostředí GNOME Shell"
msgid "Window management and application launching"
msgstr "Správa oken a spouštění aplikací"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Činnosti"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "APLIKACE"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "PŘEDVOLBY"
#: ../js/ui/dash.js:256
#: ../js/ui/appDisplay.js:644
msgid "New Window"
msgstr "Nové okno"
#: ../js/ui/appDisplay.js:648
msgid "Remove from Favorites"
msgstr "Odstranit z oblíbených"
#: ../js/ui/appDisplay.js:649
msgid "Add to Favorites"
msgstr "Přidat mezi oblíbené"
#: ../js/ui/appDisplay.js:1001
msgid "Drag here to add favorites"
msgstr "Oblíbené přidáte přetažením sem"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "Najít..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Procházet"
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "Hledá se..."
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(zobrazit vše)"
#. **** Applications ****
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "APLIKACE"
#: ../js/ui/dash.js:507
msgid "No matching results."
msgstr "Neodpovídá ani jeden z výsledků."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "MÍSTA"
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "MÍSTA A ZAŘÍZENÍ"
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "NEDÁVNÉ DOKUMENTY"
#: ../js/ui/dash.js:892
msgid "RECENT ITEMS"
msgstr "NEDÁVNÉ POLOŽKY"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "VÝSLEDKY HLEDÁNÍ"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Činnosti"
#: ../js/ui/runDialog.js:82
#. Translators: This is a time format.
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Připojit se k..."
#: ../js/ui/runDialog.js:235
msgid "Please enter a command:"
msgstr "Zadejte prosím příkaz:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:351
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Vykonání \"%s\" selhalo:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Aplikace"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Nedávné dokumenty"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Před méně než minutou"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:893
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -84,7 +123,7 @@ msgstr[0] "Před %d minutou"
msgstr[1] "Před %d minutami"
msgstr[2] "Před %d minutami"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:896
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -92,7 +131,7 @@ msgstr[0] "Před %d hodinou"
msgstr[1] "Před %d hodinami"
msgstr[2] "Před %d hodinami"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:899
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -100,7 +139,7 @@ msgstr[0] "Před %d dnem"
msgstr[1] "Před %d dny"
msgstr[2] "Před %d dny"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:902
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -108,67 +147,17 @@ msgstr[0] "Před %d týdnem"
msgstr[1] "Před %d týdny"
msgstr[2] "Před %d týdny"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Neznámé"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nelze uzamknout obrazovku: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Šetřič obrazovky nelze dočasně nastavit na prázdnou obrazovku: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nelze se odhlásit: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informace o účtu..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Postranní lišta"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Předvolby systému..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Uzamknout obrazovku"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Přepnout uživatele"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Odhlásit..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Vypnout..."
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Domovská složka"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Systém souborů"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Hledat"
@ -177,11 +166,62 @@ msgstr "Hledat"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Frequent"
#~ msgstr "Časté"
#~ msgid "More"
#~ msgstr "Více"
#~ msgid "(see all)"
#~ msgstr "(zobrazit vše)"
#~ msgid "PLACES"
#~ msgstr "MÍSTA"
#~ msgid "SEARCH RESULTS"
#~ msgstr "VÝSLEDKY HLEDÁNÍ"
#~ msgid "Unknown"
#~ msgstr "Neznámé"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Nelze uzamknout obrazovku: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr "Šetřič obrazovky nelze dočasně nastavit na prázdnou obrazovku: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "Nelze se odhlásit: %s"
#~ msgid "Account Information..."
#~ msgstr "Informace o účtu..."
#~ msgid "Sidebar"
#~ msgstr "Postranní lišta"
#~ msgid "System Preferences..."
#~ msgstr "Předvolby systému..."
#~ msgid "Lock Screen"
#~ msgstr "Uzamknout obrazovku"
#~ msgid "Switch User"
#~ msgstr "Přepnout uživatele"
#~ msgid "Log Out..."
#~ msgstr "Odhlásit..."
#~ msgid "Shut Down..."
#~ msgstr "Vypnout..."
#~ msgid "Browse"
#~ msgstr "Procházet"
#~ msgid "Manager"
#~ msgstr "Správce"

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
"POT-Creation-Date: 2009-10-21 22:51+0200\n"
"PO-Revision-Date: 2009-10-18 17:32+0200\n"
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"MIME-Version: 1.0\n"
@ -24,80 +24,123 @@ msgstr "Skal til GNOME"
msgid "Window management and application launching"
msgstr "Vinduehåndtering og åbning af programmer"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Aktiviteter"
#: ../js/ui/appDisplay.js:332
msgid "Frequent"
msgstr "Ofte"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/appIcon.js:410
msgid "New Window"
msgstr "Nyt vindue"
#: ../js/ui/dash.js:256
#: ../js/ui/appIcon.js:414
msgid "Remove from Favorites"
msgstr "Fjern fra favoritter"
#: ../js/ui/appIcon.js:415
msgid "Add to Favorites"
msgstr "Tilføj til favoritter"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Find..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Gennemse"
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Mere"
#: ../js/ui/dash.js:511
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(se alle)"
#. **** Applications ****
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
#: ../js/ui/dash.js:725 ../js/ui/dash.js:787
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:725
#: ../js/ui/dash.js:745
msgid "PLACES"
msgstr "STEDER"
#. **** Documents ****
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
#: ../js/ui/dash.js:752 ../js/ui/dash.js:797
msgid "RECENT DOCUMENTS"
msgstr "SENESTE DOKUMENTER"
#. **** Search Results ****
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
#: ../js/ui/dash.js:777 ../js/ui/dash.js:961
msgid "SEARCH RESULTS"
msgstr "SØGERESULTATER"
#: ../js/ui/runDialog.js:82
#: ../js/ui/dash.js:792
msgid "PREFERENCES"
msgstr "INDSTILLINGER"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "Forbind til..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Indtast en kommando:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Kørsel af \"%s\" mislykkedes:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Programmer"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Seneste dokumenter"
#: ../src/shell-global.c:812
msgid "Less than a minute ago"
msgstr "Mindre end et minut siden"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:815
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minut siden"
msgstr[1] "%d minutter siden"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:818
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d time siden"
msgstr[1] "%d timer siden"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:821
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag siden"
msgstr[1] "%d dage siden"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:824
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -178,6 +221,9 @@ msgstr "Søg"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Browse"
#~ msgstr "Gennemse"
#~ msgid "Find apps or documents"
#~ msgstr "Find programmer eller dokumenter"

256
po/de.po
View File

@ -4,18 +4,21 @@
#
# Hendrik Brandt <heb@gnome-de.org>, 2009.
# Hendrik Richter <hendrikr@gnome.org>, 2009.
# Christian Kirbach <Christian.Kirbach@googlemail.com>, 2009.
# Mario Blättermann <mariobl@gnome.org>, 2009, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-20 16:47+0200\n"
"PO-Revision-Date: 2009-08-20 16:49+0200\n"
"Last-Translator: Hendrik Richter <hendrikr@gnome.org>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2010-01-07 23:31+0000\n"
"PO-Revision-Date: 2010-01-15 16:54+0100\n"
"Last-Translator: Mario Blättermann <mariobl@gnome.org>\n"
"Language-Team: German <gnome-de@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
@ -26,148 +29,137 @@ msgstr "GNOME-Shell"
msgid "Window management and application launching"
msgstr "Fenster verwalten und Anwendungen starten"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Aktivitäten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:251
msgid "Find apps or documents"
msgstr "Anwendungen oder Dokumente suchen"
#: ../js/ui/dash.js:369
msgid "Browse"
msgstr "Durchsuchen"
#. **** Applications ****
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "ANWENDUNGEN"
#. **** Documents ****
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
msgid "RECENT DOCUMENTS"
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "EINSTELLUNGEN"
#: ../js/ui/appDisplay.js:707 ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "Neues Fenster"
#: ../js/ui/appDisplay.js:711 ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Aus Favoriten entfernen"
#: ../js/ui/appDisplay.js:712 ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Zu Favoriten hinzufügen"
#: ../js/ui/appDisplay.js:1064
msgid "Drag here to add favorites"
msgstr "Hier ablegen, um zu Favoriten hinzuzufügen"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "Suchen …"
#: ../js/ui/dash.js:493
#| msgid "Search"
msgid "Searching..."
msgstr "Suche läuft …"
#: ../js/ui/dash.js:507
msgid "No matching results."
msgstr "Keine passenden Ergebnisse."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:598
msgid "PLACES"
msgstr "ORTE"
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "ORTE UND GERÄTE"
#: ../js/ui/runDialog.js:75
#. **** Documents ****
#: ../js/ui/dash.js:892
#| msgid "RECENT DOCUMENTS"
msgid "RECENT ITEMS"
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Aktivitäten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Verbinden mit …"
#: ../js/ui/runDialog.js:235
msgid "Please enter a command:"
msgstr "Bitte geben Sie einen Befehl ein:"
#: ../src/gdmuser/gdm-user.c:243
msgid "Manager"
msgstr "Verwaltung"
#: ../js/ui/runDialog.js:351
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Ausführung von »%s« ist gescheitert:"
#: ../src/gdmuser/gdm-user.c:244
msgid "The user manager object this user is controlled by."
msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../src/shell-global.c:841
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Anwendungen"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Zuletzt geöffnete Dokumente"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Vor weniger als einer Minute"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:893
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Vor %d Minute"
msgstr[1] "Vor %d Minuten"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:896
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Vor %d Stunde"
msgstr[1] "Vor %d Stunden"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:899
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Vor %d Tag"
msgstr[1] "Vor %d Tagen"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:902
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Vor %d Woche"
msgstr[1] "Vor %d Wochen"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Unbekannt"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Bildschirm kann nicht gesperrt werden: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Der Bildschirmschoner kann vorübergehend nicht auf einen leeren Schirm "
"gesetzt werden: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Abmelden ist nicht möglich: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Benutzerinformationen …"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Seitenleiste"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systemeinstellungen …"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bildschirm sperren"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Benutzer wechseln"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Abmelden …"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Ausschalten …"
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Persönlicher Ordner"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Dateisystem"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Suchen"
@ -176,7 +168,69 @@ msgstr "Suchen"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Frequent"
#~ msgstr "Häufig"
#~ msgid "More"
#~ msgstr "Mehr"
#~ msgid "(see all)"
#~ msgstr "(alle sehen)"
#~ msgid "PLACES"
#~ msgstr "ORTE"
#~ msgid "SEARCH RESULTS"
#~ msgstr "SUCHERGEBNISSE"
#~ msgid "Unknown"
#~ msgstr "Unbekannt"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Bildschirm kann nicht gesperrt werden: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr ""
#~ "Der Bildschirmschoner kann vorübergehend nicht auf einen leeren Schirm "
#~ "gesetzt werden: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "Abmelden ist nicht möglich: %s"
#~ msgid "Account Information..."
#~ msgstr "Benutzerinformationen …"
#~ msgid "Sidebar"
#~ msgstr "Seitenleiste"
#~ msgid "System Preferences..."
#~ msgstr "Systemeinstellungen …"
#~ msgid "Lock Screen"
#~ msgstr "Bildschirm sperren"
#~ msgid "Switch User"
#~ msgstr "Benutzer wechseln"
#~ msgid "Log Out..."
#~ msgstr "Abmelden …"
#~ msgid "Shut Down..."
#~ msgstr "Ausschalten …"
#~ msgid "Find apps or documents"
#~ msgstr "Anwendungen oder Dokumente suchen"
#~ msgid "Browse"
#~ msgstr "Durchsuchen"
#~ msgid "Manager"
#~ msgstr "Verwaltung"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."

186
po/el.po Normal file
View File

@ -0,0 +1,186 @@
# translation of gnome-shell.po.master.po to Greek
# Greek translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
#
# Jennie Petoumenou <epetoumenou@gmail.com>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell.po.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n"
"POT-Creation-Date: 2009-10-04 08:03+0000\n"
"PO-Revision-Date: 2009-10-04 10:25+0200\n"
"Last-Translator: Jennie Petoumenou <epetoumenou@gmail.com>\n"
"Language-Team: Greek <<team AT BLOCKSPAM gnome DOT gr>>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Κέλυφος GNOME"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Διαχείριση παραθύρων και εκκίνηση εφαρμογών"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Δραστηριότητες"
#. Translators: This is a time format.
#: ../js/ui/panel.js:461
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Εύρεση..."
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Περισσότερα"
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(εμφάνιση όλων)"
#. **** Applications ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "ΕΦΑΡΜΟΓΕΣ"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:783
msgid "PLACES"
msgstr "ΤΟΠΟΘΕΣΙΕΣ"
#. **** Documents ****
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "ΠΡΟΣΦΑΤΑ ΕΓΓΡΑΦΑ"
#. **** Search Results ****
#: ../js/ui/dash.js:815 ../js/ui/dash.js:955
msgid "SEARCH RESULTS"
msgstr "ΑΠΟΤΕΛΕΣΜΑΤΑ ΑΝΑΖΗΤΗΣΗΣ"
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "ΠΡΟΤΙΜΗΣΕΙΣ"
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Παρακαλώ εισάγετε μία εντολή:"
#: ../src/shell-global.c:812
msgid "Less than a minute ago"
msgstr "Λιγότερο από ένα λεπτό πριν"
#: ../src/shell-global.c:815
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d λεπτό πριν"
msgstr[1] "%d λεπτά πριν"
#: ../src/shell-global.c:818
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ώρα πριν"
msgstr[1] "%d ώρες πριν"
#: ../src/shell-global.c:821
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d ημέρα πριν"
msgstr[1] "%d ημέρες πριν"
#: ../src/shell-global.c:824
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d εβδομάδα πριν"
msgstr[1] "%d εβδομάδες πριν"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Άγνωστο"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Αδύνατο το κλείδωμα της οθόνης: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Δεν είναι δυνατή η προσωρινή ρύθμιση της προστασίας οθόνης σε κενή οθόνη: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Αδύνατη η αποσύνδεση: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Πληροφορίες λογαριασμού..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Πλευρική στήλη"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Προστιμήσεις συστήματος..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Κλείδωμα οθόνης"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Αλλαγή χρήστη"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Αποσύνδεση..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Τερματισμός..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Προσωπικός φάκελος"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Σύστημα αρχείων"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Αναζήτηση"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

301
po/es.po
View File

@ -1,20 +1,19 @@
# Spanish translation of gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
#
# Jorge González <jorgegonz@svn.gnome.org>, 2009.
# Jorge González <jorgegonz@svn.gnome.org>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-11 21:48+0000\n"
"PO-Revision-Date: 2009-09-12 14:40+0200\n"
"POT-Creation-Date: 2010-02-15 13:36+0000\n"
"PO-Revision-Date: 2010-02-15 21:45+0100\n"
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
"Language-Team: Español <gnome-es-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
@ -25,153 +24,223 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Gestión de ventanas e inicio de aplicaciones"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "APLICACIONES"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/dash.js:283
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Ventana nueva"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Quitar de los favoritos"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Añadir a los favoritos"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Arrastrar aquí para añadir a los favoritos"
#: ../js/ui/appFavorites.js:89
#, c-format
msgid "%s has been added to your favorites."
msgstr "Se ha añadido %s a sus favoritos."
#: ../js/ui/appFavorites.js:107
#, c-format
#| msgid "Remove from Favorites"
msgid "%s has been removed from your favorites."
msgstr "Se ha quitado %s de sus favoritos."
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Buscar…"
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Examine"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Buscando…"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(ver todo)"
#. **** Applications ****
#: ../js/ui/dash.js:736 ../js/ui/dash.js:792
msgid "APPLICATIONS"
msgstr "APLICACIONES"
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "No se encontró ningún resultado coincidente."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:756
msgid "PLACES"
msgstr "LUGARES"
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "LUGARES Y DISPOSITIVOS"
#. **** Documents ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:802
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECIENTES"
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "ELEMENTOS RECIENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:782 ../js/ui/dash.js:907
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DE LA BÚSQUEDA"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "No hay extensiones instaladas"
#: ../js/ui/dash.js:797
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Activado"
#: ../js/ui/runDialog.js:90
#: ../js/ui/lookingGlass.js:395
msgid "Disabled"
msgstr "Desactivado"
#: ../js/ui/lookingGlass.js:397
msgid "Error"
msgstr "Error"
#: ../js/ui/lookingGlass.js:399
msgid "Out of date"
msgstr "Caducado"
#: ../js/ui/lookingGlass.js:424
msgid "View Source"
msgstr "Ver fuente"
#: ../js/ui/lookingGlass.js:430
msgid "Web Page"
msgstr "Página web"
#: ../js/ui/overview.js:95
msgid "Undo"
msgstr "Deshacer"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Actividades"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Conectar a…"
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Introduzca un comando:"
#: ../src/shell-global.c:799
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Falló la ejecución de «%s»:"
#: ../js/ui/statusMenu.js:107
msgid "Available"
msgstr "Disponible"
#: ../js/ui/statusMenu.js:112
msgid "Busy"
msgstr "Ocupado"
#: ../js/ui/statusMenu.js:117
msgid "Invisible"
msgstr "Invisible"
#: ../js/ui/statusMenu.js:126
msgid "Account Information..."
msgstr "Información de la cuenta…"
#: ../js/ui/statusMenu.js:132
msgid "Sidebar"
msgstr "Barra lateral"
#: ../js/ui/statusMenu.js:142
msgid "System Preferences..."
msgstr "Preferencias del sistema…"
#: ../js/ui/statusMenu.js:151
msgid "Lock Screen"
msgstr "Bloquear la pantalla"
#: ../js/ui/statusMenu.js:156
msgid "Switch User"
msgstr "Cambiar de usuario"
#: ../js/ui/statusMenu.js:162
msgid "Log Out..."
msgstr "Salir…"
#: ../js/ui/statusMenu.js:167
msgid "Shut Down..."
msgstr "Apagar…"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Aplicaciones"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documentos recientes"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Hace menos de un minuto"
#: ../src/shell-global.c:802
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Hace %d minuto"
msgstr[1] "Hace %d minutos"
#: ../src/shell-global.c:805
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Hace %d hora"
msgstr[1] "Hace %d horas"
#: ../src/shell-global.c:808
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Hace %d día"
msgstr[1] "Hace %d días"
#: ../src/shell-global.c:811
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Hace %d semana"
msgstr[1] "Hace %d semanas"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Desconocido"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "No se puede bloquear la pantalla: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"No se puede establecer temporalmente el salvapantallas a oscurecer pantalla: "
"%s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "No se puede salir de la sesión: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Información de la cuenta…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferencias del sistema…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bloquear la pantalla"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambiar de usuario"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Salir…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Apagar…"
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Carpeta personal"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Sistema de archivos"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Buscar"
@ -180,11 +249,43 @@ msgstr "Buscar"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "PLACES"
#~ msgstr "LUGARES"
#~ msgid "Frequent"
#~ msgstr "Frecuentes"
#~ msgid "More"
#~ msgstr "Más"
#~ msgid "(see all)"
#~ msgstr "(ver todo)"
#~ msgid "SEARCH RESULTS"
#~ msgstr "RESULTADOS DE LA BÚSQUEDA"
#~ msgid "Unknown"
#~ msgstr "Desconocido"
#~ msgid "Can't lock screen: %s"
#~ msgstr "No se puede bloquear la pantalla: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr ""
#~ "No se puede establecer temporalmente el salvapantallas a oscurecer "
#~ "pantalla: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "No se puede salir de la sesión: %s"
#~ msgid "Browse"
#~ msgstr "Examine"
#~ msgid "Find apps or documents"
#~ msgstr "Encuentre aplicaciones o documentos"

226
po/fi.po Normal file
View File

@ -0,0 +1,226 @@
# gnome-shell Finnish translation
# Copyright (C) 2009 Timo Jyrinki
# This file is distributed under the same license as the gnome-shell package.
# Timo Jyrinki <timo.jyrinki@iki.fi>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-11-04 11:16+0200\n"
"PO-Revision-Date: 2009-11-04 11:16+0200\n"
"Last-Translator: Timo Jyrinki <timo.jyrinki@iki.fi>\n"
"Language-Team: Finnish <gnome-fi-laatu@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr ""
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Ikkunanhallinta ja sovelluksien käynnistäminen"
#: ../js/ui/appDisplay.js:332
msgid "Frequent"
msgstr "Usein käytetyt"
#: ../js/ui/appDisplay.js:867
msgid "Drag here to add favorites"
msgstr "Raahaa tähän lisätäksesi suosikkeihin"
#: ../js/ui/appIcon.js:426
msgid "New Window"
msgstr "Uusi ikkuna"
#: ../js/ui/appIcon.js:430
msgid "Remove from Favorites"
msgstr "Poista suosikeista"
#: ../js/ui/appIcon.js:431
msgid "Add to Favorites"
msgstr "Lisää suosikkeihin"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Etsi..."
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Lisää"
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(näytä kaikki)"
#. **** Applications ****
#: ../js/ui/dash.js:725 ../js/ui/dash.js:787
msgid "APPLICATIONS"
msgstr "SOVELLUKSET"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:745
msgid "PLACES"
msgstr "SIJAINNIT"
#. **** Documents ****
#: ../js/ui/dash.js:752 ../js/ui/dash.js:797
msgid "RECENT DOCUMENTS"
msgstr "VIIMEISIMMÄT ASIAKIRJAT"
#. **** Search Results ****
#: ../js/ui/dash.js:777 ../js/ui/dash.js:961
msgid "SEARCH RESULTS"
msgstr "HAKUTULOKSET"
#: ../js/ui/dash.js:792
msgid "PREFERENCES"
msgstr "ASETUKSET"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "Toiminnot"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %I.%M"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "Yhdistä..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Syötä komento:"
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr ""
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%I.%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Sovellukset"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Viimeisimmät asiakirjat"
#: ../src/shell-global.c:821
msgid "Less than a minute ago"
msgstr "Alle minuutti sitten"
#: ../src/shell-global.c:824
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuutti sitten"
msgstr[1] "%d minuuttia sitten"
#: ../src/shell-global.c:827
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d tunti sitten"
msgstr[1] "%d tuntia sitten"
#: ../src/shell-global.c:830
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d päivä sitten"
msgstr[1] "%d päivää sitten"
#: ../src/shell-global.c:833
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d viikko sitten"
msgstr[1] "%d viikkoa sitten"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Tuntematon"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Näyttöä ei voi lukita: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr ""
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Käyttäjätilin tiedot..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sivupalkki"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Järjestelmän asetukset"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lukitse näyttö"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Vaihda käyttäjää"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Kirjaudu ulos..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Sammuta..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Kotikansio"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Tiedostojärjestelmä"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Haku"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

102
po/fr.po
View File

@ -6,13 +6,13 @@
#
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Project-Id-Version: gnome-shell master fr\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-09 21:30+0000\n"
"PO-Revision-Date: 2009-09-11 21:40+0200\n"
"Last-Translator: Mathieu Bridon <bochecha@fedoraproject.org>\n"
"Language-Team: GNOME French Team\n"
"POT-Creation-Date: 2009-11-13 17:44+0000\n"
"PO-Revision-Date: 2009-12-05 16:43+0100\n"
"Last-Translator: Pablo Martin-Gomez <pablo.martin-gomez@laposte.net>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -26,80 +26,115 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Gestion des fenêtres et lancement des applications"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Activités"
#: ../js/ui/appDisplay.js:696
msgid "Drag here to add favorites"
msgstr "Glisser ici pour ajouter aux favoris"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "Nouvelle fenêtre"
#: ../js/ui/dash.js:255
#: ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Enlever des favoris"
#: ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Ajouter aux favoris"
#: ../js/ui/dash.js:237
msgid "Find..."
msgstr "Rechercher..."
#: ../js/ui/dash.js:372
msgid "Browse"
msgstr "Parcourir"
#: ../js/ui/dash.js:508
msgid "(see all)"
msgstr "(tout afficher)"
#. **** Applications ****
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
#: ../js/ui/dash.js:656 ../js/ui/dash.js:718
msgid "APPLICATIONS"
msgstr "APPLICATIONS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:720
#: ../js/ui/dash.js:676 ../js/ui/dash.js:733
msgid "PLACES"
msgstr "RACCOURCIS"
#. **** Documents ****
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
#: ../js/ui/dash.js:683 ../js/ui/dash.js:728
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTS RÉCENTS"
#. **** Search Results ****
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
#: ../js/ui/dash.js:708 ../js/ui/dash.js:898
msgid "SEARCH RESULTS"
msgstr "RÉSULTATS DE LA RECHERCHE"
#: ../js/ui/runDialog.js:90
#: ../js/ui/dash.js:723
msgid "PREFERENCES"
msgstr "PRÉFÉRENCES"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "Activités"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/placeDisplay.js:84
msgid "Connect to..."
msgstr "Connexion à..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Veuillez saisir une commande :"
#: ../src/shell-global.c:799
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Exécution de « %s » impossible :"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Applications"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documents récents"
#: ../src/shell-global.c:821
msgid "Less than a minute ago"
msgstr "Il y a moins d'une minute"
#: ../src/shell-global.c:802
#: ../src/shell-global.c:824
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Il y a %d minute"
msgstr[1] "Il y a %d minutes"
#: ../src/shell-global.c:805
#: ../src/shell-global.c:827
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Il y a %d heure"
msgstr[1] "Il y a %d heures"
#: ../src/shell-global.c:808
#: ../src/shell-global.c:830
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Il y a %d jour"
msgstr[1] "Il y a %d jours"
#: ../src/shell-global.c:811
#: ../src/shell-global.c:833
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -180,3 +215,6 @@ msgstr "Recherche"
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s : %2$s"
#~ msgid "Browse"
#~ msgstr "Parcourir"

240
po/gl.po
View File

@ -2,19 +2,22 @@
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Fran Diéguez <fran.dieguez@mabishu.com>, 2009.
#
# Anton Meixome <certima@certima.net>, 2009.
# Antón Méixome <meixome@certima.net>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
"Language-Team: Galician <gnome@mancomun.org>\n"
"POT-Creation-Date: 2009-12-28 17:07+0100\n"
"PO-Revision-Date: 2009-12-28 08:11+0100\n"
"Last-Translator: Antón Méixome <meixome@certima.net>\n"
"Language-Team: Galician Proxecto Trasno <proxecto@trasno.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: gl\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Virtaal 0.4.0\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
@ -22,154 +25,133 @@ msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Xestor de xanelas e lanzado de aplicativos"
msgstr "Xestor de xanelas e lanzamento de aplicativos"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:858
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/dash.js:283
#: ../js/ui/appDisplay.js:707 ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "Xanela nova"
#: ../js/ui/appDisplay.js:711 ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Eliminar de Favoritos"
#: ../js/ui/appDisplay.js:712 ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Engadir a Favoritos"
#: ../js/ui/appDisplay.js:1064
msgid "Drag here to add favorites"
msgstr "Arrastra aquí para engadir favoritos"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "Buscar..."
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Explorar"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(ver todos)"
#. **** Applications ****
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#: ../js/ui/dash.js:437
msgid "Searching..."
msgstr "Buscando..."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:773
#: ../js/ui/dash.js:878 ../js/ui/placeDisplay.js:519
msgid "PLACES"
msgstr "LUGARES"
#. **** Documents ****
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
#: ../js/ui/dash.js:885
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DA BÚSQUEDA"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:227
msgid "Activities"
msgstr "Actividades"
#: ../js/ui/dash.js:814
msgid "PREFERENCES"
msgstr ""
#. Translators: This is a time format.
#: ../js/ui/panel.js:440
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/runDialog.js:96
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Conectar con..."
#: ../js/ui/runDialog.js:235
msgid "Please enter a command:"
msgstr "Insira unha orde:"
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Menos de un minuto"
#: ../js/ui/runDialog.js:351
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Fallou a execución de %s"
#: ../src/shell-global.c:802
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Aplicativos"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documentos recentes"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Hai menos dun minuto"
#: ../src/shell-global.c:893
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "fai %d minuto"
msgstr[1] "fai %d minutos"
msgstr[0] "hai %d minuto"
msgstr[1] "hai %d minutos"
#: ../src/shell-global.c:805
#: ../src/shell-global.c:896
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "fai %d hora"
msgstr[1] "fai %d horas"
msgstr[0] "hai %d hora"
msgstr[1] "hai %d horas"
#: ../src/shell-global.c:808
#: ../src/shell-global.c:899
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "fai %d día"
msgstr[1] "fai %d días"
msgstr[0] "hai %d día"
msgstr[1] "hai %d días"
#: ../src/shell-global.c:811
#: ../src/shell-global.c:902
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "fai %d semana"
msgstr[1] "fai %d semanas"
msgstr[0] "hai %d semana"
msgstr[1] "hai %d semanas"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Descoñecido"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Non foi posíbel bloquear a pantalla: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Non foi posíbel establecer o salvapantallas a unha pantalla en branco: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Non foi posíbel pechar a sesión: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Información da conta..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferenzas do sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bloquear pantalla"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambiar de usuario"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Pechar sesión..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Apagar..."
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Cartafol persoal"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Sistema de ficheiros"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Buscar"
@ -178,11 +160,55 @@ msgstr "Buscar"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "SEARCH RESULTS"
#~ msgstr "RESULTADOS DA BUSCA"
#~ msgid "Unknown"
#~ msgstr "Descoñecido"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Non foi posíbel bloquear a pantalla: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr ""
#~ "Non foi posíbel estabelecer temporalmente o salvapantallas a unha "
#~ "pantalla en branco: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "Non foi posíbel pechar a sesión: %s"
#~ msgid "Account Information..."
#~ msgstr "Información da conta..."
#~ msgid "Sidebar"
#~ msgstr "Barra lateral"
#~ msgid "System Preferences..."
#~ msgstr "Preferencias do sistema..."
#~ msgid "Lock Screen"
#~ msgstr "Bloquear pantalla"
#~ msgid "Switch User"
#~ msgstr "Cambiar de usuario"
#~ msgid "Log Out..."
#~ msgstr "Saír da sesión..."
#~ msgid "Shut Down..."
#~ msgstr "Apagar..."
#~ msgid "Browse"
#~ msgstr "Explorar"
#~ msgid "(see all)"
#~ msgstr "(ver todos)"
#~ msgid "Find apps or documents"
#~ msgstr "Atopar aplicativos ou documentos"

215
po/he.po Normal file
View File

@ -0,0 +1,215 @@
# Hebrew translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# liel <lielft@gmail.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-11-13 17:44+0000\n"
"PO-Revision-Date: 2009-11-28 17:33+0200\n"
"Last-Translator: Liel Fridman <lielft@gmail.com>\n"
"Language-Team: Hebrew <he@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "מעטפת GNOME"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "ניהול חלונות והרצת יישומים"
#: ../js/ui/appDisplay.js:696
msgid "Drag here to add favorites"
msgstr "יש לגרור פריטים לכאן כדי להוסיף מועדפים"
#: ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "חלון חדש"
#: ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "הסר מהמועדפים"
#: ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "הוסף למועדפים"
#: ../js/ui/dash.js:237
msgid "Find..."
msgstr "חפש..."
#. **** Applications ****
#: ../js/ui/dash.js:656 ../js/ui/dash.js:718
msgid "APPLICATIONS"
msgstr "יישומים"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:676 ../js/ui/dash.js:733
msgid "PLACES"
msgstr "מקומות"
#. **** Documents ****
#: ../js/ui/dash.js:683 ../js/ui/dash.js:728
msgid "RECENT DOCUMENTS"
msgstr "מסמכים אחרונים"
#. **** Search Results ****
#: ../js/ui/dash.js:708 ../js/ui/dash.js:898
msgid "SEARCH RESULTS"
msgstr "תוצאות חיפוש"
#: ../js/ui/dash.js:723
msgid "PREFERENCES"
msgstr "העדפות"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "פעילויות"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/placeDisplay.js:84
msgid "Connect to..."
msgstr "התחבר אל..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "נא להזין פקודה:"
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "ההרצה של '%s' נכשלה:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "יישומים"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "מסמכים אחרונים"
#: ../src/shell-global.c:821
msgid "Less than a minute ago"
msgstr "לפני פחות מדקה"
#: ../src/shell-global.c:824
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "לפני דקה"
msgstr[1] "לפני %d דקות"
#: ../src/shell-global.c:827
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "לפני שעה"
msgstr[1] "לפני %d שעות"
#: ../src/shell-global.c:830
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "לפני יום"
msgstr[1] "לפני %d ימים"
#: ../src/shell-global.c:833
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "לפני שבוע"
msgstr[1] "לפני %d שבועות"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "לא ידוע"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "לא ניתן לנעול את המסך: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "לא ניתן זמנית לקבוע שומר מסך כמסך שחור: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "לא ניתן להתנתק: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "מידע על המשתמש..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "סרגל צד"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "העדפות מערכת..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "נעילת המסך"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "החלף משתמש"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "ניתוק..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "כיבוי..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "תיקיית הבית"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "מערכת הקבצים"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "חפש"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

348
po/hu.po
View File

@ -2,13 +2,13 @@
# Copyright 2009. Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
#
# Gabor Kelemen <kelemeng at gnome dot hu>, 2009.
# Gabor Kelemen <kelemeng at gnome dot hu>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-15 11:35+0200\n"
"PO-Revision-Date: 2009-08-15 11:35+0200\n"
"POT-Creation-Date: 2010-02-16 10:04+0100\n"
"PO-Revision-Date: 2010-02-16 10:10+0100\n"
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
"Language-Team: Hungarian <gnome at fsf dot hu>\n"
"MIME-Version: 1.0\n"
@ -17,135 +17,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Tevékenységek"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
msgid "%a %l:%M %p"
msgstr "%a., %k.%M"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Alkalmazások vagy dokumentumok keresése"
#: ../js/ui/dash.js:336
msgid "Browse"
msgstr "Tallózás"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
msgid "APPLICATIONS"
msgstr "ALKALMAZÁSOK"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "LEGUTÓBBI DOKUMENTUMOK"
#. **** Places ****
#: ../js/ui/dash.js:563
msgid "PLACES"
msgstr "HELYEK"
#: ../js/ui/runDialog.js:74
msgid "Please enter a command:"
msgstr "Adjon meg egy parancsot:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Kezelő"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "A felhasználót kezelő felhasználókezelő objektum."
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Kevesebb, mint egy perce"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d perce"
msgstr[1] "%d perce"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d órája"
msgstr[1] "%d órája"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d napja"
msgstr[1] "%d napja"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d hete"
msgstr[1] "%d hete"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Ismeretlen"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nem lehet zárolni a képernyőt: %s "
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Átmenetileg nem lehet beállítani a képernyővédőt a képernyő elsötétítésére: %"
"s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nem lehet kijelentkezni: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Fiókinformációk…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Oldalsáv"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Rendszerbeállítások…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Képernyő zárolása"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Felhasználóváltás"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Kijelentkezés…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Leállítás…"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
@ -154,17 +25,222 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Ablakkezelés és alkalmazásindítás"
#: ../src/shell-uri-util.c:87
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "ALKALMAZÁSOK"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "BEÁLLÍTÁSOK"
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Új ablak"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Eltávolítás a Kedvencek közül"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Hozzáadás a Kedvencekhez"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Ide húzással kedvenceket vehet fel"
#: ../js/ui/appFavorites.js:89
#, c-format
msgid "%s has been added to your favorites."
msgstr "%s felvéve a Kedvencek közé."
#: ../js/ui/appFavorites.js:107
#, c-format
msgid "%s has been removed from your favorites."
msgstr "%s eltávolítva a Kedvencek közül"
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Keresés…"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Keresés…"
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "Nincs találat."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "HELYEK ÉS ESZKÖZÖK"
#. **** Documents ****
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "LEGUTÓBBI ELEMEK"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "Nincsenek kiterjesztések telepítve"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Engedélyezve"
#: ../js/ui/lookingGlass.js:395
msgid "Disabled"
msgstr "Tiltva"
#: ../js/ui/lookingGlass.js:397
msgid "Error"
msgstr "Hiba"
#: ../js/ui/lookingGlass.js:399
msgid "Out of date"
msgstr "Elavult"
#: ../js/ui/lookingGlass.js:424
msgid "View Source"
msgstr "Forrás megtekintése"
#: ../js/ui/lookingGlass.js:430
msgid "Web Page"
msgstr "Weblap"
#: ../js/ui/overview.js:92
msgid "Undo"
msgstr "Visszavonás"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Tevékenységek"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a, %p %l.%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Kapcsolódás…"
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Adjon meg egy parancsot:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "„%s” végrehajtása meghiúsult:"
#: ../js/ui/statusMenu.js:107
msgid "Available"
msgstr "Elérhető"
#: ../js/ui/statusMenu.js:112
msgid "Busy"
msgstr "Elfoglalt"
#: ../js/ui/statusMenu.js:117
msgid "Invisible"
msgstr "Láthatatlan"
#: ../js/ui/statusMenu.js:126
msgid "Account Information..."
msgstr "Fiókinformációk…"
#: ../js/ui/statusMenu.js:132
msgid "Sidebar"
msgstr "Oldalsáv"
#: ../js/ui/statusMenu.js:142
msgid "System Preferences..."
msgstr "Rendszerbeállítások…"
#: ../js/ui/statusMenu.js:151
msgid "Lock Screen"
msgstr "Képernyő zárolása"
#: ../js/ui/statusMenu.js:156
msgid "Switch User"
msgstr "Felhasználóváltás"
#: ../js/ui/statusMenu.js:162
msgid "Log Out..."
msgstr "Kijelentkezés…"
#: ../js/ui/statusMenu.js:167
msgid "Shut Down..."
msgstr "Leállítás…"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%k.%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Alkalmazások"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Legutóbbi dokumentumok"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Kevesebb, mint egy perce"
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d perce"
msgstr[1] "%d perce"
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d órája"
msgstr[1] "%d órája"
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d napja"
msgstr[1] "%d napja"
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d hete"
msgstr[1] "%d hete"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Saját mappa"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Fájlrendszer"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Oldalsáv"
@ -173,7 +249,7 @@ msgstr "Oldalsáv"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

249
po/it.po
View File

@ -1,15 +1,14 @@
# Italian translations for gnome-shell package.
# Copyright (C) 2009 the gnome-shell copyright holder
# This file is distributed under the same license as the gnome-shell package.
# Milo Casagrande <milo@ubuntu.com>, 2009.
#
# Milo Casagrande <milo@ubuntu.com>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-02-10 22:30+0100\n"
"PO-Revision-Date: 2010-02-10 22:31+0100\n"
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
"Language-Team: Italian <tp@lists.linux.it>\n"
"MIME-Version: 1.0\n"
@ -25,151 +24,136 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Gestione finestre e avvio applicazioni"
#. left side
#: ../js/ui/panel.js:271
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "Applicazioni"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "Preferenze"
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Nuova finestra"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Rimuovi dai preferiti"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Aggiungi ai preferiti"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Trascinare qui per aggiungere ai preferiti"
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Trova..."
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Ricerca..."
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "Nessun risultato."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "Risorse e dispositivi"
#. **** Documents ****
#: ../js/ui/dash.js:907
msgid "RECENT ITEMS"
msgstr "Elementi recenti"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Attività"
# (ndt) proviamo col k, se non funge, sappiamo il perché...
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
#: ../js/ui/panel.js:557
msgid "%a %l:%M %p"
msgstr "%a %k.%M"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Trova..."
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Connetti a..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Esplora"
#: ../js/ui/dash.js:511
msgid "(see all)"
msgstr "(vedi tutto)"
#. **** Applications ****
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
msgid "APPLICATIONS"
msgstr "Applicazioni"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:725
msgid "PLACES"
msgstr "Risorse"
#. **** Documents ****
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
msgid "RECENT DOCUMENTS"
msgstr "Documenti recenti"
#. **** Search Results ****
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
msgid "SEARCH RESULTS"
msgstr "Risultati ricerca"
#: ../js/ui/runDialog.js:82
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Inserire un comando:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Esecuzione di «%s» non riuscita:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%k.%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Applicazioni"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documenti recenti"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Meno di un minuto fa"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuto fa"
msgstr[1] "%d minuti fa"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ora fa"
msgstr[1] "%d ore fa"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d giorno fa"
msgstr[1] "%d giorni fa"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d settimana fa"
msgstr[1] "%d settimane fa"
# (ndt) valutare se vada al femminile
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Sconosciuto"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Impossibile bloccare lo schermo: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Impossibile impostare temporaneamente il salva schermo a schermo nero: %s "
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Impossibile terminare la sessione: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informazioni account..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra laterale"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferenze di sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Blocca schermo"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambia utente"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Termina sessione..."
# (ndt) da valutare... pare che ora anche Windows usi 'Arresta...'...
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Spegni..."
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Cartella home"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "File system"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Cerca"
@ -179,19 +163,58 @@ msgstr "Cerca"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
#~ msgid "Find apps or documents"
#~ msgstr "Trova programmi e documenti"
#~ msgid "PLACES"
#~ msgstr "Risorse"
# (ndt) no idea...
#~ msgid "Manager"
#~ msgstr "Manager"
#~ msgid "Frequent"
#~ msgstr "Frequente"
# (ndt) no idea...
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "L'oggetto user manager che controlla questo utente."
#~ msgid "More"
#~ msgstr "Altro"
#~ msgid "(see all)"
#~ msgstr "(vedi tutto)"
#~ msgid "SEARCH RESULTS"
#~ msgstr "Risultati ricerca"
# (ndt) valutare se vada al femminile
#~ msgid "Unknown"
#~ msgstr "Sconosciuto"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Impossibile bloccare lo schermo: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr ""
#~ "Impossibile impostare temporaneamente il salva schermo a schermo nero: %s "
#~ msgid "Can't logout: %s"
#~ msgstr "Impossibile terminare la sessione: %s"
#~ msgid "Account Information..."
#~ msgstr "Informazioni account..."
#~ msgid "Sidebar"
#~ msgstr "Barra laterale"
#~ msgid "System Preferences..."
#~ msgstr "Preferenze di sistema..."
#~ msgid "Lock Screen"
#~ msgstr "Blocca schermo"
#~ msgid "Switch User"
#~ msgstr "Cambia utente"
#~ msgid "Log Out..."
#~ msgstr "Termina sessione..."
# (ndt) da valutare... pare che ora anche Windows usi 'Arresta...'...
#~ msgid "Shut Down..."
#~ msgstr "Spegni..."

182
po/nb.po
View File

@ -1,14 +1,14 @@
# Norwegian bokmål translation of gnome-shell.
# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Kjartan Maraas <kmaraas@broadpark.no>, 2009.
# Kjartan Maraas <kmaraas@broadpark.no>, 2009-2010.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 0.4\n"
"Project-Id-Version: gnome-shell 2.28.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-21 12:36+0200\n"
"PO-Revision-Date: 2009-08-21 12:44+0200\n"
"POT-Creation-Date: 2010-02-14 13:45+0100\n"
"PO-Revision-Date: 2010-02-14 13:46+0100\n"
"Last-Translator: Kjartan Maraas <kmaraas@broadpark.no>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"MIME-Version: 1.0\n"
@ -24,138 +24,140 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Vindushåndtering og oppstart av programmer"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%a %l:%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Finn programmer eller dokumenter"
#: ../js/ui/dash.js:368
msgid "Browse"
msgstr "Bla gjennom"
#. **** Applications ****
#: ../js/ui/dash.js:504 ../js/ui/dash.js:577
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#. **** Documents ****
#: ../js/ui/dash.js:509 ../js/ui/dash.js:604
msgid "RECENT DOCUMENTS"
msgstr "SISTE DOKUMENTER"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "BRUKERVALG"
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Nytt vindu"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Fjern fra favoritter"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Legg til i favoritter"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Dra hit for å legge til favoritter"
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Finn..."
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Søker..."
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "Ingen treff."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:597
msgid "PLACES"
msgstr "STEDER"
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "STEDER & ENHETER"
#: ../js/ui/runDialog.js:75
#. **** Documents ****
#: ../js/ui/dash.js:907
msgid "RECENT ITEMS"
msgstr "SISTE OPPFØRINGER"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Koble til..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Oppgi en kommando:"
#: ../src/shell-global.c:841
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Kjøring av «%s» feilet:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Programmer"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Siste dokumenter"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Mindre enn ett minutt siden"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minutt siden"
msgstr[1] "%d minutter siden"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d time siden"
msgstr[1] "%d timer siden"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag siden"
msgstr[1] "%d dager siden"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d uke siden"
msgstr[1] "%d uker siden"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Ukjent"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan ikke låse skjermen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan ikke sette skjermsparer midlertidig til blank skjerm: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan ikke logge ut: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Kontoinformasjon..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidelinje"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Brukervalg for systemet..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lås skjerm"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Bytt bruker"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Logg ut..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Slå av..."
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Hjemmemappe"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Filsystem"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Søk"
@ -164,7 +166,7 @@ msgstr "Søk"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

View File

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
"cgi?product=gnome-shell&component=general\n"
"POT-Creation-Date: 2009-08-31 22:31+0000\n"
"PO-Revision-Date: 2009-09-01 06:51+0530\n"
"POT-Creation-Date: 2009-10-09 22:10+0000\n"
"PO-Revision-Date: 2009-10-15 06:18+0530\n"
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\n"
"MIME-Version: 1.0\n"
@ -26,80 +26,123 @@ msgstr "ਗਨੋਮ ਸ਼ੈਲ"
msgid "Window management and application launching"
msgstr "ਵਿੰਡੋ ਪਰਬੰਧ ਅਤੇ ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਓ"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "ਸਰਗਰਮੀਆਂ"
#: ../js/ui/appDisplay.js:335
msgid "Frequent"
msgstr "ਅਕਸਰ"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/appIcon.js:462
msgid "New Window"
msgstr "ਨਵੀਂ ਵਿੰਡੋ"
#: ../js/ui/dash.js:256
#: ../js/ui/appIcon.js:475
msgid "Remove from Favorites"
msgstr "ਪਸੰਦ ਵਿੱਚੋਂ ਹਟਾਓ"
#: ../js/ui/appIcon.js:476
msgid "Add to Favorites"
msgstr "ਪਸੰਦ 'ਚ ਸ਼ਾਮਲ ਕਰੋ"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "ਖੋਜ..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "ਝਲਕ"
#: ../js/ui/dash.js:400
msgid "More"
msgstr "ਹੋਰ"
#: ../js/ui/dash.js:451
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(ਸਭ ਵੇਖੋ)"
#. **** Applications ****
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
#: ../js/ui/dash.js:783
msgid "PLACES"
msgstr "ਥਾਵਾਂ"
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
#. **** Search Results ****
#: ../js/ui/dash.js:679
#: ../js/ui/dash.js:815 ../js/ui/dash.js:955
msgid "SEARCH RESULTS"
msgstr "ਖੋਜ ਨਤੀਜੇ"
#: ../js/ui/runDialog.js:82
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "ਪਸੰਦ"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:272
msgid "Activities"
msgstr "ਸਰਗਰਮੀਆਂ"
#. Translators: This is a time format.
#: ../js/ui/panel.js:464
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "...ਨਾਲ ਕੁਨੈਕਟ ਕਰੋ"
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "'%s' ਚਲਾਉਣ ਲਈ ਫੇਲ੍ਹ:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:162
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:316
msgid "Applications"
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
#: ../js/ui/widget.js:341
msgid "Recent Documents"
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
#: ../src/shell-global.c:812
msgid "Less than a minute ago"
msgstr "ਇੱਕ ਮਿੰਟ ਤੋਂ ਘੱਟ ਚਿਰ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:815
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:818
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:821
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:824
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -180,3 +223,5 @@ msgstr "ਖੋਜ"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Browse"
#~ msgstr "ਝਲਕ"

View File

@ -2,91 +2,139 @@
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Og Maciel <ogmaciel@gnome.org>, 2009.
# Rodrigo Flores <mail@rodrigoflores.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-14 17:53-0400\n"
"PO-Revision-Date: 2009-08-14 17:53-0400\n"
"Last-Translator: Og Maciel <ogmaciel@gnome.org>\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-11-12 21:33+0000\n"
"PO-Revision-Date: 2009-11-14 11:53-0200\n"
"Last-Translator: Amanda Magalhães <amandinhakee@gmail.com>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. left side
#: ../js/ui/panel.js:266
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Gerenciamento de janelas e lançador de aplicações"
#: ../js/ui/appDisplay.js:696
msgid "Drag here to add favorites"
msgstr "Arraste até aqui para adicionar aos favoritos"
#: ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "Nova janela"
#: ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Remover dos Favoritos"
#: ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Adicionar aos Favoritos"
#: ../js/ui/dash.js:237
msgid "Find..."
msgstr "Procurar..."
#. **** Applications ****
#: ../js/ui/dash.js:656 ../js/ui/dash.js:718
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:676 ../js/ui/dash.js:733
msgid "PLACES"
msgstr "LOCAIS"
#. **** Documents ****
#: ../js/ui/dash.js:683 ../js/ui/dash.js:728
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:708 ../js/ui/dash.js:898
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DA BUSCA"
#: ../js/ui/dash.js:723
msgid "PREFERENCES"
msgstr "PREFERÊNCIAS"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "Atividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Localizar aplicativos ou documentos"
#: ../js/ui/placeDisplay.js:84
msgid "Connect to..."
msgstr "Conectar ao..."
#: ../js/ui/dash.js:336
msgid "Browse"
msgstr "Navegar"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Places ****
#: ../js/ui/dash.js:563
msgid "PLACES"
msgstr "LOCAIS"
#: ../js/ui/runDialog.js:74
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Por favor digite um comando:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Gerenciador"
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "A execução de \"%s\" falhou:"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "O objeto gerenciador de usuários que controla este usuário."
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../src/shell-global.c:841
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Aplicações"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documentos Recentes"
#: ../src/shell-global.c:821
msgid "Less than a minute ago"
msgstr "Menos de um minuto atrás"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:824
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuto atrás"
msgstr[1] "%d minutos atrás"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:827
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d hora atrás"
msgstr[1] "%d horas atrás"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:830
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dia atrás"
msgstr[1] "%d dias atrás"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:833
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -142,3 +190,42 @@ msgstr "Encerrar sessão..."
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Desligar..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Pasta home"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Sistema de arquivos"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Procurar"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Browse"
#~ msgstr "Navegar"
#~ msgid "(see all)"
#~ msgstr "(veja todos)"
#~ msgid "Find apps or documents"
#~ msgstr "Localizar aplicativos ou documentos"
#~ msgid "Manager"
#~ msgstr "Gerenciador"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "O objeto gerenciador de usuários que controla este usuário."

232
po/ro.po Normal file
View File

@ -0,0 +1,232 @@
# Romanian translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Lucian Adrian Grijincu <lucian.grijincu@gmail.com>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-10-28 22:25+0200\n"
"PO-Revision-Date: 2009-10-28 22:33+0200\n"
"Last-Translator: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>\n"
"Language-Team: Romanian <gnomero-list@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
"20)) ? 1 : 2);;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Administrare de ferestre și lansare de aplicații"
#: ../js/ui/appDisplay.js:332
msgid "Frequent"
msgstr "Frecvent"
#: ../js/ui/appDisplay.js:867
msgid "Drag here to add favorites"
msgstr "Adăugați aici favorite cu mausul"
#: ../js/ui/appIcon.js:426
msgid "New Window"
msgstr "Fereastră nouă"
#: ../js/ui/appIcon.js:430
msgid "Remove from Favorites"
msgstr "Șterge din favorite"
#: ../js/ui/appIcon.js:431
msgid "Add to Favorites"
msgstr "Adaugă la favorite"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Caută..."
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Mai multe"
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(arată tot)"
#. **** Applications ****
#: ../js/ui/dash.js:725 ../js/ui/dash.js:787
msgid "APPLICATIONS"
msgstr "APPLICAȚII"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:745
msgid "PLACES"
msgstr "LOCAȚII"
#. **** Documents ****
#: ../js/ui/dash.js:752 ../js/ui/dash.js:797
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTE RECENTE"
#. **** Search Results ****
#: ../js/ui/dash.js:777 ../js/ui/dash.js:961
msgid "SEARCH RESULTS"
msgstr "REZULTATELE CĂUTĂRII"
#: ../js/ui/dash.js:792
msgid "PREFERENCES"
msgstr "PREFERINȚE"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:274
msgid "Activities"
msgstr "Activități"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "Conectare la..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Introduceți o comandă:"
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Execuția comenzii „%s” a eșuat:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Aplicații"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Documente recente"
#: ../src/shell-global.c:821
msgid "Less than a minute ago"
msgstr "În ultimul minut"
#: ../src/shell-global.c:824
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "acum un minut"
msgstr[1] "acum %d minute"
msgstr[2] "acum %d de minute"
#: ../src/shell-global.c:827
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "acum o oră"
msgstr[1] "acum %d ore"
msgstr[2] "acum %d de ore"
#: ../src/shell-global.c:830
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "acum o zi"
msgstr[1] "acum %d zile"
msgstr[2] "acum %d de zile"
#: ../src/shell-global.c:833
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "acum o săptămână"
msgstr[1] "acum %d săptămâni"
msgstr[2] "acum %d de săptămâni"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Necunoscut"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nu s-a putut bloca ecranul: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Nu s-a putut folosi temporar un ecran gol pentru economizorul de "
"ecran: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nu se poate ieși din sesiune: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informații despre cont..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Bară laterală"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferințe de sistem..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Blocare ecran"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Alt utilizator"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Ieșire..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Oprire..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Dosar personal"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Sistem de fișiere"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Caută"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

233
po/ru.po Normal file
View File

@ -0,0 +1,233 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Andrey Korzinev <fellrond@gmail.com>, 2009.
# Sergey V. Kovylov <serejka@gmail.com>, 2009.
# Marina Zhurakhinskaya <marinaz@redhat.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n"
"POT-Creation-Date: 2009-10-09 00:27-0400\n"
"PO-Revision-Date: 2009-10-09 00:27-0400\n"
"Last-Translator: Marina Zhurakhinskaya <marinaz@redhat.com>\n"
"Language-Team: Russian <gnome-cyr@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Управление окнами и запуск приложений"
#: ../js/ui/appDisplay.js:335
msgid "Frequent"
msgstr "Часто используемые"
#: ../js/ui/appIcon.js:462
msgid "New Window"
msgstr "Новое окно"
#: ../js/ui/appIcon.js:475
msgid "Remove from Favorites"
msgstr "Удалить из избранного"
#: ../js/ui/appIcon.js:476
msgid "Add to Favorites"
msgstr "Добавить в избранное"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Найти…"
#: ../js/ui/dash.js:400
msgid "More"
msgstr "Ещё"
#: ../js/ui/dash.js:543
#: "(увидеть все)" does not fit when it is next to "НЕДАВНИЕ ДОКУМЕНТЫ", so I'm just using "(все)"
msgid "(see all)"
msgstr "(все)"
#. **** Applications ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "ПРИЛОЖЕНИЯ"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:783
msgid "PLACES"
msgstr "ПАПКИ И РЕСУРСЫ"
#. **** Documents ****
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "НЕДАВНИЕ ДОКУМЕНТЫ"
#. **** Search Results ****
#: ../js/ui/dash.js:815 ../js/ui/dash.js:955
msgid "SEARCH RESULTS"
msgstr "РЕЗУЛЬТАТЫ ПОИСКА"
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "НАСТРОЙКИ"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:272
#. Another word that was considered was "Обзор", but it was decided that it doesn't give a full sense of the actions
#. possible when in the overview mode.
msgid "Activities"
msgstr "Действия"
#. Translators: This is a time format.
#: ../js/ui/panel.js:464
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/places.js:178
msgid "Connect to..."
msgstr "Соединиться с…"
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Введите команду:"
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Не удалось выполнить «%s»:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:162
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:316
msgid "Applications"
msgstr "Приложения"
#: ../js/ui/widget.js:341
msgid "Recent Documents"
msgstr "Недавние документы"
#: ../src/shell-global.c:812
msgid "Less than a minute ago"
msgstr "Менее минуты назад"
#: ../src/shell-global.c:815
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d минуту назад"
msgstr[1] "%d минуты назад"
msgstr[2] "%d минут назад"
#: ../src/shell-global.c:818
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d час назад"
msgstr[1] "%d часа назад"
msgstr[2] "%d часов назад"
#: ../src/shell-global.c:821
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d день назад"
msgstr[1] "%d дня назад"
msgstr[2] "%d дней назад"
#: ../src/shell-global.c:824
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d неделю назад"
msgstr[1] "%d недели назад"
msgstr[2] "%d недель назад"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Неизвестно"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Не удалось заблокировать экран: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Не удалось временно установить пустую экранную заставку: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Не удалось завершить сеанс пользователя: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Информация о пользователе…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Боковая панель"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Системные настройки…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Заблокировать экран"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Сменить пользователя"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Завершить сеанс…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Выключить…"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Домашняя папка"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Файловая система"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Поиск"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

293
po/sl.po Normal file
View File

@ -0,0 +1,293 @@
# Slovenian translation of gnome-shell package.
# Copyright (C) 2006 Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
#
# Matej Urbančič <mateju@svn.gnome.org>, 2009 - 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n"
"POT-Creation-Date: 2010-02-15 17:28+0000\n"
"PO-Revision-Date: 2010-02-15 19:03+0100\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: Slovenian\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);\n"
"X-Poedit-Language: Slovenian\n"
"X-Poedit-Country: SLOVENIA\n"
"X-Poedit-SourceCharset: utf-8\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Gnome Lupina"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Upravljanje oken in zaganjanje programov"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252
#: ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "Programi"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "Možnosti"
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Novo okno"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Odstrani iz priljubljenih"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Dodaj med priljubljene"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "S potegom na to mesto se izbor doda med priljubljene"
#: ../js/ui/appFavorites.js:89
#, c-format
msgid "%s has been added to your favorites."
msgstr "Program \"%s\" je dodan med priljubljeno."
#: ../js/ui/appFavorites.js:107
#, c-format
msgid "%s has been removed from your favorites."
msgstr "Program \"%s\" je odstranjen iz priljubljenih."
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Najdi ..."
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Iskanje ..."
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "Ni zadetkov iskanja"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:900
#: ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "Mesta in naprave"
#. **** Documents ****
#: ../js/ui/dash.js:907
#: ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "Nedavni predmeti"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "Ni nameščenih razširitev"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Omogočeno"
#: ../js/ui/lookingGlass.js:395
msgid "Disabled"
msgstr "Onemogočeno"
#: ../js/ui/lookingGlass.js:397
msgid "Error"
msgstr "Napaka"
#: ../js/ui/lookingGlass.js:399
msgid "Out of date"
msgstr "Zastarelo"
#: ../js/ui/lookingGlass.js:424
msgid "View Source"
msgstr "Poglej vir"
#: ../js/ui/lookingGlass.js:430
msgid "Web Page"
msgstr "Spletna stran"
#: ../js/ui/overview.js:95
msgid "Undo"
msgstr "Razveljavi"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Dejavnosti"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a. %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Povezava z ..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Vnos ukaza:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Izvajanje '%s' je spodletelo:"
#: ../js/ui/statusMenu.js:107
msgid "Available"
msgstr "Razpoložljivo"
#: ../js/ui/statusMenu.js:112
msgid "Busy"
msgstr "Zasedeno"
#: ../js/ui/statusMenu.js:117
msgid "Invisible"
msgstr "Nevidno"
#: ../js/ui/statusMenu.js:126
msgid "Account Information..."
msgstr "Podrobnosti računa ..."
#: ../js/ui/statusMenu.js:132
msgid "Sidebar"
msgstr "Stranska vrstica"
#: ../js/ui/statusMenu.js:142
msgid "System Preferences..."
msgstr "Sistemske možnosti ..."
#: ../js/ui/statusMenu.js:151
msgid "Lock Screen"
msgstr "Zakleni zaslon"
#: ../js/ui/statusMenu.js:156
msgid "Switch User"
msgstr "Preklop uporabnika"
#: ../js/ui/statusMenu.js:162
msgid "Log Out..."
msgstr "Odjava ..."
#: ../js/ui/statusMenu.js:167
msgid "Shut Down..."
msgstr "Izklopi ..."
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Programi"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Nedavni dokumenti"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Pred manj kot eno minuto"
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Pred %d minutami"
msgstr[1] "Pred %d minuto"
msgstr[2] "Pred %d minutama"
msgstr[3] "Pred %d minutami"
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Pred %d urami"
msgstr[1] "Pred %d uro"
msgstr[2] "Pred %d urama"
msgstr[3] "Pred %d urami"
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Pred %d dnevi"
msgstr[1] "Pred %d dnevom"
msgstr[2] "Pred %d dnevoma"
msgstr[3] "Pred %d dnevi"
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Pred %d tedni"
msgstr[1] "Pred %d tednom"
msgstr[2] "Pred %d tednoma"
msgstr[3] "Pred %d tedni"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Domača mapa"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Datotečni sistem"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Poišči"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "PLACES"
#~ msgstr "Mesta"
#~ msgid "SEARCH RESULTS"
#~ msgstr "Rezultati iskanja"
#~ msgid "Unknown"
#~ msgstr "Neznano"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Ni mogoče zakleniti zaslona: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr ""
#~ "Ni mogoče začasno nastaviti črnega zaslona za ohranjevalnik zaslona: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "Ni se mogoče odjaviti: %s"
#~ msgid "Frequent"
#~ msgstr "Pogosto"
#~ msgid "More"
#~ msgstr "Več"
#~ msgid "(see all)"
#~ msgstr "(poglej vse)"
#~ msgid "Browse"
#~ msgstr "Prebrskaj"

177
po/sr.po Normal file
View File

@ -0,0 +1,177 @@
# Serbian translation for gnome-shell.
# Copyright (C) 2010 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Милош Поповић <gpopac@gmail.com>, 2010.
# Милош Поповић <gpopac@gmail.com>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2010-01-18 20:13+0000\n"
"PO-Revision-Date: 2010-01-19 00:14+0000\n"
"Last-Translator: Милош Поповић <gpopac@gmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n%"
"10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Гномова шкољка"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Управник прозорима и покретач програма"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "ПРОГРАМИ"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "ПОСТАВКЕ"
#: ../js/ui/appDisplay.js:647
msgid "New Window"
msgstr "Нови прозор"
#: ../js/ui/appDisplay.js:651
msgid "Remove from Favorites"
msgstr "Уклони из омиљених"
#: ../js/ui/appDisplay.js:652
msgid "Add to Favorites"
msgstr "Додај у омиљене"
#: ../js/ui/appDisplay.js:1004
msgid "Drag here to add favorites"
msgstr "Превуците овде како би додали у омиљене"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "Нађи..."
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "Тражим..."
#: ../js/ui/dash.js:507
msgid "No matching results."
msgstr "Ништа није пронађено."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "МЕСТА И УРЕЂАЈИ"
#. **** Documents ****
#: ../js/ui/dash.js:892
msgid "RECENT ITEMS"
msgstr "СКОРАШЊЕ СТАВКЕ"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Активности"
#. Translators: This is a time format.
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%A, %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Повежи се на..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Унесите наредбу:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Није успело покретање „%s“:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Програми"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Скорашњи документи"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Пре мање од једног минута"
#: ../src/shell-global.c:894
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Пре %d минут"
msgstr[1] "Пре %d минута"
msgstr[2] "Пре %d минута"
msgstr[3] "Пре %d минута"
#: ../src/shell-global.c:899
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Пре %d сат"
msgstr[1] "Пре %d сата"
msgstr[2] "Пре %d сата"
msgstr[3] "Пре %d сата"
#: ../src/shell-global.c:904
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Пре %d дан"
msgstr[1] "Пре %d дана"
msgstr[2] "Пре %d дана"
msgstr[3] "Пре %d дана"
#: ../src/shell-global.c:909
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Пре %d недеље"
msgstr[1] "Пре %d недеље"
msgstr[2] "Пре %d недеље"
msgstr[3] "Пре %d недеља"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Лична фасцикла"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Систем датотека"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Тражи"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

177
po/sr@latin.po Normal file
View File

@ -0,0 +1,177 @@
# Serbian translation for gnome-shell.
# Copyright (C) 2010 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Miloš Popović <gpopac@gmail.com>, 2010.
# Miloš Popović <gpopac@gmail.com>, 2010.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2010-01-18 20:13+0000\n"
"PO-Revision-Date: 2010-01-19 00:14+0000\n"
"Last-Translator: Miloš Popović <gpopac@gmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n%"
"10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Gnomova školjka"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Upravnik prozorima i pokretač programa"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "PROGRAMI"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "POSTAVKE"
#: ../js/ui/appDisplay.js:647
msgid "New Window"
msgstr "Novi prozor"
#: ../js/ui/appDisplay.js:651
msgid "Remove from Favorites"
msgstr "Ukloni iz omiljenih"
#: ../js/ui/appDisplay.js:652
msgid "Add to Favorites"
msgstr "Dodaj u omiljene"
#: ../js/ui/appDisplay.js:1004
msgid "Drag here to add favorites"
msgstr "Prevucite ovde kako bi dodali u omiljene"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "Nađi..."
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "Tražim..."
#: ../js/ui/dash.js:507
msgid "No matching results."
msgstr "Ništa nije pronađeno."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "MESTA I UREĐAJI"
#. **** Documents ****
#: ../js/ui/dash.js:892
msgid "RECENT ITEMS"
msgstr "SKORAŠNJE STAVKE"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Aktivnosti"
#. Translators: This is a time format.
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%A, %H:%M"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Poveži se na..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Unesite naredbu:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Nije uspelo pokretanje „%s“:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Programi"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Skorašnji dokumenti"
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Pre manje od jednog minuta"
#: ../src/shell-global.c:894
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Pre %d minut"
msgstr[1] "Pre %d minuta"
msgstr[2] "Pre %d minuta"
msgstr[3] "Pre %d minuta"
#: ../src/shell-global.c:899
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Pre %d sat"
msgstr[1] "Pre %d sata"
msgstr[2] "Pre %d sata"
msgstr[3] "Pre %d sata"
#: ../src/shell-global.c:904
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Pre %d dan"
msgstr[1] "Pre %d dana"
msgstr[2] "Pre %d dana"
msgstr[3] "Pre %d dana"
#: ../src/shell-global.c:909
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Pre %d nedelje"
msgstr[1] "Pre %d nedelje"
msgstr[2] "Pre %d nedelje"
msgstr[3] "Pre %d nedelja"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Lična fascikla"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Sistem datoteka"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Traži"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

184
po/sv.po
View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-01 00:31+0200\n"
"PO-Revision-Date: 2009-09-01 00:31+0100\n"
"POT-Creation-Date: 2009-12-01 23:52+0100\n"
"PO-Revision-Date: 2009-12-01 23:53+0100\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"MIME-Version: 1.0\n"
@ -24,149 +24,139 @@ msgstr "GNOME-skal"
msgid "Window management and application launching"
msgstr "Fönsterhantering och programstarter"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Aktiviteter"
#: ../js/ui/appDisplay.js:580
#: ../js/ui/appIcon.js:425
msgid "New Window"
msgstr "Nytt fönster"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H.%M"
#: ../js/ui/appDisplay.js:584
#: ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Ta bort från favoriter"
#: ../js/ui/dash.js:256
#: ../js/ui/appDisplay.js:585
#: ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Lägg till som favorit"
#: ../js/ui/appDisplay.js:1029
msgid "Drag here to add favorites"
msgstr "Dra hit för att lägga till favorit"
#: ../js/ui/dash.js:236
msgid "Find..."
msgstr "Sök..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Bläddra"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(se alla)"
#. **** Applications ****
#: ../js/ui/dash.js:633
#: ../js/ui/dash.js:681
#: ../js/ui/dash.js:620
#: ../js/ui/dash.js:682
msgid "APPLICATIONS"
msgstr "PROGRAM"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
#: ../js/ui/dash.js:640
#: ../js/ui/dash.js:697
msgid "PLACES"
msgstr "PLATSER"
#. **** Documents ****
#: ../js/ui/dash.js:660
#: ../js/ui/dash.js:647
#: ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "SENASTE DOKUMENT"
#. **** Search Results ****
#: ../js/ui/dash.js:679
#: ../js/ui/dash.js:672
#: ../js/ui/dash.js:862
msgid "SEARCH RESULTS"
msgstr "SÖKRESULTAT"
#: ../js/ui/runDialog.js:82
#: ../js/ui/dash.js:687
msgid "PREFERENCES"
msgstr "INSTÄLLNINGAR"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:227
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:440
msgid "%a %l:%M %p"
msgstr "%a %H.%M"
#: ../js/ui/placeDisplay.js:84
msgid "Connect to..."
msgstr "Anslut till..."
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Ange ett kommando:"
#: ../src/shell-global.c:840
#: ../js/ui/runDialog.js:173
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Körning av \"%s\" misslyckades:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H.%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Program"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Senaste dokument"
#: ../src/shell-global.c:826
msgid "Less than a minute ago"
msgstr "Mindre än en minut sedan"
#: ../src/shell-global.c:843
#: ../src/shell-global.c:829
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minut sedan"
msgstr[1] "%d minuter sedan"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:832
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d timme sedan"
msgstr[1] "%d timmar sedan"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:835
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag sedan"
msgstr[1] "%d dagar sedan"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:838
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d vecka sedan"
msgstr[1] "%d veckor sedan"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Okänt"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan inte låsa skärmen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan inte temporärt ställa in skärmsläckaren till blank skärm: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan inte logga ut: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Kontoinformation..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidopanel"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systeminställningar..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lås skärmen"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Växla användare"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Logga ut..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Stäng av..."
#: ../src/shell-uri-util.c:87
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Hemmapp"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Filsystem"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Sök"
@ -175,11 +165,37 @@ msgstr "Sök"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "(see all)"
#~ msgstr "(se alla)"
#~ msgid "Unknown"
#~ msgstr "Okänt"
#~ msgid "Can't lock screen: %s"
#~ msgstr "Kan inte låsa skärmen: %s"
#~ msgid "Can't temporarily set screensaver to blank screen: %s"
#~ msgstr "Kan inte temporärt ställa in skärmsläckaren till blank skärm: %s"
#~ msgid "Can't logout: %s"
#~ msgstr "Kan inte logga ut: %s"
#~ msgid "Account Information..."
#~ msgstr "Kontoinformation..."
#~ msgid "Sidebar"
#~ msgstr "Sidopanel"
#~ msgid "System Preferences..."
#~ msgstr "Systeminställningar..."
#~ msgid "Lock Screen"
#~ msgstr "Lås skärmen"
#~ msgid "Switch User"
#~ msgstr "Växla användare"
#~ msgid "Log Out..."
#~ msgstr "Logga ut..."
#~ msgid "Shut Down..."
#~ msgstr "Stäng av..."
#~ msgid "Browse"
#~ msgstr "Bläddra"
#~ msgid "Find apps or documents"
#~ msgstr "Hitta program eller dokument"
#~ msgid "DOCUMENTS"

250
po/vi.po Normal file
View File

@ -0,0 +1,250 @@
# Vietnamese translation for gnome-shell.
# Copyright (C) 2010 GNOME i18n Project for Vietnamese.
# This file is distributed under the same license as the gnome-shell package.
# Nguyễn Thái Ngọc Duy <pclouds@gmail.com>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-02-16 19:32+0700\n"
"PO-Revision-Date: 2010-02-16 19:36+0700\n"
"Last-Translator: Duy <pclouds@gmail.com>\n"
"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Quản lý cửa sổ và chạy ứng dụng"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "ỨNG DỤNG"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "TUỲ THÍCH"
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Cửa sổ mới"
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Bỏ đánh dấu ưa thích"
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Đánh dấu ưa thích"
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Kéo vào đây để thêm vào danh mục ưa thích"
#: ../js/ui/appFavorites.js:89
#, c-format
msgid "%s has been added to your favorites."
msgstr "Đã được đánh dấu ưa thích cho %s."
#: ../js/ui/appFavorites.js:107
#, c-format
msgid "%s has been removed from your favorites."
msgstr "Đã bỏ đánh dấu ưa thích cho %s"
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Tìm"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Đang tìm..."
#: ../js/ui/dash.js:522
msgid "No matching results."
msgstr "Không tìm thấy."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "ĐỊA ĐIỂM & THIẾT BỊ"
#. **** Documents ****
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "MỤC GẦN ĐÂY"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "Chưa cài phần mở rộng"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Bật"
#: ../js/ui/lookingGlass.js:395
msgid "Disabled"
msgstr "Tắt"
#: ../js/ui/lookingGlass.js:397
msgid "Error"
msgstr "Lỗi"
#: ../js/ui/lookingGlass.js:399
msgid "Out of date"
msgstr "Hết hạn"
#: ../js/ui/lookingGlass.js:424
msgid "View Source"
msgstr "Xem mã nguồn"
#: ../js/ui/lookingGlass.js:430
msgid "Web Page"
msgstr "Trang Web"
#: ../js/ui/overview.js:92
msgid "Undo"
msgstr "Hoàn lại"
#. Button on the left side of the panel.
#. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Hoạt động"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a %R"
#. Translators: This is a time format used for AM/PM.
#: ../js/ui/panel.js:563
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Kết nối đến..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Vui lòng nhập lệnh:"
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Lỗi thực hiện '%s':"
#: ../js/ui/statusMenu.js:107
msgid "Available"
msgstr "Có mặt"
#: ../js/ui/statusMenu.js:112
msgid "Busy"
msgstr "Bận"
#: ../js/ui/statusMenu.js:117
msgid "Invisible"
msgstr "Giấu mặt"
#: ../js/ui/statusMenu.js:126
msgid "Account Information..."
msgstr "Thông tin tài khoản..."
#: ../js/ui/statusMenu.js:132
msgid "Sidebar"
msgstr "Thanh bên"
#: ../js/ui/statusMenu.js:142
msgid "System Preferences..."
msgstr "Thiết lập hệ thống..."
#: ../js/ui/statusMenu.js:151
msgid "Lock Screen"
msgstr "Khoá màn hình"
#: ../js/ui/statusMenu.js:156
msgid "Switch User"
msgstr "Chuyển người dùng"
#: ../js/ui/statusMenu.js:162
msgid "Log Out..."
msgstr "Đăng xuất..."
#: ../js/ui/statusMenu.js:167
msgid "Shut Down..."
msgstr "Tắt máy..."
#. Translators: This is a time format.
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Ứng dụng"
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Tài liệu gần đây"
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Chưa đến một phút"
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d phút trước"
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d giờ trước"
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d ngày trước"
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d tuần trước"
#: ../src/shell-uri-util.c:89
msgid "Home Folder"
msgstr "Thư mục chính"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "Hệ tập tin"
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "Tìm"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:300
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

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