Compare commits

...

185 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
113 changed files with 9567 additions and 3346 deletions

3
.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
@ -39,6 +41,7 @@ src/gnome-shell
src/test-recorder
src/test-recorder.ogg
src/test-theme
src/st.h
stamp-h1
tests/run-test.sh
xmldocs.make

View File

@ -1,9 +1,13 @@
SUBDIRS = data js src tests 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 \
autogen.sh
autogen.sh \
tools/check-for-missing.py
# These are files checked into Git that we don't want to distribute
DIST_EXCLUDE = \
@ -14,14 +18,4 @@ DIST_EXCLUDE = \
distcheck-hook:
@echo "Checking disted files against files in git"
@failed=false; \
exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \
for f in `cd $(srcdir) && git ls-files $$exclude` ; do \
if ! test -e $(distdir)/$$f ; then \
echo File missing from distribution: $$f ; \
failed=true ; \
fi \
done ; \
if $$failed ; then \
exit 1 ; \
fi
@$(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.28.1)
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,7 +54,7 @@ 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
@ -94,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
@ -122,7 +124,7 @@ changequote([,])dnl
AC_PATH_PROG(mutter, [mutter])
AC_SUBST(mutter)
AC_OUTPUT([
AC_CONFIG_FILES([
Makefile
data/Makefile
js/Makefile
@ -131,4 +133,6 @@ AC_OUTPUT([
src/Makefile
tests/Makefile
po/Makefile.in
man/Makefile
])
AC_OUTPUT

View File

@ -14,24 +14,33 @@ gnome-shell.desktop: gnome-shell.desktop.in
imagesdir = $(pkgdatadir)/images
dist_images_DATA = \
add-workspace.svg \
app-well-glow.png \
close-black.svg \
magnifier.svg \
remove-workspace.svg
magnifier.svg
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
theme/gnome-shell.css \
theme/close.svg \
theme/add-workspace.svg \
theme/close-window.svg \
theme/scroll-button-down.png \
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-up.png \
theme/scroll-button-down.png \
theme/scroll-button-up-hover.png \
theme/scroll-vhandle.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.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
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>
@ -103,6 +117,68 @@
</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,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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -26,6 +26,10 @@
color: #0000e0;
}
.label-shadow {
color: rgba(0,0,0,0.5);
}
StScrollBar
{
padding: 0px;
@ -37,36 +41,48 @@ StScrollView
scrollbar-height: 16px;
}
StButton#up-stepper
StScrollView > .top-shadow
{
border-image: url("scroll-button-up.png") 5;
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 255);
background-gradient-end: rgba(0, 0, 0, 0);
height: 30px;
}
StButton#up-stepper:hover,
StButton#up-stepper:active
StScrollView > .bottom-shadow
{
border-image: url("scroll-button-up-hover.png") 5;
background-gradient-direction: vertical;
background-gradient-start: rgba(0, 0, 0, 0);
background-gradient-end: rgba(0, 0, 0, 255);
height: 30px;
}
StButton#down-stepper
{
border-image: url("scroll-button-down.png") 5;
}
StButton#down-stepper:hover,
StButton#down-stepper:active
{
border-image: url("scroll-button-down-hover.png") 5;
StScrollBar {
background-color: #080808;
border: 1px solid #2d2d2d;
border-radius: 8px;
}
StScrollBar StButton#vhandle
{
border-image: url("scroll-vhandle.png") 5;
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
{
border-image: url("scroll-vhandle.png") 5;
background-color: #292929;
}
StTooltip {
@ -85,6 +101,7 @@ StTooltip {
background-gradient-direction: vertical;
background-gradient-start: #161616;
background-gradient-end: #000000;
border-bottom: 1px solid #1f1f1f;
}
#panelLeft, #panelCenter, #panelRight {
@ -99,11 +116,6 @@ StTooltip {
padding-left: 4px;
}
.panel-button:pressed {
background-color: rgba(50,76,111,0.98);
border-radius: 4px;
}
#appMenu {
spacing: 4px;
}
@ -116,23 +128,83 @@ StTooltip {
.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 {
background-color: #314a6c;
.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;
}
/* Overlay */
/* 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);
@ -146,14 +218,56 @@ StTooltip {
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;
background-color: rgba(0,0,0,0.75);
font-size: 12px;
padding: 0px 14px;
}
@ -175,17 +289,9 @@ StTooltip {
}
.section-header {
border: 1px solid #262626;
background-gradient-direction: vertical;
background-gradient-start: #161616;
background-gradient-end: #000000;
font-weight: bold;
font-size: 12px;
}
.section-header-inner {
border: 1px solid #000000;
padding: 0px 4px;
spacing: 4px;
}
@ -208,7 +314,6 @@ StTooltip {
}
.dash-section-content {
font-size: 14px;
color: #ffffff;
spacing: 8px;
}
@ -222,6 +327,12 @@ StTooltip {
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;
@ -250,12 +361,14 @@ StTooltip {
}
.dash-search-result-content {
padding: 2px;
padding: 3px;
}
.dash-search-result-content:selected {
padding: 1px;
border: 1px solid #262626;
padding: 2px;
border: 1px solid #5c5c5c;
border-radius: 2px;
background-color: #1e1e1e;
}
/* GenericDisplay */
@ -296,22 +409,50 @@ StTooltip {
/* Apps */
.overview-pane {
width: 440px;
}
#dashAppWell {
spacing: 2px;
-shell-grid-item-size: 74px;
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 #080808;
border-radius: 2px;
border: 1px solid #181818;
border-radius: 4px;
padding: 2px;
width: 74px;
height: 74px;
font-size: 12px;
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 #202020;
border: 1px solid #666666;
}
.app-well-app:active {
@ -319,11 +460,6 @@ StTooltip {
border: 1px solid #5f5f5f;
}
.app-well-app-glow {
-shell-glow-extend-vertical: 3px;
-shell-glow-shrink-horizontal: 3px;
}
.app-well-menu {
border: 1px solid #5f5f5f;
border-radius: 4px;
@ -472,6 +608,52 @@ StTooltip {
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);
@ -515,3 +697,54 @@ StTooltip {
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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 323 B

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

@ -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

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

@ -18,15 +18,15 @@ function parse(params, defaults, allowExtras) {
return defaults;
if (!allowExtras) {
for (let prop in params) {
if (!(prop in defaults))
throw new Error('Unrecognized parameter "' + prop + '"');
}
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];
if (!(prop in params))
params[prop] = defaults[prop];
}
return params;

View File

@ -16,6 +16,8 @@ dist_jsui_DATA = \
link.js \
lookingGlass.js \
main.js \
messageTray.js \
notificationDaemon.js \
overview.js \
panel.js \
placeDisplay.js \
@ -27,5 +29,8 @@ dist_jsui_DATA = \
tweener.js \
widget.js \
widgetBox.js \
windowAttentionHandler.js \
windowManager.js \
workspaces.js
workspacesView.js \
workspaceSwitcherPopup.js \
workspace.js

View File

@ -84,9 +84,9 @@ AltTabPopup.prototype = {
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
let primary = global.get_primary_monitor();
this._appSwitcher.actor.x = primary.x + Math.floor((primary.width - this._appSwitcher.actor.width) / 2);
this._appSwitcher.actor.y = primary.y + Math.floor((primary.height - this._appSwitcher.actor.height) / 2);
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;
@ -395,8 +395,8 @@ AltTabPopup.prototype = {
thumbnailCenter = stageX + icon.width / 2;
} else {
// Center the thumbnails on the monitor
let primary = global.get_primary_monitor();
thumbnailCenter = primary.x + primary.width / 2;
let focus = global.get_focus_monitor();
thumbnailCenter = focus.x + focus.width / 2;
}
this._thumbnails.actor.x = Math.floor(thumbnailCenter - this._thumbnails.actor.width / 2);
@ -512,7 +512,7 @@ SwitcherList.prototype = {
let totalSpacing = this._list.spacing * (this._items.length - 1);
alloc.min_size = this._items.length * maxChildMin + separatorWidth + totalSpacing;
alloc.nat_size = this._items.length * maxChildNat + separatorWidth + totalSpacing;
alloc.natural_size = alloc.min_size;
},
_getPreferredHeight: function (actor, forWidth, alloc) {
@ -528,11 +528,11 @@ SwitcherList.prototype = {
if (this._squareItems) {
let [childMin, childNat] = this._maxChildWidth(-1);
maxChildMin = Math.max(childMin, maxChildMin);
maxChildNat = Math.max(childNat, maxChildNat);
maxChildNat = maxChildMin;
}
alloc.min_size = maxChildMin;
alloc.nat_size = maxChildNat;
alloc.natural_size = maxChildNat;
},
_allocate: function (actor, box, flags) {
@ -592,7 +592,10 @@ AppIcon.prototype = {
this.actor = new St.BoxLayout({ style_class: "alt-tab-app",
vertical: true });
this._icon = this.app.create_icon_texture(POPUP_APPICON_SIZE);
this.actor.add(this._icon, { x_fill: false, y_fill: false } );
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 });
}

View File

@ -19,200 +19,118 @@ const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Search = imports.ui.search;
const Workspaces = imports.ui.workspaces;
const Workspace = imports.ui.workspace;
const APPICON_SIZE = 48;
const WELL_MAX_COLUMNS = 8;
/* This class represents a single display item containing information about an application.
*
* appInfo - AppInfo object containing information about the application
*/
function AppDisplayItem(appInfo) {
this._init(appInfo);
function AllAppView() {
this._init();
}
AppDisplayItem.prototype = {
__proto__: GenericDisplay.GenericDisplayItem.prototype,
_init : function(appInfo) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
this._appInfo = appInfo;
this._setItemInfo(appInfo.get_name(), appInfo.get_description());
AllAppView.prototype = {
_init: function(apps) {
this.actor = new St.BoxLayout({ vertical: true });
this._grid = new WellGrid(true);
this._appSystem = Shell.AppSystem.get_default();
this.actor.add(this._grid.actor, { y_align: St.Align.START, expand: true });
},
getId: function() {
return this._appInfo.get_id();
_removeAll: function() {
this._grid.removeAll();
this._apps = [];
},
//// Public method overrides ////
_addApp: function(app) {
let App = new AppWellIcon(this._appSystem.get_app(app.get_id()));
App.connect('launching', Lang.bind(this, function() {
this.emit('launching');
}));
App._draggable.connect('drag-begin', Lang.bind(this, function() {
this.emit('drag-begin');
}));
// Opens an application represented by this display item.
launch : function() {
let appSys = Shell.AppSystem.get_default();
let app = appSys.get_app(this._appInfo.get_id());
let windows = app.get_windows();
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.overview.activateWindow(mostRecentWindow, global.get_current_time());
} else {
this._appInfo.launch();
this._grid.addItem(App.actor);
this._apps.push(App);
},
refresh: function(apps) {
let ids = [];
for (let i in apps)
ids.push(i);
ids.sort(function(a, b) {
return apps[a].get_name().localeCompare(apps[b].get_name());
});
this._removeAll();
for (let i = 0; i < ids.length; i++) {
this._addApp(apps[ids[i]]);
}
},
//// Protected method overrides ////
// Returns an icon for the item.
_createIcon : function() {
return this._appInfo.create_icon_texture(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
},
// Returns a preview icon for the item.
_createPreviewIcon : function() {
return this._appInfo.create_icon_texture(GenericDisplay.PREVIEW_ICON_SIZE);
},
shellWorkspaceLaunch: function() {
this.launch();
}
};
Signals.addSignalMethods(AllAppView.prototype);
/* This class represents a display containing a collection of application items.
* The applications are sorted based on their popularity by default, and based on
* their name if some search filter is applied.
*
* showPrefs - a boolean indicating if this AppDisplay should contain preference
* applets, rather than applications
* The applications are sorted based on their name.
*/
function AppDisplay(showPrefs, flags) {
this._init(showPrefs, flags);
function AllAppDisplay() {
this._init();
}
AppDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function(showPrefs, flags) {
GenericDisplay.GenericDisplay.prototype._init.call(this, flags);
this._showPrefs = showPrefs;
this._menus = [];
this._menuDisplays = [];
// map<search term, map<appId, true>>
// We use a map of appIds instead of an array to ensure that we don't have duplicates and for easier lookup.
this._menuSearchAppMatches = {};
AllAppDisplay.prototype = {
_init: function() {
this._appSystem = Shell.AppSystem.get_default();
this._appsStale = true;
this._appSystem.connect('installed-changed', Lang.bind(this, function(appSys) {
this._appsStale = true;
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
Main.queueDeferredWork(this._workId);
}));
let bin = new St.BoxLayout({ style_class: 'all-app-controls-panel' });
this.actor = new St.BoxLayout({ style_class: 'all-app', vertical: true });
this.actor.hide();
let view = new St.ScrollView({ x_fill: true,
y_fill: false,
style_class: 'all-app-scroll-view',
vshadows: true });
this._scrollView = view;
this.actor.add(bin);
this.actor.add(view, { expand: true, y_fill: false, y_align: St.Align.START });
this._appView = new AllAppView();
this._appView.connect('launching', Lang.bind(this, this.close));
this._appView.connect('drag-begin', Lang.bind(this, this.close));
this._scrollView.add_actor(this._appView.actor);
this._scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
},
//// Private ////
_redisplay: function() {
let apps = this._appSystem.get_flattened_apps().filter(function(app) {
return !app.get_is_nodisplay();
});
_addApp: function(appInfo) {
let appId = appInfo.get_id();
this._allItems[appId] = appInfo;
this._appView.refresh(apps);
},
//// Protected method overrides ////
toggle: function() {
this.emit('open-state-changed', !this.actor.visible);
// Gets information about all applications by calling Gio.app_info_get_all().
_refreshCache : function() {
if (!this._appsStale)
return true;
this._allItems = {};
if (this._showPrefs) {
// Get the desktop file ids for settings/preferences.
// These are used for search results, but not in the app menus.
let settings = this._appSystem.get_all_settings();
for (let i = 0; i < settings.length; i++) {
let app = settings[i];
this._addApp(app);
}
} else {
let apps = this._appSystem.get_flattened_apps();
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
this._addApp(app);
}
}
this._appsStale = false;
return false;
this.actor.visible = !this.actor.visible;
},
_setDefaultList : function() {
this._matchedItems = this._allItems;
this._matchedItemKeys = [];
for (let itemId in this._matchedItems) {
let app = this._allItems[itemId];
if (app.get_is_nodisplay())
continue;
this._matchedItemKeys.push(itemId);
}
this._matchedItemKeys.sort(Lang.bind(this, this._compareItems));
},
// Compares items associated with the item ids based on the alphabetical order
// of the item names.
// Returns an integer value indicating the result of the comparison.
_compareItems : function(itemIdA, itemIdB) {
let appA = this._allItems[itemIdA];
let appB = this._allItems[itemIdB];
return appA.get_name().localeCompare(appB.get_name());
},
// Checks if the item info can be a match for the search string by checking
// the name, description, execution command, and category for the application.
// Item info is expected to be Shell.AppInfo.
// Returns a boolean flag indicating if itemInfo is a match.
_isInfoMatching : function(itemInfo, search) {
// Don't show nodisplay items here
if (itemInfo.get_is_nodisplay())
return false;
if (search == null || search == '')
return true;
let fold = function(s) {
if (!s)
return s;
return GLib.utf8_casefold(GLib.utf8_normalize(s, -1,
GLib.NormalizeMode.ALL), -1);
};
let name = fold(itemInfo.get_name());
if (name.indexOf(search) >= 0)
return true;
let description = fold(itemInfo.get_description());
if (description) {
if (description.indexOf(search) >= 0)
return true;
}
let exec = fold(itemInfo.get_executable());
if (exec == null) {
log("Missing an executable for " + itemInfo.name);
} else {
if (exec.indexOf(search) >= 0)
return true;
}
return false;
},
// Creates an AppDisplayItem based on itemInfo, which is expected be an Shell.AppInfo object.
_createDisplayItem: function(itemInfo) {
return new AppDisplayItem(itemInfo);
close: function() {
if (!this.actor.visible)
return;
this.toggle();
}
};
Signals.addSignalMethods(AppDisplay.prototype);
Signals.addSignalMethods(AllAppDisplay.prototype);
function BaseAppSearchProvider() {
this._init();
@ -236,6 +154,16 @@ BaseAppSearchProvider.prototype = {
},
activateResult: function(id) {
let app = this._appSys.get_app(id);
let windows = app.get_windows();
if (windows.length > 0)
Main.activateWindow(windows[0]);
else
app.launch();
},
dragActivateResult: function(id) {
let app = this._appSys.get_app(id);
app.launch();
}
@ -299,15 +227,10 @@ AppIcon.prototype = {
_init : function(app) {
this.app = app;
this._glowExtendVertical = 0;
this._glowShrinkHorizontal = 0;
this.actor = new St.Bin({ style_class: 'app-icon',
x_fill: true,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._rerenderGlow));
let box = new St.BoxLayout({ vertical: true });
this.actor.set_child(box);
@ -316,95 +239,9 @@ AppIcon.prototype = {
box.add(this.icon, { expand: true, x_fill: false, y_fill: false });
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 St.Label({ text: this.app.get_name() });
this._name.clutter_text.line_alignment = Pango.Alignment.CENTER;
nameBox.add_actor(this._name);
this._glowBox = new St.BoxLayout({ style_class: 'app-well-app-glow' });
this._glowBox.connect('style-changed', Lang.bind(this, this._onStyleChanged));
this._nameBox.add_actor(this._glowBox);
this._glowBox.lower(this._name);
this._appWindowChangedId = this.app.connect('windows-changed', Lang.bind(this, this._queueRerenderGlow));
box.add(nameBox);
},
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
let [min, natural] = this._name.get_preferred_width(forHeight);
alloc.min_size = min;
alloc.natural_size = natural;
},
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
let [min, natural] = this._name.get_preferred_height(forWidth);
alloc.min_size = min + this._glowExtendVertical * 2;
alloc.natural_size = natural + this._glowExtendVertical * 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 = this._glowExtendVertical;
childBox.y2 = availHeight - this._glowExtendVertical;
this._name.allocate(childBox, flags);
// Now the glow
let glowPaddingHoriz = Math.max(0, xPadding - this._glowShrinkHorizontal);
glowPaddingHoriz = Math.max(this._glowShrinkHorizontal, glowPaddingHoriz);
childBox.x1 = glowPaddingHoriz;
childBox.x2 = availWidth - glowPaddingHoriz;
childBox.y1 = 0;
childBox.y2 = availHeight;
this._glowBox.allocate(childBox, flags);
},
_onDestroy: function() {
if (this._appWindowChangedId > 0)
this.app.disconnect(this._appWindowChangedId);
},
_queueRerenderGlow: function() {
Main.queueDeferredWork(this._workId);
},
_onStyleChanged: function() {
let themeNode = this._glowBox.get_theme_node();
let success, len;
[success, len] = themeNode.get_length('-shell-glow-extend-vertical', false);
if (success)
this._glowExtendVertical = len;
[success, len] = themeNode.get_length('-shell-glow-shrink-horizontal', false);
if (success)
this._glowShrinkHorizontal = len;
this.actor.queue_relayout();
},
_rerenderGlow: function() {
this._glowBox.destroy_children();
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
let windows = this.app.get_windows();
for (let i = 0; i < 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.add(glow);
}
box.add_actor(this._name);
}
}
@ -415,6 +252,7 @@ function AppWellIcon(app) {
AppWellIcon.prototype = {
_init : function(app) {
this.app = app;
this._running = false;
this.actor = new St.Clickable({ style_class: 'app-well-app',
reactive: true,
x_fill: true,
@ -433,6 +271,33 @@ AppWellIcon.prototype = {
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChange));
this.actor.connect('show', Lang.bind(this, this._onShow));
this.actor.connect('hide', Lang.bind(this, this._onHideDestroy));
this.actor.connect('destroy', Lang.bind(this, this._onHideDestroy));
this._appWindowChangedId = 0;
},
_onShow: function() {
this._appWindowChangedId = this.app.connect('windows-changed',
Lang.bind(this,
this._updateStyleClass));
this._updateStyleClass();
},
_onHideDestroy: function() {
if (this._appWindowChangedId > 0)
this.app.disconnect(this._appWindowChangedId);
},
_updateStyleClass: function() {
let windows = this.app.get_windows();
let running = windows.length > 0;
if (running == this._running)
return;
this._running = running;
this.actor.style_class = this._running ? "app-well-app running"
: "app-well-app";
},
_onButtonPress: function(actor, event) {
@ -467,6 +332,10 @@ AppWellIcon.prototype = {
return false;
},
getId: function() {
return this.app.get_id();
},
popupMenu: function(activatingButton) {
if (!this._menu) {
this._menu = new AppIconMenu(this);
@ -492,10 +361,12 @@ AppWellIcon.prototype = {
activateMostRecentWindow: function () {
let mostRecentWindow = this.app.get_windows()[0];
Main.overview.activateWindow(mostRecentWindow, global.get_current_time());
Main.activateWindow(mostRecentWindow);
},
highlightWindow: function(metaWindow) {
if (this._didActivateWindow)
return;
if (!this._getRunning())
return;
Main.overview.getWorkspacesForWindow(metaWindow).setHighlightWindow(metaWindow);
@ -504,7 +375,7 @@ AppWellIcon.prototype = {
activateWindow: function(metaWindow) {
if (metaWindow) {
this._didActivateWindow = true;
Main.overview.activateWindow(metaWindow, global.get_current_time());
Main.activateWindow(metaWindow);
} else
Main.overview.hide();
},
@ -513,6 +384,7 @@ AppWellIcon.prototype = {
if (this._getRunning()) {
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(this.app.get_id());
this._setWindowSelection = true;
this._didActivateWindow = false;
}
},
@ -532,14 +404,17 @@ AppWellIcon.prototype = {
_onActivate: function (event) {
let running = this._getRunning();
this.emit('launching');
if (!running) {
this.app.launch();
Main.overview.hide();
} else {
let modifiers = Shell.get_event_state(event);
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
this.app.launch();
Main.overview.hide();
} else {
this.activateMostRecentWindow();
}
@ -562,10 +437,10 @@ AppWellIcon.prototype = {
return this.app.create_icon_texture(APPICON_SIZE);
},
// Returns the original icon that is being used as a source for the cloned texture
// that represents the item as it is being dragged.
// Returns the original actor that should align with the actor
// we show as the item is being dragged.
getDragActorSource: function() {
return this.actor;
return this._icon.icon;
}
}
Signals.addSignalMethods(AppWellIcon.prototype);
@ -757,7 +632,7 @@ AppIconMenu.prototype = {
},
_findMetaWindowForActor: function (actor) {
if (actor._delegate instanceof Workspaces.WindowClone)
if (actor._delegate instanceof Workspace.WindowClone)
return actor._delegate.metaWindow;
else if (actor.get_meta_window)
return actor.get_meta_window();
@ -874,12 +749,12 @@ function WellGrid() {
WellGrid.prototype = {
_init: function() {
this.actor = new St.Bin({ name: "dashAppWell" });
this.actor = new St.BoxLayout({ name: "dashAppWell", vertical: true });
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._item_size = 48;
this._grid = new Shell.GenericContainer();
this.actor.set_child(this._grid);
this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -1069,9 +944,9 @@ AppWell.prototype = {
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
let app = null;
if (source instanceof AppDisplayItem) {
if (source instanceof AppWellIcon) {
app = this._appSystem.get_app(source.getId());
} else if (source instanceof Workspaces.WindowClone) {
} else if (source instanceof Workspace.WindowClone) {
app = this._tracker.get_window_app(source.metaWindow);
}

View File

@ -3,7 +3,10 @@
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();
@ -61,23 +64,50 @@ AppFavorites.prototype = {
return appId in this._favorites;
},
addFavorite: function(appId) {
_addFavorite: function(appId) {
if (appId in this._favorites)
return;
return false;
let app = Shell.AppSystem.get_default().get_app(appId);
if (!app)
return;
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 (!appId in this._favorites)
if (!this._removeFavorite(appId))
return;
let ids = this._getIds().filter(function (id) { return id != appId; });
this._gconf.set_string_list(this.FAVORITE_APPS_KEY, ids);
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);

View File

@ -1,591 +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 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 Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const GenericDisplay = imports.ui.genericDisplay;
const AppFavorites = imports.ui.appFavorites;
const Main = imports.ui.main;
const Workspaces = imports.ui.workspaces;
const GLOW_COLOR = new Clutter.Color();
GLOW_COLOR.from_pixel(0x4f6ba4ff);
const GLOW_PADDING_HORIZONTAL = 3;
const GLOW_PADDING_VERTICAL = 3;
const APPICON_DEFAULT_ICON_SIZE = 48;
const APPICON_PADDING = 1;
const APPICON_BORDER_WIDTH = 1;
const APPICON_CORNER_RADIUS = 4;
const APPICON_MENU_POPUP_TIMEOUT_MS = 600;
const APPICON_DEFAULT_BORDER_COLOR = new Clutter.Color();
APPICON_DEFAULT_BORDER_COLOR.from_pixel(0x787878ff);
const APPICON_MENU_BACKGROUND_COLOR = new Clutter.Color();
APPICON_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
const APPICON_MENU_FONT = 'Sans 14px';
const APPICON_MENU_COLOR = new Clutter.Color();
APPICON_MENU_COLOR.from_pixel(0xffffffff);
const APPICON_MENU_SELECTED_COLOR = new Clutter.Color();
APPICON_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
const APPICON_MENU_SEPARATOR_COLOR = new Clutter.Color();
APPICON_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
const APPICON_MENU_BORDER_WIDTH = 1;
const APPICON_MENU_ARROW_SIZE = 12;
const APPICON_MENU_CORNER_RADIUS = 4;
const APPICON_MENU_PADDING = 4;
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const MenuType = { NONE: 0, ON_RIGHT: 1, BELOW: 2 };
function AppIcon(params) {
this._init(params);
}
AppIcon.prototype = {
_init : function(params) {
this.app = params.app;
if (!this.app)
throw new Error('AppIcon constructor requires "app" param');
this._menuType = ('menuType' in params) ? params.menuType : MenuType.NONE;
this._iconSize = ('size' in params) ? params.size : APPICON_DEFAULT_ICON_SIZE;
this._showGlow = ('glow' in params) ? params.glow : false;
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
border: APPICON_BORDER_WIDTH,
corner_radius: APPICON_CORNER_RADIUS,
padding: APPICON_PADDING,
reactive: true });
this.actor._delegate = this;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.highlight_border_color = APPICON_DEFAULT_BORDER_COLOR;
if (this._menuType != MenuType.NONE) {
this.actor.connect('button-press-event', Lang.bind(this, this._updateMenuOnButtonPress));
this.actor.connect('notify::hover', Lang.bind(this, this._updateMenuOnHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._updateMenuOnActivate));
this._menuTimeoutId = 0;
this._menu = null;
}
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
width: this._iconSize,
height: this._iconSize });
this.icon = this.app.create_icon_texture(this._iconSize);
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
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 St.Label({ style_class: "app-icon-label",
text: this.app.get_name() });
this._name.clutter_text.line_alignment = Pango.Alignment.CENTER;
nameBox.add_actor(this._name);
if (this._showGlow) {
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
this._nameBox.add_actor(this._glowBox);
this._glowBox.lower(this._name);
this._appWindowChangedId = this.app.connect('windows-changed', Lang.bind(this, this._rerenderGlow));
this._rerenderGlow();
} else {
this._glowBox = null;
this._appWindowChangedId = 0;
}
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);
}
},
_onDestroy: function() {
if (this._appWindowChangedId > 0)
this.app.disconnect(this._appWindowChangedId);
},
_rerenderGlow: function() {
if (!this._showGlow)
return;
this._glowBox.get_children().forEach(function (a) { a.destroy(); });
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
let windows = this.app.get_windows();
for (let i = 0; i < 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);
}
},
// AppIcon itself is not a draggable, but if you want to make
// a subclass of it draggable, you can use this method to create
// a drag actor
createDragActor: function() {
return this.app.create_icon_texture(this._iconSize);
},
setHighlight: function(highlight) {
if (highlight) {
this.actor.border_color = this.highlight_border_color;
} else {
this.actor.border_color = TRANSPARENT_COLOR;
}
},
_updateMenuOnActivate: function(actor, event) {
if (this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
this.emit('activate');
return false;
},
_updateMenuOnHoverChanged: function() {
if (!this.actor.hover && this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
return false;
},
_updateMenuOnButtonPress: function(actor, event) {
let button = event.get_button();
if (button == 1) {
if (this._menuTimeoutId != 0)
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = Mainloop.timeout_add(APPICON_MENU_POPUP_TIMEOUT_MS,
Lang.bind(this, function () { this.popupMenu(button); }));
} else if (button == 3) {
this.popupMenu(button);
}
return false;
},
popupMenu: function(activatingButton) {
if (this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
this.actor.fake_release();
if (!this._menu) {
this._menu = new AppIconMenu(this, this._menuType);
this._menu.connect('highlight-window', Lang.bind(this, function (menu, window) {
this.highlightWindow(window);
}));
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
this.activateWindow(window);
}));
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
if (isPoppedUp)
this.menuPoppedUp();
else
this.menuPoppedDown();
}));
}
this._menu.popup(activatingButton);
return false;
},
// Default implementations; AppDisplay.RunningWellItem overrides these
highlightWindow: function(window) {
this.emit('highlight-window', window);
},
activateWindow: function(window) {
this.emit('activate-window', window);
},
menuPoppedUp: function() {
this.emit('menu-popped-up', this._menu);
},
menuPoppedDown: function() {
this.emit('menu-popped-down', this._menu);
}
};
Signals.addSignalMethods(AppIcon.prototype);
function AppIconMenu(source, type) {
this._init(source, type);
}
AppIconMenu.prototype = {
_init: function(source, type) {
this._source = source;
this._type = type;
this.actor = new Shell.GenericContainer({ reactive: true });
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._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
border_color: source.highlight_border_color,
border: APPICON_MENU_BORDER_WIDTH,
background_color: APPICON_MENU_BACKGROUND_COLOR,
padding: 4,
corner_radius: APPICON_MENU_CORNER_RADIUS,
width: Main.overview._dash.actor.width * 0.75 });
this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
this.actor.add_actor(this._windowContainer);
// Stay popped up on release over application icon
this._windowContainer.set_persistent_source(this._source.actor);
// Intercept events while the menu has the pointer grab to do window-related effects
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
this._arrow = new St.DrawingArea();
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
Shell.draw_box_pointer(texture,
this._type == MenuType.ON_RIGHT ? Shell.PointerDirection.LEFT : Shell.PointerDirection.UP,
source.highlight_border_color,
APPICON_MENU_BACKGROUND_COLOR);
}));
this.actor.add_actor(this._arrow);
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
if (!source.actor.mapped)
this._windowContainer.popdown();
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
global.stage.add_actor(this.actor);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
if (this._type == MenuType.ON_RIGHT) {
min += APPICON_MENU_ARROW_SIZE;
natural += APPICON_MENU_ARROW_SIZE;
}
alloc.min_size = min;
alloc.natural_size = natural;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
if (this._type == MenuType.BELOW) {
min += APPICON_MENU_ARROW_SIZE;
natural += APPICON_MENU_ARROW_SIZE;
}
alloc.min_size = min;
alloc.natural_size = natural;
},
_allocate: function(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
if (this._type == MenuType.ON_RIGHT) {
childBox.x1 = 0;
childBox.x2 = APPICON_MENU_ARROW_SIZE;
childBox.y1 = Math.floor((height / 2) - (APPICON_MENU_ARROW_SIZE / 2));
childBox.y2 = childBox.y1 + APPICON_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
childBox.x1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
childBox.x2 = width;
childBox.y1 = 0;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
} else /* MenuType.BELOW */ {
childBox.x1 = Math.floor((width / 2) - (APPICON_MENU_ARROW_SIZE / 2));
childBox.x2 = childBox.x1 + APPICON_MENU_ARROW_SIZE;
childBox.y1 = 0;
childBox.y2 = APPICON_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
childBox.x1 = 0;
childBox.x2 = width;
childBox.y1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
}
},
_redisplay: function() {
this._windowContainer.remove_all();
let windows = this._source.app.get_windows();
this._windowContainer.show();
let iconsDiffer = false;
let texCache = Shell.TextureCache.get_default();
if (windows.length > 0) {
let firstIcon = windows[0].mini_icon;
for (let i = 1; i < windows.length; i++) {
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
iconsDiffer = true;
break;
}
}
}
// Display the app windows menu items and the separator between windows
// of the current desktop and other windows.
let activeWorkspace = global.screen.get_active_workspace();
let separatorShown = windows.length > 0 && windows[0].get_workspace() != activeWorkspace;
for (let i = 0; i < windows.length; i++) {
if (!separatorShown && windows[i].get_workspace() != activeWorkspace) {
this._appendSeparator();
separatorShown = true;
}
let icon = null;
if (iconsDiffer)
icon = Shell.TextureCache.get_default().bind_pixbuf_property(windows[i], "mini-icon");
let box = this._appendMenuItem(icon, windows[i].title);
box._window = windows[i];
}
if (windows.length > 0)
this._appendSeparator();
let isFavorite = AppFavorites.getAppFavorites().isFavorite(this._source.app.get_id());
this._newWindowMenuItem = windows.length > 0 ? this._appendMenuItem(null, _("New Window")) : null;
if (windows.length > 0)
this._appendSeparator();
this._toggleFavoriteMenuItem = this._appendMenuItem(null, isFavorite ? _("Remove from Favorites")
: _("Add to Favorites"));
this._highlightedItem = null;
},
_appendSeparator: function () {
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
box.append(new Clutter.Rectangle({ height: 1,
color: APPICON_MENU_SEPARATOR_COLOR }),
Big.BoxPackFlags.EXPAND);
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
},
_appendMenuItem: function(iconTexture, labelText) {
/* Use padding here rather than spacing in the box above so that
* we have a larger reactive area.
*/
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: 4,
padding_bottom: 4,
spacing: 4,
reactive: true });
let vCenter;
if (iconTexture != null) {
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
vCenter.append(iconTexture, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
}
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let label = new Clutter.Text({ text: labelText,
font_name: APPICON_MENU_FONT,
ellipsize: Pango.EllipsizeMode.END,
color: APPICON_MENU_COLOR });
vCenter.append(label, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
return box;
},
popup: function(activatingButton) {
let [stageX, stageY] = this._source.actor.get_transformed_position();
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
this._redisplay();
this._windowContainer.popup(activatingButton, global.get_current_time());
this.emit('popup', true);
let x, y;
if (this._type == MenuType.ON_RIGHT) {
x = Math.floor(stageX + stageWidth);
y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
} else {
x = Math.floor(stageX + (stageWidth / 2) - (this.actor.width / 2));
y = Math.floor(stageY + stageHeight);
}
this.actor.set_position(x, y);
this.actor.show();
},
popdown: function() {
this._windowContainer.popdown();
this.emit('popup', false);
this.actor.hide();
},
selectWindow: function(metaWindow) {
this._selectMenuItemForWindow(metaWindow);
},
_findMetaWindowForActor: function (actor) {
if (actor._delegate instanceof Workspaces.WindowClone)
return actor._delegate.metaWindow;
else if (actor.get_meta_window)
return actor.get_meta_window();
return null;
},
// This function is called while the menu has a pointer grab; what we want
// to do is see if the mouse was released over a window representation
_onMenuButtonRelease: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this.emit('activate-window', metaWindow);
}
},
_updateHighlight: function (item) {
if (this._highlightedItem) {
this._highlightedItem.background_color = TRANSPARENT_COLOR;
this.emit('highlight-window', null);
}
this._highlightedItem = item;
if (this._highlightedItem) {
this._highlightedItem.background_color = APPICON_MENU_SELECTED_COLOR;
let window = this._highlightedItem._window;
if (window)
this.emit('highlight-window', window);
}
},
_selectMenuItemForWindow: function (metaWindow) {
let children = this._windowContainer.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
let menuMetaWindow = child._window;
if (menuMetaWindow == metaWindow)
this._updateHighlight(child);
}
},
// Called while menu has a pointer grab
_onMenuEnter: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this._selectMenuItemForWindow(metaWindow);
}
},
// Called while menu has a pointer grab
_onMenuLeave: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this._updateHighlight(null);
}
},
_onItemUnselected: function (actor, child) {
this._updateHighlight(null);
},
_onItemSelected: function (actor, child) {
this._updateHighlight(child);
},
_onItemActivate: function (actor, child) {
if (child._window) {
let metaWindow = child._window;
this.emit('activate-window', metaWindow);
} else if (child == this._newWindowMenuItem) {
this._source.app.launch();
this.emit('activate-window', null);
} else if (child == this._toggleFavoriteMenuItem) {
let favs = AppFavorites.getAppFavorites();
let isFavorite = favs.isFavorite(this._source.app.get_id());
if (isFavorite)
favs.removeFavorite(this._source.app.get_id());
else
favs.addFavorite(this._source.app.get_id());
}
this.popdown();
},
_onWindowSelectionCancelled: function () {
this.emit('highlight-window', null);
this.popdown();
}
};
Signals.addSignalMethods(AppIconMenu.prototype);

View File

@ -31,7 +31,7 @@ Calendar.prototype = {
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;
this._weekStart = 0;
}
// Find the ordering for month/year in the calendar heading
@ -63,14 +63,19 @@ Calendar.prototype = {
this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: 7 });
let back = new St.Button({ label: "&lt;", style_class: 'calendar-change-month' });
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: "&gt;", style_class: 'calendar-change-month' });
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
this._topBox.add(forward);
forward.connect("clicked", Lang.bind(this, this._nextMonth));
@ -84,7 +89,7 @@ Calendar.prototype = {
this.actor.add(new St.Label({ text: iter.toLocaleFormat("%a") }),
{ row: 1,
col: (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: 1.0 });
x_fill: false, x_align: St.Align.END });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
@ -163,7 +168,7 @@ Calendar.prototype = {
label.style_class = "calendar-day";
this.actor.add(label,
{ row: row, col: (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: 1.0 });
x_fill: false, x_align: St.Align.END });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
if (iter.getDay() == this._weekStart) {

View File

@ -208,9 +208,14 @@ 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.OVERRIDE_REDIRECT ||
layer == Meta.StackLayer.FULLSCREEN) {
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 <= primary.x &&
windows[i].x + windows[i].width >= primary.x + primary.width &&
windows[i].y <= primary.y &&

View File

@ -13,6 +13,7 @@ const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay;
const DND = imports.ui.dnd;
const DocDisplay = imports.ui.docDisplay;
const PlaceDisplay = imports.ui.placeDisplay;
const GenericDisplay = imports.ui.genericDisplay;
@ -49,8 +50,6 @@ SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff);
const BROWSE_ACTIVATED_BG = new Clutter.Color();
BROWSE_ACTIVATED_BG.from_pixel(0x303030f0);
const APPS = "apps";
const PREFS = "prefs";
const DOCS = "docs";
const PLACES = "places";
@ -68,11 +67,7 @@ function _getIndexWrapped(index, increment, length) {
}
function _createDisplay(displayType, flags) {
if (displayType == APPS)
return new AppDisplay.AppDisplay(false, flags);
else if (displayType == PREFS)
return new AppDisplay.AppDisplay(true, flags);
else if (displayType == DOCS)
if (displayType == DOCS)
return new DocDisplay.DocDisplay(flags);
else if (displayType == PLACES)
return new PlaceDisplay.PlaceDisplay(flags);
@ -363,6 +358,8 @@ SearchResult.prototype = {
this.actor.set_child(content);
this.actor.connect('clicked', Lang.bind(this, this._onResultClicked));
let draggable = DND.makeDraggable(this.actor);
},
setSelected: function(selected) {
@ -376,6 +373,21 @@ SearchResult.prototype = {
_onResultClicked: function(actor, event) {
this.activate();
},
getDragActorSource: function() {
return this.metaInfo['icon'];
},
getDragActor: function(stageX, stageY) {
return new Clutter.Clone({ source: this.metaInfo['icon'] });
},
shellWorkspaceLaunch: function() {
if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id);
else
this.provider.activateResult(this.metaInfo.id);
}
}
@ -433,9 +445,8 @@ SearchResults.prototype = {
this.actor = new St.BoxLayout({ name: 'dashSearchResults',
vertical: true });
this._searchingNotice = new St.Label({ style_class: 'dash-search-starting',
text: _("Searching...") });
this.actor.add(this._searchingNotice);
this._statusText = new St.Label({ style_class: 'dash-search-statustext' });
this.actor.add(this._statusText);
this._selectedProvider = -1;
this._providers = this._searchSystem.getProviders();
this._providerMeta = [];
@ -485,13 +496,14 @@ SearchResults.prototype = {
reset: function() {
this._searchSystem.reset();
this._searchingNotice.hide();
this._statusText.hide();
this._clearDisplay();
},
startingSearch: function() {
this.reset();
this._searchingNotice.show();
this._statusText.set_text(_("Searching..."));
this._statusText.show();
},
_metaForProvider: function(provider) {
@ -501,9 +513,16 @@ SearchResults.prototype = {
updateSearch: function (searchString) {
let results = this._searchSystem.updateSearch(searchString);
this._searchingNotice.hide();
this._clearDisplay();
if (results.length == 0) {
this._statusText.set_text(_("No matching results."));
this._statusText.show();
return true;
} else {
this._statusText.hide();
}
let terms = this._searchSystem.getTerms();
for (let i = 0; i < results.length; i++) {
@ -594,8 +613,8 @@ MoreLink.prototype = {
reactive: true });
this.pane = null;
let expander = new St.Bin({ style_class: "more-link-expander" });
this.actor.add(expander, { expand: true, y_fill: false });
this._expander = new St.Bin({ style_class: "more-link-expander" });
this.actor.add(this._expander, { expand: true, y_fill: false });
},
activate: function() {
@ -610,6 +629,10 @@ MoreLink.prototype = {
setPane: function (pane) {
this._pane = pane;
this._pane.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
if (!isOpen)
this._expander.style_class = 'more-link-expander';
else
this._expander.style_class = 'more-link-expander open';
}));
}
}
@ -859,13 +882,12 @@ Dash.prototype = {
let appWell = new AppDisplay.AppWell();
this._appsSection.content.add(appWell.actor, { expand: true });
this._moreAppsPane = null;
this._allApps = null;
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
if (this._moreAppsPane == null) {
this._moreAppsPane = new ResultPane(this);
this._moreAppsPane.packResults(APPS);
this._addPane(this._moreAppsPane);
link.setPane(this._moreAppsPane);
if (this._allApps == null) {
this._allApps = new AppDisplay.AllAppDisplay();
this._addPane(this._allApps);
link.setPane(this._allApps);
}
}));
@ -875,14 +897,14 @@ Dash.prototype = {
/* Translators: This is in the sense of locations for documents,
network locations, etc. */
this._placesSection = new Section(_("PLACES"), true);
this._placesSection = new Section(_("PLACES & DEVICES"), true);
let placesDisplay = new PlaceDisplay.DashPlaceDisplay();
this._placesSection.content.add(placesDisplay.actor, { expand: true });
this.sectionArea.add(this._placesSection.actor);
/***** Documents *****/
this._docsSection = new Section(_("RECENT DOCUMENTS"));
this._docsSection = new Section(_("RECENT ITEMS"));
this._docDisplay = new DocDisplay.DashDocDisplay();
this._docsSection.content.add(this._docDisplay.actor, { expand: true });

View File

@ -357,34 +357,37 @@ 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 maxNatural = 0;
for (let i = 0; i < children.length; i++) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(this._itemWidth);
maxNatural = Math.max(maxNatural, naturalSize);
}
this._itemHeight = maxNatural;
let firstColumnChildren = Math.ceil(children.length / 2);
let natural = 0;
for (let i = 0; i < firstColumnChildren; i++) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(-1);
natural += naturalSize;
if (i > 0 && i < children.length - 1) {
natural += DEFAULT_SPACING;
}
}
alloc.natural_size = natural;
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
@ -393,9 +396,7 @@ DashDocDisplay.prototype = {
while (i < children.length) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(-1);
if (y + naturalSize > box.y2) {
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.
@ -404,9 +405,9 @@ DashDocDisplay.prototype = {
}
// 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.
@ -416,13 +417,13 @@ DashDocDisplay.prototype = {
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++;
}
@ -438,7 +439,6 @@ DashDocDisplay.prototype = {
this._checkDocExistence = false;
}
let skipPaint = [];
for (; i < children.length; i++)
this.actor.set_skip_paint(children[i], true);
},
@ -485,7 +485,7 @@ DocSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function(name) {
Search.SearchProvider.prototype._init.call(this, _("DOCUMENTS"));
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
this._docManager = DocInfo.getDocManager();
},

View File

@ -608,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");
},

View File

@ -12,6 +12,7 @@ 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
*
@ -29,24 +30,24 @@ SHADE_COLOR.from_pixel(0x00000044);
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height
*/
function Lightbox(container, width, height) {
this._init(container, width, height);
function Lightbox(container, inhibitEvents, width, height) {
this._init(container, inhibitEvents, width, height);
}
Lightbox.prototype = {
_init : function(container, width, height) {
_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: true });
reactive: inhibitEvents });
container.add_actor(this.actor);
this.actor.raise_top();
this._destroySignalId = this.actor.connect('destroy', Lang.bind(this, this.destroy));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
if (width && height) {
this.actor.width = width;
@ -134,18 +135,24 @@ Lightbox.prototype = {
/**
* destroy:
*
* Destroys the lightbox. This is called automatically if the
* lightbox's container is destroyed.
* 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.actor.disconnect(this._destroySignalId);
this.highlight(null);
this.actor.destroy();
}
};

View File

@ -15,11 +15,14 @@ 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 WindowManager = imports.ui.windowManager;
@ -35,6 +38,9 @@ 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;
@ -42,6 +48,8 @@ let modalActorFocusStack = [];
let _errorLogStack = [];
let _startDate;
let background = null;
function start() {
// Add a binding for "global" in the global JS namespace; (gjs
// keeps the web browser convention of having that namespace be
@ -93,10 +101,6 @@ function start() {
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
themeContext.set_theme (theme);
global.connect('panel-run-dialog', function(panel) {
// Make sure not more than one run dialog is shown.
getRunDialog().open();
});
let shellwm = global.window_manager;
shellwm.takeover_keybinding("panel_main_menu");
shellwm.connect("keybinding::panel_main_menu", function () {
@ -113,6 +117,9 @@ function start() {
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();
@ -124,11 +131,25 @@ 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();
@ -137,11 +158,11 @@ function start() {
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);
}
@ -192,6 +213,15 @@ function _relayout() {
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,
@ -373,12 +403,14 @@ function getRunDialog() {
* 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
* Activates @window, switching to its workspace first if necessary,
* and switching out of the overview if it's currently active
*/
function activateWindow(window, time) {
function activateWindow(window, time, workspaceNum) {
let activeWorkspaceNum = global.screen.get_active_workspace_index();
let windowWorkspaceNum = window.get_workspace().index();
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
if (!time)
time = global.get_current_time();
@ -389,6 +421,8 @@ function activateWindow(window, time) {
} else {
window.activate(time);
}
overview.hide();
}
// TODO - replace this timeout with some system to guess when the user might

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,6 +8,9 @@ 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;
@ -16,10 +19,7 @@ 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;
@ -73,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();
@ -84,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;
@ -110,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();
@ -121,8 +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) {
@ -132,13 +244,52 @@ 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 () {
let primary = global.get_primary_monitor();
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
@ -158,6 +309,8 @@ Overview.prototype = {
relayout: function () {
let primary = global.get_primary_monitor();
this._recalculateGridSizes();
this._group.set_position(primary.x, primary.y);
let contentY = Panel.PANEL_HEIGHT;
@ -185,10 +338,14 @@ Overview.prototype = {
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 = primary.height - Math.floor(displayGridRowHeight * 4/5);
this._workspacesBarX = this._workspacesX;
this._workspacesBarWidth = primary.width - this._workspacesBarX - WORKSPACE_GRID_PADDING;
this._workspacesBarY = primary.height - displayGridRowHeight;
// The parent (this._group) is positioned at the top left of the primary monitor
// while this._backOver occupies the entire screen.
@ -204,12 +361,10 @@ Overview.prototype = {
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.
@ -217,10 +372,10 @@ 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 () {
@ -235,7 +390,7 @@ Overview.prototype = {
backgroundEventId = null;
}
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._paneContainer.hide();
this._workspaces.actor.opacity = 255;
}
}));
@ -296,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
@ -305,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
@ -361,9 +512,8 @@ Overview.prototype = {
this._activeDisplayPane.close();
this._workspaces.hide();
this._addButton.actor.destroy();
this._addButton.actor = null;
this._addButton = null;
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
@ -411,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() {
@ -446,7 +582,7 @@ Overview.prototype = {
this._dash.hide();
this._group.hide();
this.visible = false;
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
@ -454,43 +590,6 @@ Overview.prototype = {
Main.popModal(this._dash.actor);
this.emit('hidden');
},
_addNewWorkspace: function() {
global.screen.append_new_workspace(false, global.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

@ -13,6 +13,7 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay;
const Calendar = imports.ui.calendar;
const Main = imports.ui.main;
const StatusMenu = imports.ui.statusMenu;
@ -46,6 +47,99 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'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();
}
@ -59,10 +153,11 @@ AppPanelMenu.prototype = {
this._startupSequences = {};
this.actor = new St.BoxLayout({ name: 'appMenu' });
this._iconBox = new St.Bin({ name: 'appMenuIcon' });
this._iconBox = new Shell.Slicer({ name: 'appMenuIcon' });
this.actor.add(this._iconBox);
this._label = new St.Label();
this.actor.add(this._label, { expand: true, y_fill: false });
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 St.BoxLayout();
this.actor.add(this._startupBox);
@ -86,6 +181,16 @@ AppPanelMenu.prototype = {
this._sync();
},
_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;
},
_sync: function() {
let tracker = Shell.WindowTracker.get_default();
@ -112,20 +217,24 @@ AppPanelMenu.prototype = {
if (this._iconBox.child != null)
this._iconBox.child.destroy();
this._iconBox.hide();
this._label.set_text('');
this._label.setText('');
let icon;
if (this._focusedApp != null) {
let icon = this._focusedApp.create_icon_texture(PANEL_ICON_SIZE);
this._iconBox.set_child(icon);
this._iconBox.show();
let appName = this._focusedApp.get_name();
// Use _set_text to work around http://bugzilla.openedhand.com/show_bug.cgi?id=1851
this._label.set_text(appName);
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.set_child(icon);
this._iconBox.show();
this._label.set_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');
}
@ -289,6 +398,7 @@ Panel.prototype = {
this._clock = new St.Label();
clockButton.set_child(this._clock);
this._clockButton = clockButton;
this._calendarPopup = null;
@ -376,6 +486,13 @@ Panel.prototype = {
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,
@ -436,8 +553,15 @@ 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;
},
@ -452,11 +576,47 @@ Panel.prototype = {
}
},
_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();
}
}

View File

@ -114,7 +114,7 @@ PlacesManager.prototype = {
this._defaultPlaces = [];
this._mounts = [];
this._bookmarks = [];
this._isDesktopHome = false;
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();
@ -172,6 +172,7 @@ PlacesManager.prototype = {
this._defaultPlaces.push(this._home);
this._desktopMenuIndex = this._defaultPlaces.length;
if (!this._isDesktopHome)
this._defaultPlaces.push(this._desktopMenu);
@ -211,7 +212,6 @@ PlacesManager.prototype = {
}));
this._reloadBookmarks();
this._updateDesktopMenuVisibility();
gconf.connect('changed::' + DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
@ -327,6 +327,12 @@ PlacesManager.prototype = {
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');
@ -353,13 +359,13 @@ PlacesManager.prototype = {
return this._mounts;
},
_lookupById: function(sourceArray, id) {
_lookupIndexById: function(sourceArray, id) {
for (let i = 0; i < sourceArray.length; i++) {
let place = sourceArray[i];
if (place.id == id)
return place;
return i;
}
return null;
return -1;
},
lookupPlaceById: function(id) {
@ -372,7 +378,11 @@ PlacesManager.prototype = {
sourceArray = this._mounts;
else if (type == 'bookmark')
sourceArray = this._bookmarks;
return this._lookupById(sourceArray, id);
return sourceArray[this._lookupIndexById(sourceArray, id)];
},
_removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
}
};
@ -516,7 +526,7 @@ PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("PLACES"));
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
},
getResultMeta: function(resultId) {

View File

@ -42,7 +42,14 @@ CommandCompleter.prototype = {
for (let i = 0; i < this._paths.length; i++) {
this._childs[i] = [];
let file = Gio.file_new_for_path(this._paths[i]);
let info = file.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, null);
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;
@ -53,6 +60,9 @@ CommandCompleter.prototype = {
this._monitors[i].connect("changed", Lang.bind(this, this._onChanged));
}
}
this._paths = this._paths.filter(function(a) {
return a != null;
});
this._update(0);
},
@ -206,7 +216,7 @@ RunDialog.prototype = {
height: global.screen_height });
global.stage.add_actor(this._group);
let lightbox = new Lightbox.Lightbox(this._group);
let lightbox = new Lightbox.Lightbox(this._group, true);
this._boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,

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,8 +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) {
@ -90,7 +99,7 @@ Sidebar.prototype = {
_adjustPosition: function() {
let primary=global.get_primary_monitor();
this.actor.y = Math.max(primary.y + Panel.PANEL_HEIGHT,primary.height/2 - this.actor.height/2);
this.actor.y = Math.floor(Math.max(primary.y + Panel.PANEL_HEIGHT,primary.height/2 - this.actor.height/2));
this.actor.x = primary.x;
},
@ -118,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++)
@ -135,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();

View File

@ -30,7 +30,7 @@ StatusMenu.prototype = {
this._user = this._gdm.get_user(GLib.get_user_name());
this._presence = new GnomeSessionPresence();
this.actor = new St.BoxLayout({ name: 'StatusMenu' });
this.actor = new St.BoxLayout({ name: 'statusMenu' });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._iconBox = new St.Bin();
@ -104,17 +104,17 @@ StatusMenu.prototype = {
let item;
item = this._createImageMenuItem(_('Available'), 'gtk-yes', true);
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 = 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 = this._createImageMenuItem(_("Invisible"), 'gtk-close', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSessionPresenceStatus.INVISIBLE));
this._menu.append(item);
item.show();
@ -123,13 +123,13 @@ StatusMenu.prototype = {
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_('Account Information...'), 'user-info');
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'),
item = new Gtk.CheckMenuItem({ label: _("Sidebar"),
active: gconf.get_boolean(SIDEBAR_VISIBLE_KEY) });
item.connect('activate', Lang.bind(this,
function() {
@ -139,7 +139,7 @@ StatusMenu.prototype = {
item.show();
this._sidebarItem = item;
item = this._createImageMenuItem(_('System Preferences...'), 'preferences-desktop');
item = this._createImageMenuItem(_("System Preferences..."), 'preferences-desktop');
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this._menu.append(item);
item.show();
@ -148,23 +148,23 @@ StatusMenu.prototype = {
this._menu.append(item);
item.show();
item = this._createImageMenuItem(_('Lock Screen'), 'system-lock-screen');
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 = 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 = 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 = this._createImageMenuItem(_("Shut Down..."), 'system-shutdown');
item.connect('activate', Lang.bind(this, this._onShutDownActivate));
this._menu.append(item);
item.show();

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

@ -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");
@ -373,6 +373,20 @@ WidgetBox.prototype = {
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() {
if (this._widget.destroy)
this._widget.destroy();

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

@ -7,6 +7,7 @@ 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;
@ -42,6 +43,17 @@ WindowManager.prototype = {
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) {
@ -74,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,
@ -272,9 +289,45 @@ WindowManager.prototype = {
},
_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();
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,4 +1,5 @@
ar
bg
ca
cs
da
@ -22,6 +23,9 @@ pt_BR
ro
ru
sl
sr
sr@latin
sv
tr
vi
zh_CN

View File

@ -1,11 +1,14 @@
data/gnome-shell.desktop.in.in
js/ui/appDisplay.js
js/ui/appIcon.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

197
po/ar.po
View File

@ -1,13 +1,13 @@
# 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.
# Khaled Hosny <khaledhosny@eglug.org>, 2009, 2010.
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-11-08 20:55+0200\n"
"PO-Revision-Date: 2009-11-08 20:55+0300\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"
@ -16,7 +16,7 @@ msgstr ""
"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.4.1\n"
"X-Generator: Virtaal 0.5.1\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
@ -26,84 +26,75 @@ msgstr "صدفة جنوم"
msgid "Window management and application launching"
msgstr "إدارة النوافذ وإطلاق التطبيقات"
#: ../js/ui/appDisplay.js:332
msgid "Frequent"
msgstr "متكرر"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "التطبيقات"
#: ../js/ui/appDisplay.js:867
msgid "Drag here to add favorites"
msgstr "اسحب إلى هنا ليضاف إلى المفضّلة"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "التفضيلات"
#: ../js/ui/appIcon.js:426
#: ../js/ui/appDisplay.js:644
msgid "New Window"
msgstr "نافذة جديدة"
#: ../js/ui/appIcon.js:430
#: ../js/ui/appDisplay.js:648
msgid "Remove from Favorites"
msgstr "أزِل من المفضّلة"
#: ../js/ui/appIcon.js:431
#: ../js/ui/appDisplay.js:649
msgid "Add to Favorites"
msgstr "أضِف إلى المفضّلة"
#: ../js/ui/dash.js:267
#: ../js/ui/appDisplay.js:1001
msgid "Drag here to add favorites"
msgstr "اسحب إلى هنا ليضاف إلى المفضّلة"
#: ../js/ui/dash.js:240
msgid "Find..."
msgstr "ابحث..."
#: ../js/ui/dash.js:376
msgid "More"
msgstr "المزيد"
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "يبحث..."
#: ../js/ui/dash.js:532
msgid "(see all)"
msgstr "(انظر الكل)"
#. **** Applications ****
#: ../js/ui/dash.js:711 ../js/ui/dash.js:773
msgid "APPLICATIONS"
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:731
msgid "PLACES"
msgstr "الأماكن"
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "الأماكن والأجهزة"
#. **** Documents ****
#: ../js/ui/dash.js:738 ../js/ui/dash.js:783
msgid "RECENT DOCUMENTS"
msgstr "المستندات الحديثة"
#. **** Search Results ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:947
msgid "SEARCH RESULTS"
msgstr "نتائج البحث"
#: ../js/ui/dash.js:778
msgid "PREFERENCES"
msgstr "التفضيلات"
#: ../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:274
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "الأنشطة"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%A %Ol:%OM %p"
#: ../js/ui/places.js:178
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "اتّصل ب‍..."
#: ../js/ui/runDialog.js:96
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "من فضلك اكتب أمرا:"
#: ../js/ui/runDialog.js:173
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "فشل تنفيذ '%s':"
@ -121,11 +112,11 @@ msgstr "التطبيقات"
msgid "Recent Documents"
msgstr "المستندات الحديثة"
#: ../src/shell-global.c:821
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "منذ أقل من دقيقة"
#: ../src/shell-global.c:824
#: ../src/shell-global.c:894
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -136,7 +127,7 @@ msgstr[3] "منذ %d دقائق"
msgstr[4] "منذ %d دقيقة"
msgstr[5] "منذ %d دقيقة"
#: ../src/shell-global.c:827
#: ../src/shell-global.c:899
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -147,7 +138,7 @@ msgstr[3] "منذ %d ساعات"
msgstr[4] "منذ %d ساعة"
msgstr[5] "منذ %d ساعة"
#: ../src/shell-global.c:830
#: ../src/shell-global.c:904
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -158,7 +149,7 @@ msgstr[3] "منذ %d أيام"
msgstr[4] "منذ %d يوما"
msgstr[5] "منذ %d يوم"
#: ../src/shell-global.c:833
#: ../src/shell-global.c:909
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -169,67 +160,17 @@ msgstr[3] "منذ %d أسابيع"
msgstr[4] "منذ %d أسبوعا"
msgstr[5] "منذ %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
#: ../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:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "نظام الملفات"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "ابحث"
@ -238,10 +179,58 @@ msgstr "ابحث"
#. * 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 "متكرر"
#~ 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"

197
po/cs.po
View File

@ -1,14 +1,14 @@
# 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-11-05 18:03+0100\n"
"PO-Revision-Date: 2009-11-05 18:03+0100\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"
@ -25,84 +25,75 @@ msgstr "Prostředí GNOME Shell"
msgid "Window management and application launching"
msgstr "Správa oken a spouštění aplikací"
#: ../js/ui/appDisplay.js:332
msgid "Frequent"
msgstr "Časté"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "APLIKACE"
#: ../js/ui/appDisplay.js:867
msgid "Drag here to add favorites"
msgstr "Oblíbené přidáte přetažením sem"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "PŘEDVOLBY"
#: ../js/ui/appIcon.js:426
#: ../js/ui/appDisplay.js:644
msgid "New Window"
msgstr "Nové okno"
#: ../js/ui/appIcon.js:430
#: ../js/ui/appDisplay.js:648
msgid "Remove from Favorites"
msgstr "Odstranit z oblíbených"
#: ../js/ui/appIcon.js:431
#: ../js/ui/appDisplay.js:649
msgid "Add to Favorites"
msgstr "Přidat mezi oblíbené"
#: ../js/ui/dash.js:267
#: ../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:376
msgid "More"
msgstr "Více"
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "Hledá se..."
#: ../js/ui/dash.js:532
msgid "(see all)"
msgstr "(zobrazit vše)"
#. **** Applications ****
#: ../js/ui/dash.js:711 ../js/ui/dash.js:773
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:731
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:738 ../js/ui/dash.js:783
msgid "RECENT DOCUMENTS"
msgstr "NEDÁVNÉ DOKUMENTY"
#. **** Search Results ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:947
msgid "SEARCH RESULTS"
msgstr "VÝSLEDKY HLEDÁNÍ"
#: ../js/ui/dash.js:778
msgid "PREFERENCES"
msgstr "PŘEDVOLBY"
#: ../js/ui/dash.js:892
msgid "RECENT ITEMS"
msgstr "NEDÁVNÉ POLOŽKY"
#. 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
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Činnosti"
#. Translators: This is a time format.
#: ../js/ui/panel.js:491
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/places.js:178
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Připojit se k..."
#: ../js/ui/runDialog.js:96
#: ../js/ui/runDialog.js:235
msgid "Please enter a command:"
msgstr "Zadejte prosím příkaz:"
#: ../js/ui/runDialog.js:173
#: ../js/ui/runDialog.js:351
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Vykonání \"%s\" selhalo:"
@ -120,11 +111,11 @@ msgstr "Aplikace"
msgid "Recent Documents"
msgstr "Nedávné dokumenty"
#: ../src/shell-global.c:821
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Před méně než minutou"
#: ../src/shell-global.c:824
#: ../src/shell-global.c:893
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -132,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:827
#: ../src/shell-global.c:896
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -140,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:830
#: ../src/shell-global.c:899
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -148,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:833
#: ../src/shell-global.c:902
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -156,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"
@ -225,11 +166,59 @@ 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"

205
po/de.po
View File

@ -5,16 +5,16 @@
# 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.
# Mario Blättermann <mariobl@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-10-16 20:05+0000\n"
"PO-Revision-Date: 2009-10-17 23:37+0200\n"
"Last-Translator: Christian Kirbach <Christian.Kirbach@googlemail.com>\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"
@ -29,192 +29,137 @@ msgstr "GNOME-Shell"
msgid "Window management and application launching"
msgstr "Fenster verwalten und Anwendungen starten"
#: ../js/ui/appDisplay.js:335
msgid "Frequent"
msgstr "Häufig"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "ANWENDUNGEN"
#: ../js/ui/appIcon.js:407
#: ../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/appIcon.js:420
#: ../js/ui/appDisplay.js:711 ../js/ui/appIcon.js:429
msgid "Remove from Favorites"
msgstr "Aus Favoriten entfernen"
#: ../js/ui/appIcon.js:421
#: ../js/ui/appDisplay.js:712 ../js/ui/appIcon.js:430
msgid "Add to Favorites"
msgstr "Zu Favoriten hinzufügen"
#: ../js/ui/dash.js:283
#: ../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:400
msgid "More"
msgstr "Mehr"
#: ../js/ui/dash.js:493
#| msgid "Search"
msgid "Searching..."
msgstr "Suche läuft …"
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(alle sehen)"
#. **** Applications ****
#: ../js/ui/dash.js:725 ../js/ui/dash.js:787
msgid "APPLICATIONS"
msgstr "ANWENDUNGEN"
#: ../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:745
msgid "PLACES"
msgstr "ORTE"
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr "ORTE UND GERÄTE"
#. **** Documents ****
#: ../js/ui/dash.js:752 ../js/ui/dash.js:797
msgid "RECENT DOCUMENTS"
#: ../js/ui/dash.js:892
#| msgid "RECENT DOCUMENTS"
msgid "RECENT ITEMS"
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
#. **** Search Results ****
#: ../js/ui/dash.js:777 ../js/ui/dash.js:961
msgid "SEARCH RESULTS"
msgstr "SUCHERGEBNISSE"
#: ../js/ui/dash.js:792
msgid "PREFERENCES"
msgstr "EINSTELLUNGEN"
#. 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:273
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Aktivitäten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:465
#: ../js/ui/panel.js:549
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/places.js:178
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Verbinden mit …"
#: ../js/ui/runDialog.js:96
#: ../js/ui/runDialog.js:235
msgid "Please enter a command:"
msgstr "Bitte geben Sie einen Befehl ein:"
#: ../js/ui/runDialog.js:173
#: ../js/ui/runDialog.js:351
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Ausführung von »%s« ist gescheitert:"
#. Translators: This is a time format.
#: ../js/ui/widget.js:162
#: ../js/ui/widget.js:163
msgid "%H:%M"
msgstr "%H:%M"
#: ../js/ui/widget.js:316
#: ../js/ui/widget.js:317
msgid "Applications"
msgstr "Anwendungen"
#: ../js/ui/widget.js:341
#: ../js/ui/widget.js:339
msgid "Recent Documents"
msgstr "Zuletzt geöffnete Dokumente"
#: ../src/shell-global.c:812
#: ../src/shell-global.c:890
msgid "Less than a minute ago"
msgstr "Vor weniger als einer Minute"
#: ../src/shell-global.c:815
#: ../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:818
#: ../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:821
#: ../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:824
#: ../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"
@ -223,11 +168,61 @@ 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"

172
po/es.po
View File

@ -1,15 +1,14 @@
# 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-12-18 15:06+0000\n"
"PO-Revision-Date: 2009-12-19 14:41+0100\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"
@ -26,7 +25,7 @@ msgid "Window management and application launching"
msgstr "Gestión de ventanas e inicio de aplicaciones"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:852
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "APLICACIONES"
@ -34,67 +33,158 @@ msgstr "APLICACIONES"
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/appDisplay.js:707 ../js/ui/appIcon.js:425
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Ventana nueva"
#: ../js/ui/appDisplay.js:711 ../js/ui/appIcon.js:429
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Quitar de los favoritos"
#: ../js/ui/appDisplay.js:712 ../js/ui/appIcon.js:430
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Añadir a los favoritos"
#: ../js/ui/appDisplay.js:1064
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Arrastrar aquí para añadir a los favoritos"
#: ../js/ui/dash.js:240
#: ../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:437
#| msgid "Search"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Buscando…"
#: ../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:872 ../js/ui/placeDisplay.js:471
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:879
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECIENTES"
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "ELEMENTOS RECIENTES"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "No hay extensiones instaladas"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Activado"
#: ../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:227
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Actividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:440
#. 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:99
#: ../js/ui/placeDisplay.js:144
msgid "Connect to..."
msgstr "Conectar a…"
#: ../js/ui/runDialog.js:96
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Introduzca un comando:"
#: ../js/ui/runDialog.js:173
#: ../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"
@ -108,32 +198,32 @@ msgstr "Aplicaciones"
msgid "Recent Documents"
msgstr "Documentos recientes"
#: ../src/shell-global.c:826
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Hace menos de un minuto"
#: ../src/shell-global.c:829
#: ../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:832
#: ../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:835
#: ../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:838
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -164,6 +254,9 @@ msgstr "Buscar"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "PLACES"
#~ msgstr "LUGARES"
#~ msgid "Frequent"
#~ msgstr "Frecuentes"
@ -190,27 +283,6 @@ msgstr "%1$s: %2$s"
#~ msgid "Can't logout: %s"
#~ msgstr "No se puede salir de la sesión: %s"
#~ msgid "Account Information..."
#~ msgstr "Información de la cuenta…"
#~ msgid "Sidebar"
#~ msgstr "Barra lateral"
#~ msgid "System Preferences..."
#~ msgstr "Preferencias del sistema…"
#~ msgid "Lock Screen"
#~ msgstr "Bloquear la pantalla"
#~ msgid "Switch User"
#~ msgstr "Cambiar de usuario"
#~ msgid "Log Out..."
#~ msgstr "Salir…"
#~ msgid "Shut Down..."
#~ msgstr "Apagar…"
#~ msgid "Browse"
#~ msgstr "Examine"

265
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-09-28 13:41+0200\n"
"PO-Revision-Date: 2009-09-28 13:42+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"
@ -25,153 +25,222 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Ablakkezelés és alkalmazásindítás"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Tevékenységek"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "ALKALMAZÁSOK"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a., %k.%M"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "BEÁLLÍTÁSOK"
#: ../js/ui/dash.js:283
#: ../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:400
msgid "More"
msgstr "Több"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Keresés…"
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(összes megjelenítése)"
#. **** Applications ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "ALKALMAZÁSOK"
#: ../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:783
msgid "PLACES"
msgstr "HELYEK"
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "HELYEK ÉS ESZKÖZÖK"
#. **** Documents ****
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "LEGUTÓBBI DOKUMENTUMOK"
#: ../js/ui/dash.js:907 ../js/ui/docDisplay.js:488
msgid "RECENT ITEMS"
msgstr "LEGUTÓBBI ELEMEK"
#. **** Search Results ****
#: ../js/ui/dash.js:815 ../js/ui/dash.js:958
msgid "SEARCH RESULTS"
msgstr "TALÁLATOK"
#: ../js/ui/lookingGlass.js:356
msgid "No extensions installed"
msgstr "Nincsenek kiterjesztések telepítve"
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "BEÁLLÍTÁSOK"
#: ../js/ui/lookingGlass.js:393
msgid "Enabled"
msgstr "Engedélyezve"
#: ../js/ui/runDialog.js:94
#: ../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:"
#: ../src/shell-global.c:799
#: ../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:802
#: ../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:805
#: ../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:808
#: ../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:811
#: ../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-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…"
#: ../src/shell-uri-util.c:87
#: ../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"
@ -180,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"

View File

@ -1,14 +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: \n"
"POT-Creation-Date: 2009-12-28 21:58+0100\n"
"PO-Revision-Date: 2009-12-28 21:59+0100\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,7 +25,7 @@ msgid "Window management and application launching"
msgstr "Gestione finestre e avvio applicazioni"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:858
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "Applicazioni"
@ -33,51 +33,55 @@ msgstr "Applicazioni"
msgid "PREFERENCES"
msgstr "Preferenze"
#: ../js/ui/appDisplay.js:707 ../js/ui/appIcon.js:425
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Nuova finestra"
#: ../js/ui/appDisplay.js:711 ../js/ui/appIcon.js:429
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Rimuovi dai preferiti"
#: ../js/ui/appDisplay.js:712 ../js/ui/appIcon.js:430
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Aggiungi ai preferiti"
#: ../js/ui/appDisplay.js:1064
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "Trascinare qui per aggiungere ai preferiti"
#: ../js/ui/dash.js:240
#: ../js/ui/dash.js:241
msgid "Find..."
msgstr "Trova..."
#: ../js/ui/dash.js:437
#: ../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:878 ../js/ui/placeDisplay.js:519
msgid "PLACES"
msgstr "Risorse"
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "Risorse e dispositivi"
#. **** Documents ****
#: ../js/ui/dash.js:885
msgid "RECENT DOCUMENTS"
msgstr "Documenti recenti"
#: ../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:227
#: ../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:440
#: ../js/ui/panel.js:557
msgid "%a %l:%M %p"
msgstr "%a %k.%M"
@ -85,11 +89,11 @@ msgstr "%a %k.%M"
msgid "Connect to..."
msgstr "Connetti a..."
#: ../js/ui/runDialog.js:235
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Inserire un comando:"
#: ../js/ui/runDialog.js:351
#: ../js/ui/runDialog.js:361
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Esecuzione di «%s» non riuscita:"
@ -107,32 +111,32 @@ msgstr "Applicazioni"
msgid "Recent Documents"
msgstr "Documenti recenti"
#: ../src/shell-global.c:890
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Meno di un minuto fa"
#: ../src/shell-global.c:893
#: ../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:896
#: ../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:899
#: ../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:902
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -164,6 +168,9 @@ msgstr "Cerca"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "PLACES"
#~ msgstr "Risorse"
#~ msgid "Frequent"
#~ msgstr "Frequente"

183
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-10-03 10:47+0200\n"
"PO-Revision-Date: 2009-10-03 10:48+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,151 +24,140 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "Vindushåndtering og oppstart av programmer"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Aktiviteter"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#. Translators: This is a time format.
#: ../js/ui/panel.js:461
msgid "%a %l:%M %p"
msgstr "%a %l:%M"
#: ../js/ui/appDisplay.js:276
msgid "PREFERENCES"
msgstr "BRUKERVALG"
#: ../js/ui/dash.js:283
#: ../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:400
msgid "More"
msgstr "Mer"
#: ../js/ui/dash.js:508
msgid "Searching..."
msgstr "Søker..."
#: ../js/ui/dash.js:543
msgid "(see all)"
msgstr "(se alle)"
#. **** Applications ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:825
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#: ../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:783
msgid "PLACES"
msgstr "STEDER"
#: ../js/ui/dash.js:900 ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "STEDER & ENHETER"
#. **** Documents ****
#: ../js/ui/dash.js:790 ../js/ui/dash.js:835
msgid "RECENT DOCUMENTS"
msgstr "SISTE DOKUMENTER"
#: ../js/ui/dash.js:907
msgid "RECENT ITEMS"
msgstr "SISTE OPPFØRINGER"
#. **** Search Results ****
#: ../js/ui/dash.js:815 ../js/ui/dash.js:955
msgid "SEARCH RESULTS"
msgstr "SØKERESULTATER"
#. 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"
#: ../js/ui/dash.js:830
msgid "PREFERENCES"
msgstr "BRUKERVALG"
#. Translators: This is the time format used in 24-hour mode.
#: ../js/ui/panel.js:560
msgid "%a %R"
msgstr "%a %R"
#: ../js/ui/runDialog.js:96
#. 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:812
#: ../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:815
#: ../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:818
#: ../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:821
#: ../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:824
#: ../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"
@ -177,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"

165
po/sl.po
View File

@ -8,8 +8,8 @@ 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-05 01:21+0000\n"
"PO-Revision-Date: 2010-01-05 09:09+0100\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"
@ -23,7 +23,7 @@ msgstr ""
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Gnome lupina"
msgstr "Gnome Lupina"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
@ -31,7 +31,7 @@ msgstr "Upravljanje oken in zaganjanje programov"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252
#: ../js/ui/dash.js:858
#: ../js/ui/dash.js:880
msgid "APPLICATIONS"
msgstr "Programi"
@ -39,54 +39,103 @@ msgstr "Programi"
msgid "PREFERENCES"
msgstr "Možnosti"
#: ../js/ui/appDisplay.js:707
#: ../js/ui/appIcon.js:425
#: ../js/ui/appDisplay.js:649
msgid "New Window"
msgstr "Novo okno"
#: ../js/ui/appDisplay.js:711
#: ../js/ui/appIcon.js:429
#: ../js/ui/appDisplay.js:653
msgid "Remove from Favorites"
msgstr "Odstrani iz priljubljenih"
#: ../js/ui/appDisplay.js:712
#: ../js/ui/appIcon.js:430
#: ../js/ui/appDisplay.js:654
msgid "Add to Favorites"
msgstr "Dodaj med priljubljene"
#: ../js/ui/appDisplay.js:1064
#: ../js/ui/appDisplay.js:1006
msgid "Drag here to add favorites"
msgstr "S potegom na to mesto se izbor doda med priljubljene"
#: ../js/ui/dash.js:240
#: ../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:437
#: ../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:878
#: ../js/ui/placeDisplay.js:519
msgid "PLACES"
msgstr "Mesta"
#: ../js/ui/dash.js:900
#: ../js/ui/placeDisplay.js:529
msgid "PLACES & DEVICES"
msgstr "Mesta in naprave"
#. **** Documents ****
#: ../js/ui/dash.js:885
msgid "RECENT DOCUMENTS"
msgstr "Nedavni dokumenti"
#: ../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:227
#: ../js/ui/panel.js:336
msgid "Activities"
msgstr "Dejavnosti"
#. Translators: This is a time format.
#: ../js/ui/panel.js:440
#. 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"
@ -94,15 +143,55 @@ msgstr "%a, %H:%M"
msgid "Connect to..."
msgstr "Povezava z ..."
#: ../js/ui/runDialog.js:235
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "Vnos ukaza:"
#: ../js/ui/runDialog.js:351
#: ../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"
@ -116,11 +205,11 @@ msgstr "Programi"
msgid "Recent Documents"
msgstr "Nedavni dokumenti"
#: ../src/shell-global.c:890
#: ../src/shell-global.c:976
msgid "Less than a minute ago"
msgstr "Pred manj kot eno minuto"
#: ../src/shell-global.c:893
#: ../src/shell-global.c:980
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -129,7 +218,7 @@ msgstr[1] "Pred %d minuto"
msgstr[2] "Pred %d minutama"
msgstr[3] "Pred %d minutami"
#: ../src/shell-global.c:896
#: ../src/shell-global.c:985
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -138,7 +227,7 @@ msgstr[1] "Pred %d uro"
msgstr[2] "Pred %d urama"
msgstr[3] "Pred %d urami"
#: ../src/shell-global.c:899
#: ../src/shell-global.c:990
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -147,7 +236,7 @@ msgstr[1] "Pred %d dnevom"
msgstr[2] "Pred %d dnevoma"
msgstr[3] "Pred %d dnevi"
#: ../src/shell-global.c:902
#: ../src/shell-global.c:995
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -180,6 +269,8 @@ msgstr "Poišči"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "PLACES"
#~ msgstr "Mesta"
#~ msgid "SEARCH RESULTS"
#~ msgstr "Rezultati iskanja"
#~ msgid "Unknown"
@ -191,20 +282,6 @@ msgstr "%1$s: %2$s"
#~ "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 "Account Information..."
#~ msgstr "Podrobnosti računa ..."
#~ msgid "Sidebar"
#~ msgstr "Stranska vrstica"
#~ msgid "System Preferences..."
#~ msgstr "Sistemske možnosti ..."
#~ msgid "Lock Screen"
#~ msgstr "Zakleni zaslon"
#~ msgid "Switch User"
#~ msgstr "Preklop uporabnika"
#~ msgid "Log Out..."
#~ msgstr "Odjava ..."
#~ msgid "Shut Down..."
#~ msgstr "Izklopi ..."
#~ msgid "Frequent"
#~ msgstr "Pogosto"
#~ msgid "More"

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"

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"

View File

@ -2,19 +2,19 @@
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Ray Wang <raywang@gnome.org>, 2009.
#
# jiero <lililjlj@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: 2009-08-29 19:32+0000\n"
"PO-Revision-Date: 2009-08-30 00:08+0800\n"
"Last-Translator: Ray Wang <raywang@gnome.org>\n"
"Language-Team: Chinese (Simplified) <i18n-zh@googlegroups.com>\n"
"POT-Creation-Date: 2010-01-15 17:17+0000\n"
"PO-Revision-Date: 2010-01-17 15:30+0800\n"
"Last-Translator: jiero <lililjlj@gmail.com>\n"
"Language-Team: Simplified Chinese <i10n>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Content-Transfer-Encoding: UTF-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
@ -25,143 +25,133 @@ msgstr "GNOME Shell"
msgid "Window management and application launching"
msgstr "窗口管理和应用程序启动"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "活动"
#. **** Applications ****
#: ../js/ui/appDisplay.js:252 ../js/ui/dash.js:865
msgid "APPLICATIONS"
msgstr "应用程序"
#. 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 "首选项"
#: ../js/ui/dash.js:256
#: ../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:374
msgid "Browse"
msgstr "浏览"
#: ../js/ui/dash.js:493
msgid "Searching..."
msgstr "搜索..."
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(查看所有)"
#. **** Applications ****
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
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:653
msgid "PLACES"
msgstr "位置"
#: ../js/ui/dash.js:885 ../js/ui/placeDisplay.js:519
msgid "PLACES & DEVICES"
msgstr ""
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
#: ../js/ui/dash.js:892
#, fuzzy
#| msgid "RECENT DOCUMENTS"
msgid "RECENT ITEMS"
msgstr "最近的文档"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
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 "活动"
#: ../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 "连接到..."
#: ../js/ui/runDialog.js:245
msgid "Please enter a command:"
msgstr "请输入一个命令:"
#: ../src/shell-global.c:840
#: ../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:843
#: ../src/shell-global.c:894
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d 分钟前"
#: ../src/shell-global.c:846
#: ../src/shell-global.c:899
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d 小时前"
#: ../src/shell-global.c:849
#: ../src/shell-global.c:904
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d 天前"
#: ../src/shell-global.c:852
#: ../src/shell-global.c:909
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%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
#: ../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:102
#: ../src/shell-uri-util.c:104
msgid "File System"
msgstr "文件系统"
#: ../src/shell-uri-util.c:248
#: ../src/shell-uri-util.c:250
msgid "Search"
msgstr "搜索"
@ -170,7 +160,52 @@ msgstr "搜索"
#. * 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 "位置"
#~ msgid "Browse"
#~ msgstr "浏览"
#~ msgid "(see all)"
#~ 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 "关机..."

View File

@ -83,21 +83,29 @@ st_source_h = \
st/st-scrollable.h \
st/st-scroll-bar.h \
st/st-scroll-view.h \
st/st-shadow-texture.h \
st/st-shadow.h \
st/st-subtexture.h \
st/st-table.h \
st/st-table-child.h \
st/st-table-private.h \
st/st-texture-cache.h \
st/st-texture-frame.h \
st/st-theme.h \
st/st-theme-context.h \
st/st-theme-node.h \
st/st-theme-private.h \
st/st-tooltip.h \
st/st-types.h \
st/st-widget.h \
$(NULL)
st.h: Makefile
$(AM_V_GEN) (echo "#define ST_H_INSIDE 1"; \
for name in $(st_source_h); do \
echo "#include <"$$name">"; \
done; echo "#undef ST_H_INSIDE") > st.h.tmp && mv st.h.tmp st.h
BUILT_SOURCES += st.h
st_source_private_h = \
st/st-private.h \
st/st-table-private.h \
@ -122,6 +130,8 @@ st_source_c = \
st/st-scrollable.c \
st/st-scroll-bar.c \
st/st-scroll-view.c \
st/st-shadow-texture.c \
st/st-shadow.c \
st/st-subtexture.c \
st/st-table.c \
st/st-table-child.c \
@ -139,8 +149,10 @@ noinst_LTLIBRARIES += libst-1.0.la
libst_1_0_la_LIBADD = $(ST_LIBS)
libst_1_0_la_SOURCES = \
$(st_source_c) \
$(st_source_private_h) \
$(st_source_private_c) \
$(st_source_h) \
st.h \
$(st_built_sources) \
$(NULL)
libst_1_0_la_CPPFLAGS = $(st_cflags)

View File

@ -32,7 +32,6 @@ gnome_shell_cflags = \
$(MUTTER_PLUGIN_CFLAGS) \
$(LIBGNOMEUI_CFLAGS) \
-I$(srcdir)/tray \
-DGETTEXT_PACKAGE=\"gnome-shell\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
@ -85,6 +84,8 @@ libgnome_shell_la_SOURCES = \
shell-global.c \
shell-global.h \
shell-global-private.h \
shell-slicer.c \
shell-slicer.h \
shell-stack.c \
shell-stack.h \
shell-tray-manager.c \
@ -169,7 +170,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.l
--nsversion=0.1 \
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
--include=Clutter-1.0 \
--include=Meta-2.28 \
--include=Meta-2.29 \
--libtool="$(LIBTOOL)" \
--add-include-path=$(builddir) \
--include=Big-1.0 \
@ -178,6 +179,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir St-1.0.gir libgnome-shell.l
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \
$(libgnome_shell_la_CPPFLAGS) \
-I $(srcdir) \
-o $@
CLEANFILES += Shell-0.1.gir
@ -216,6 +218,7 @@ St-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libst-1.0.la Makefile
--namespace=St \
--nsversion=1.0 \
--include=Clutter-1.0 \
--include=Gtk-2.0 \
--add-include-path=$(builddir) \
--libtool="$(LIBTOOL)" \
--program=mutter \

5
src/gnome-shell.in Normal file → Executable file
View File

@ -357,8 +357,9 @@ try:
shell = None
if options.xephyr:
xephyr = start_xephyr()
# This makes us not grab the org.gnome.Panel name
os.environ['GNOME_SHELL_NO_REPLACE_PANEL'] = '1'
# This makes us not grab the org.gnome.Panel or
# org.freedesktop.Notifications D-Bus names
os.environ['GNOME_SHELL_NO_REPLACE'] = '1'
shell = start_shell()
else:
xephyr = None

View File

@ -83,6 +83,7 @@ struct _ShellAppInfo {
char *casefolded_name;
char *name_collation_key;
char *casefolded_description;
char *casefolded_exec;
GMenuTreeItem *entry;
@ -483,6 +484,32 @@ shell_app_system_get_app (ShellAppSystem *self,
return app;
}
/**
* shell_app_system_get_app_for_window:
* @self: A #ShellAppSystem
* @window: A #MetaWindow
*
* Find or create a #ShellApp for window
*
* Return value: (transfer full): The #ShellApp for window, or %NULL if none
*/
ShellApp *
shell_app_system_get_app_for_window (ShellAppSystem *self,
MetaWindow *window)
{
char *id = g_strdup_printf ("window:%p", window);
ShellApp *app = g_hash_table_lookup (self->priv->app_id_to_app, id);
if (app)
g_object_ref (G_OBJECT (app));
else
app = _shell_app_new_for_window (window);
g_free (id);
return app;
}
/* ShellAppSystem ensures we have a unique instance of
* apps per id.
*/
@ -612,11 +639,29 @@ normalize_and_casefold (const char *str)
return result;
}
static char *
trim_exec_line (const char *str)
{
const char *start, *end, *pos;
end = strchr (str, ' ');
if (end == NULL)
end = str + strlen (str);
start = str;
while ((pos = strchr (start, '/')) && pos < end)
start = ++pos;
return g_strndup (start, end - start);
}
static void
shell_app_info_init_search_data (ShellAppInfo *info)
{
const char *name;
const char *exec;
const char *comment;
char *normalized_exec;
g_assert (info->type == SHELL_APP_INFO_TYPE_ENTRY);
@ -625,6 +670,11 @@ shell_app_info_init_search_data (ShellAppInfo *info)
comment = gmenu_tree_entry_get_comment ((GMenuTreeEntry*)info->entry);
info->casefolded_description = normalize_and_casefold (comment);
exec = gmenu_tree_entry_get_exec ((GMenuTreeEntry*)info->entry);
normalized_exec = normalize_and_casefold (exec);
info->casefolded_exec = trim_exec_line (normalized_exec);
g_free (normalized_exec);
}
static ShellAppInfoSearchMatch
@ -654,6 +704,17 @@ shell_app_info_match_terms (ShellAppInfo *info,
else if (p != NULL)
match = MATCH_SUBSTRING;
p = strstr (info->casefolded_exec, term);
if (p == info->casefolded_exec)
{
if (match != MATCH_NONE)
return MATCH_MULTIPLE;
else
match = MATCH_PREFIX;
}
else if (p != NULL)
match = MATCH_SUBSTRING;
if (!info->casefolded_description)
continue;
p = strstr (info->casefolded_description, term);
@ -770,7 +831,7 @@ shell_app_system_initial_search_internal (ShellAppSystem *self,
/**
* shell_app_system_initial_search:
* @self: A #ShellAppSystem
* @prefs: %TRUE iff we should search preferences instead of apps
* @prefs: %TRUE if we should search preferences instead of apps
* @terms: (element-type utf8): List of terms, logical OR
*
* Search through applications for the given search terms. Note that returned
@ -790,7 +851,7 @@ shell_app_system_initial_search (ShellAppSystem *self,
/**
* shell_app_system_subsearch:
* @self: A #ShellAppSystem
* @prefs: %TRUE iff we should search preferences instead of apps
* @prefs: %TRUE if we should search preferences instead of apps
* @previous_results: (element-type utf8): List of previous results
* @terms: (element-type utf8): List of terms, logical OR
*

View File

@ -66,6 +66,7 @@ gboolean shell_app_info_launch (ShellAppInfo *info,
ShellAppInfo *shell_app_system_load_from_desktop_file (ShellAppSystem *system, const char *filename, GError **error);
ShellApp *shell_app_system_get_app (ShellAppSystem *system, const char *id);
ShellApp *shell_app_system_get_app_for_window (ShellAppSystem *self, MetaWindow *window);
void _shell_app_system_register_app (ShellAppSystem *self, ShellApp *app);

View File

@ -517,22 +517,6 @@ ensure_queued_save (ShellAppUsage *self)
self->save_id = g_timeout_add_seconds (SAVE_APPS_TIMEOUT_SECONDS, idle_save_application_usage, self);
}
/* Used to sort highest scores at the top */
static gint
usage_sort_apps (gconstpointer data1,
gconstpointer data2)
{
const UsageData *u1 = data1;
const UsageData *u2 = data2;
if (u1->score > u2->score)
return -1;
else if (u1->score == u2->score)
return 0;
else
return 1;
}
/* Clean up apps we see rarely.
* The logic behind this is that if an app was seen less than SCORE_MIN times
* and not seen for a week, it can probably be forgotten about.
@ -800,7 +784,7 @@ shell_app_usage_start_element_handler (GMarkupParseContext *context,
guint count = strtoul (*value, NULL, 10);
if (count > 0)
data->self->previously_running = g_slist_prepend (data->self->previously_running,
usage);
g_strdup (appid));
}
else if (strcmp (*attribute, "score") == 0)
{
@ -897,7 +881,6 @@ out:
g_object_unref (input);
idle_clean_usage (self);
self->previously_running = g_slist_sort (self->previously_running, usage_sort_apps);
if (error)
{

View File

@ -52,6 +52,70 @@ shell_draw_clock (ClutterCairoTexture *texture,
cairo_destroy (cr);
}
/**
* shell_fade_app_icon:
* @source: Source #ClutterTexture
*
* Create a new texture by modifying the alpha channel of the
* source texture, adding a horizontal gradient fade.
*
* Returns: (transfer none): A new #ClutterTexture
*/
ClutterTexture *
shell_fade_app_icon (ClutterTexture *source)
{
CoglHandle texture;
guchar *pixels;
gint width, height, rowstride;
gint fade_start;
gint fade_range;
guint i, j;
ClutterTexture *result;
texture = clutter_texture_get_cogl_texture (source);
if (texture == COGL_INVALID_HANDLE)
return NULL;
width = cogl_texture_get_width (texture);
height = cogl_texture_get_height (texture);
rowstride = (width * 4 + 3) & ~3;
pixels = g_malloc0 (rowstride * height);
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_RGBA_8888_PRE,
rowstride, pixels);
fade_start = width / 2;
fade_range = width - fade_start;
for (i = fade_start; i < width; i++)
{
for (j = 0; j < height; j++)
{
guchar *pixel = &pixels[j * rowstride + i * 4];
float fade = 1.0 - ((float) i - fade_start) / fade_range;
pixel[0] = 0.5 + pixel[0] * fade;
pixel[1] = 0.5 + pixel[1] * fade;
pixel[2] = 0.5 + pixel[2] * fade;
pixel[3] = 0.5 + pixel[3] * fade;
}
}
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
rowstride,
pixels);
g_free (pixels);
result = (ClutterTexture*)clutter_texture_new ();
clutter_texture_set_cogl_texture (result, texture);
cogl_texture_unref (texture);
return result;
}
void
shell_draw_box_pointer (ClutterCairoTexture *texture,
ShellPointerDirection direction,

View File

@ -23,6 +23,8 @@ void shell_draw_clock (ClutterCairoTexture *texture,
int hour,
int minute);
ClutterTexture * shell_fade_app_icon (ClutterTexture *source);
guint shell_add_hook_paint_red_border (ClutterActor *actor);
G_END_DECLS

View File

@ -138,14 +138,42 @@ shell_embedded_window_check_resize (GtkContainer *container)
clutter_actor_queue_relayout (CLUTTER_ACTOR (window->priv->actor));
}
static GObject *
shell_embedded_window_constructor (GType gtype,
guint n_properties,
GObjectConstructParam *properties)
{
GObject *object;
GObjectClass *parent_class;
parent_class = G_OBJECT_CLASS (shell_embedded_window_parent_class);
object = parent_class->constructor (gtype, n_properties, properties);
/* Setting the resize mode to immediate means that calling queue_resize()
* on a widget within the window will immmediately call check_resize()
* to be called, instead of having it queued to an idle. From our perspective,
* this is ideal since we just are going to queue a resize to Clutter's
* idle resize anyways.
*/
g_object_set (object,
"resize-mode", GTK_RESIZE_IMMEDIATE,
"type", GTK_WINDOW_POPUP,
NULL);
return object;
}
static void
shell_embedded_window_class_init (ShellEmbeddedWindowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
g_type_class_add_private (klass, sizeof (ShellEmbeddedWindowPrivate));
object_class->constructor = shell_embedded_window_constructor;
widget_class->show = shell_embedded_window_show;
widget_class->hide = shell_embedded_window_hide;
widget_class->realize = shell_embedded_window_realize;
@ -159,17 +187,6 @@ shell_embedded_window_init (ShellEmbeddedWindow *window)
{
window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, SHELL_TYPE_EMBEDDED_WINDOW,
ShellEmbeddedWindowPrivate);
/* Setting the resize mode to immediate means that calling queue_resize()
* on a widget within the window will immmediately call check_resize()
* to be called, instead of having it queued to an idle. From our perspective,
* this is ideal since we just are going to queue a resize to Clutter's
* idle resize anyways.
*/
g_object_set (G_OBJECT (window),
"resize-mode", GTK_RESIZE_IMMEDIATE,
"type", GTK_WINDOW_POPUP,
NULL);
}
/*

View File

@ -102,7 +102,13 @@ function runTestFixedBox() {
#include <gtk/gtk.h>
#include <girepository.h>
G_DEFINE_TYPE(ShellGenericContainer, shell_generic_container, CLUTTER_TYPE_GROUP);
static void shell_generic_container_iface_init (ClutterContainerIface *iface);
G_DEFINE_TYPE_WITH_CODE(ShellGenericContainer,
shell_generic_container,
CLUTTER_TYPE_GROUP,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
shell_generic_container_iface_init));
struct _ShellGenericContainerPrivate {
GHashTable *skip_paint;
@ -119,6 +125,7 @@ enum
static guint shell_generic_container_signals [LAST_SIGNAL] = { 0 };
static ClutterContainerIface *parent_container_iface;
static gpointer
shell_generic_container_allocation_ref (ShellGenericContainerAllocation *alloc)
@ -227,15 +234,6 @@ shell_generic_container_pick (ClutterActor *actor,
g_list_free (children);
}
static void
on_skip_paint_weakref (gpointer user_data,
GObject *location)
{
ShellGenericContainer *self = SHELL_GENERIC_CONTAINER (user_data);
g_hash_table_remove (self->priv->skip_paint, location);
}
/**
* shell_generic_container_set_skip_paint:
* @container: A #ShellGenericContainer
@ -257,29 +255,19 @@ shell_generic_container_set_skip_paint (ShellGenericContainer *self,
return;
if (!skip)
{
g_object_weak_unref ((GObject*) child, on_skip_paint_weakref, self);
g_hash_table_remove (self->priv->skip_paint, child);
}
g_hash_table_remove (self->priv->skip_paint, child);
else
{
g_object_weak_ref ((GObject*) child, on_skip_paint_weakref, self);
g_hash_table_insert (self->priv->skip_paint, child, child);
}
g_hash_table_insert (self->priv->skip_paint, child, child);
}
static void
shell_generic_container_dispose (GObject *object)
shell_generic_container_finalize (GObject *object)
{
ShellGenericContainer *self = (ShellGenericContainer*) object;
if (self->priv->skip_paint != NULL)
{
g_hash_table_destroy (self->priv->skip_paint);
self->priv->skip_paint = NULL;
}
g_hash_table_destroy (self->priv->skip_paint);
G_OBJECT_CLASS (shell_generic_container_parent_class)->dispose (object);
G_OBJECT_CLASS (shell_generic_container_parent_class)->finalize (object);
}
static void
@ -288,7 +276,7 @@ shell_generic_container_class_init (ShellGenericContainerClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->dispose = shell_generic_container_dispose;
gobject_class->finalize = shell_generic_container_finalize;
actor_class->get_preferred_width = shell_generic_container_get_preferred_width;
actor_class->get_preferred_height = shell_generic_container_get_preferred_height;
@ -326,12 +314,31 @@ shell_generic_container_class_init (ShellGenericContainerClass *klass)
g_type_class_add_private (gobject_class, sizeof (ShellGenericContainerPrivate));
}
static void
shell_generic_container_remove (ClutterContainer *container,
ClutterActor *actor)
{
ShellGenericContainer *self = SHELL_GENERIC_CONTAINER (container);
g_hash_table_remove (self->priv->skip_paint, actor);
parent_container_iface->remove (container, actor);
}
static void
shell_generic_container_iface_init (ClutterContainerIface *iface)
{
parent_container_iface = g_type_interface_peek_parent (iface);
iface->remove = shell_generic_container_remove;
}
static void
shell_generic_container_init (ShellGenericContainer *area)
{
area->priv = G_TYPE_INSTANCE_GET_PRIVATE (area, SHELL_TYPE_GENERIC_CONTAINER,
ShellGenericContainerPrivate);
area->priv->skip_paint = g_hash_table_new_full (NULL, NULL, (GDestroyNotify)g_object_unref, NULL);
area->priv->skip_paint = g_hash_table_new (NULL, NULL);
}
GType shell_generic_container_allocation_get_type (void)

View File

@ -6,6 +6,7 @@
#include "shell-wm.h"
#include "display.h"
#include "util.h"
#include <clutter/glx/clutter-glx.h>
#include <clutter/x11/clutter-x11.h>
#include <gdk/gdkx.h>
@ -17,7 +18,6 @@
#include <unistd.h>
#include <dbus/dbus-glib.h>
#include <gio/gio.h>
#include <glib/gi18n-lib.h>
#include <math.h>
#include <X11/extensions/Xfixes.h>
#include <gjs/gjs.h>
@ -28,6 +28,7 @@
#define SHELL_DBUS_SERVICE "org.gnome.Shell"
static void grab_notify (GtkWidget *widget, gboolean is_grab, gpointer user_data);
static void update_root_window_pixmap (ShellGlobal *global);
struct _ShellGlobal {
GObject parent;
@ -53,6 +54,8 @@ struct _ShellGlobal {
/* Displays the root window; see shell_global_create_root_pixmap_actor() */
ClutterActor *root_pixmap;
gint last_change_screen_width, last_change_screen_height;
};
enum {
@ -73,8 +76,7 @@ enum {
/* Signals */
enum
{
PANEL_RUN_DIALOG,
PANEL_MAIN_MENU,
SCREEN_SIZE_CHANGED,
LAST_SIGNAL
};
@ -189,6 +191,9 @@ shell_global_init (ShellGlobal *global)
global->root_pixmap = NULL;
global->input_mode = SHELL_STAGE_INPUT_MODE_NORMAL;
global->last_change_screen_width = 0;
global->last_change_screen_height = 0;
}
static void
@ -199,23 +204,14 @@ shell_global_class_init (ShellGlobalClass *klass)
gobject_class->get_property = shell_global_get_property;
gobject_class->set_property = shell_global_set_property;
shell_global_signals[PANEL_RUN_DIALOG] =
g_signal_new ("panel-run-dialog",
shell_global_signals[SCREEN_SIZE_CHANGED] =
g_signal_new ("screen-size-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ShellGlobalClass, panel_run_dialog),
G_STRUCT_OFFSET (ShellGlobalClass, screen_size_changed),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1, G_TYPE_INT);
shell_global_signals[PANEL_MAIN_MENU] =
g_signal_new ("panel-main-menu",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (ShellGlobalClass, panel_main_menu),
NULL, NULL,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE, 1, G_TYPE_INT);
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_object_class_install_property (gobject_class,
PROP_OVERLAY_GROUP,
@ -441,6 +437,73 @@ shell_global_get_windows (ShellGlobal *global)
return mutter_plugin_get_windows (global->plugin);
}
static gboolean
on_screen_size_changed_cb (gpointer data)
{
ShellGlobal *global = SHELL_GLOBAL (data);
int width, height;
mutter_plugin_query_screen_size (global->plugin, &width, &height);
if (global->last_change_screen_width != width || global->last_change_screen_height != height)
{
g_signal_emit (G_OBJECT (global), shell_global_signals[SCREEN_SIZE_CHANGED], 0);
global->last_change_screen_width = width;
global->last_change_screen_height = height;
/* update size of background actor to fix tiled backgrounds */
clutter_actor_set_size (CLUTTER_ACTOR (global->root_pixmap),
width, height);
}
return FALSE;
}
static void
global_stage_notify_width (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
ShellGlobal *global = SHELL_GLOBAL (data);
g_object_notify (G_OBJECT (global), "screen-width");
meta_later_add (META_LATER_BEFORE_REDRAW,
on_screen_size_changed_cb,
global,
NULL);
}
static void
global_stage_notify_height (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
ShellGlobal *global = SHELL_GLOBAL (data);
g_object_notify (G_OBJECT (global), "screen-height");
meta_later_add (META_LATER_BEFORE_REDRAW,
on_screen_size_changed_cb,
global,
NULL);
}
static void
global_plugin_notify_screen (GObject *gobject,
GParamSpec *pspec,
gpointer data)
{
ShellGlobal *global = SHELL_GLOBAL (data);
ClutterActor *stage = mutter_plugin_get_stage (MUTTER_PLUGIN (gobject));
g_signal_connect (stage, "notify::width",
G_CALLBACK (global_stage_notify_width), global);
g_signal_connect (stage, "notify::height",
G_CALLBACK (global_stage_notify_height), global);
}
void
_shell_global_set_plugin (ShellGlobal *global,
MutterPlugin *plugin)
@ -450,6 +513,14 @@ _shell_global_set_plugin (ShellGlobal *global,
global->plugin = plugin;
global->wm = shell_wm_new (plugin);
/* At this point screen is NULL, so we can't yet do signal connections
* to the width and height; we wait until the screen property is set
* to do that. Note that this is a one time thing - screen will never
* change once first set.
*/
g_signal_connect (plugin, "notify::screen",
G_CALLBACK (global_plugin_notify_screen), global);
}
void
@ -718,7 +789,22 @@ shell_global_reexec_self (ShellGlobal *global)
g_ptr_array_free (arr, TRUE);
}
void
/**
* shell_global_gc:
* @global: A #ShellGlobal
*
* Start a garbage collection process. For more information, see
* https://developer.mozilla.org/En/JS_GC
*/
void
shell_global_gc (ShellGlobal *global)
{
JSContext *context = gjs_context_get_context (global->js_context);
JS_GC (context);
}
void
shell_global_grab_dbus_service (ShellGlobal *global)
{
GError *error = NULL;
@ -751,7 +837,7 @@ shell_global_grab_dbus_service (ShellGlobal *global)
* unless a special environment variable is passed. The environment
* variable is used by the gnome-shell (no --replace) launcher in
* Xephyr */
if (!g_getenv ("GNOME_SHELL_NO_REPLACE_PANEL"))
if (!g_getenv ("GNOME_SHELL_NO_REPLACE"))
{
if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
"org.gnome.Panel", G_TYPE_UINT,
@ -835,22 +921,6 @@ root_window_filter (GdkXEvent *native, GdkEvent *event, gpointer data)
return GDK_FILTER_CONTINUE;
}
/* Workaround for a clutter bug where if ClutterGLXTexturePixmap
* is painted without the pixmap being set, a crash will occur inside
* Cogl.
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1644
*/
static void
root_pixmap_paint (ClutterActor *actor, gpointer data)
{
Pixmap pixmap;
g_object_get (G_OBJECT (actor), "pixmap", &pixmap, NULL);
if (!pixmap)
g_signal_stop_emission_by_name (actor, "paint");
}
/*
* Called when the root window pixmap actor is destroyed.
*/
@ -890,16 +960,24 @@ shell_global_format_time_relative_pretty (ShellGlobal *global,
*text = g_strdup (_("Less than a minute ago"));
*next_update = MINUTE - delta;
} else if (delta < HOUR) {
*text = g_strdup_printf (ngettext ("%d minute ago", "%d minutes ago", delta / MINUTE), delta / MINUTE);
*text = g_strdup_printf (dngettext (GETTEXT_PACKAGE,
"%d minute ago", "%d minutes ago",
delta / MINUTE), delta / MINUTE);
*next_update = MINUTE - (delta % MINUTE);
} else if (delta < DAY) {
*text = g_strdup_printf (ngettext ("%d hour ago", "%d hours ago", delta / HOUR), delta / HOUR);
*text = g_strdup_printf (dngettext (GETTEXT_PACKAGE,
"%d hour ago", "%d hours ago",
delta / HOUR), delta / HOUR);
*next_update = HOUR - (delta % HOUR);
} else if (delta < WEEK) {
*text = g_strdup_printf (ngettext ("%d day ago", "%d days ago", delta / DAY), delta / DAY);
*text = g_strdup_printf (dngettext (GETTEXT_PACKAGE,
"%d day ago", "%d days ago",
delta / DAY), delta / DAY);
*next_update = DAY - (delta % DAY);
} else {
*text = g_strdup_printf (ngettext ("%d week ago", "%d weeks ago", delta / WEEK), delta / WEEK);
*text = g_strdup_printf (dngettext (GETTEXT_PACKAGE,
"%d week ago", "%d weeks ago",
delta / WEEK), delta / WEEK);
*next_update = WEEK - (delta % WEEK);
}
}
@ -918,6 +996,7 @@ shell_global_create_root_pixmap_actor (ShellGlobal *global)
{
GdkWindow *window;
ClutterActor *stage;
ClutterColor stage_color;
/* The actor created is actually a ClutterClone of global->root_pixmap. */
@ -925,20 +1004,32 @@ shell_global_create_root_pixmap_actor (ShellGlobal *global)
{
global->root_pixmap = clutter_glx_texture_pixmap_new ();
clutter_texture_set_repeat (CLUTTER_TEXTURE (global->root_pixmap),
TRUE, TRUE);
/* The low and medium quality filters give nearest-neighbor resizing. */
clutter_texture_set_filter_quality (CLUTTER_TEXTURE (global->root_pixmap),
CLUTTER_TEXTURE_QUALITY_HIGH);
/* Initialize to the stage color, since that's what will be seen
* in the main view if there's no actual background window.
*/
stage = mutter_plugin_get_stage (global->plugin);
clutter_stage_get_color (CLUTTER_STAGE (stage), &stage_color);
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (global->root_pixmap),
/* ClutterColor has the same layout
* as one pixel of RGB(A) data.
*/
(const guchar *)&stage_color, FALSE,
/* w, h, rowstride, bpp, flags */
1, 1, 3, 3, 0, NULL);
/* We can only clone an actor within a stage, so we hide the source
* texture then add it to the stage */
clutter_actor_hide (global->root_pixmap);
stage = mutter_plugin_get_stage (global->plugin);
clutter_container_add_actor (CLUTTER_CONTAINER (stage),
global->root_pixmap);
g_signal_connect (global->root_pixmap, "paint",
G_CALLBACK (root_pixmap_paint), NULL);
/* This really should never happen; but just in case... */
g_signal_connect (global->root_pixmap, "destroy",
G_CALLBACK (root_pixmap_destroy), global);

View File

@ -26,10 +26,7 @@ struct _ShellGlobalClass
{
GObjectClass parent_class;
void (*panel_run_dialog) (ShellGlobal *global,
int timestamp);
void (*panel_main_menu) (ShellGlobal *global,
int timestamp);
void (*screen_size_changed) (ShellGlobal *global);
};
GType shell_global_get_type (void) G_GNUC_CONST;
@ -73,6 +70,8 @@ gboolean shell_global_display_is_grabbed (ShellGlobal *global);
void shell_global_reexec_self (ShellGlobal *global);
void shell_global_gc (ShellGlobal *global);
void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta, char **text, guint *update_time);
ClutterActor *shell_global_create_root_pixmap_actor (ShellGlobal *global);

View File

@ -61,6 +61,9 @@ struct _ShellRecorder {
gboolean only_paint; /* Used to temporarily suppress recording */
gboolean have_pack_invert; /* True when GL_MESA_pack_invert is available */
int framerate;
char *pipeline_description;
char *filename;
gboolean filename_has_count; /* %c used: handle pausing differently */
@ -91,6 +94,8 @@ struct _RecorderPipeline
static void recorder_set_stage (ShellRecorder *recorder,
ClutterStage *stage);
static void recorder_set_framerate (ShellRecorder *recorder,
int framerate);
static void recorder_set_pipeline (ShellRecorder *recorder,
const char *pipeline);
static void recorder_set_filename (ShellRecorder *recorder,
@ -102,6 +107,7 @@ static void recorder_pipeline_closed (RecorderPipeline *pipeline);
enum {
PROP_0,
PROP_STAGE,
PROP_FRAMERATE,
PROP_PIPELINE,
PROP_FILENAME
};
@ -115,7 +121,7 @@ G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
* as theora for a minimal size increase. This may be an artifact of the
* encoding process.
*/
#define FRAMES_PER_SECOND 15
#define DEFAULT_FRAMES_PER_SECOND 15
/* The time (in milliseconds) between querying the server for the cursor
* position.
@ -244,6 +250,7 @@ shell_recorder_init (ShellRecorder *recorder)
recorder->memory_target = get_memory_target();
recorder->state = RECORDER_STATE_CLOSED;
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
}
static void
@ -423,11 +430,14 @@ recorder_draw_cursor (ShellRecorder *recorder,
recorder->stage_height,
recorder->stage_width * 4);
/* The data we get from glReadPixels is "upside down", so transform
* our cairo drawing to match */
/* When not using GL_MESA_pack_invert the data we get from glReadPixels is "upside down",
* so transform our cairo drawing to match */
cr = cairo_create (surface);
cairo_translate(cr, 0, recorder->stage_height);
cairo_scale(cr, 1, -1);
if (!recorder->have_pack_invert)
{
cairo_translate(cr, 0, recorder->stage_height);
cairo_scale(cr, 1, -1);
}
cairo_set_source_surface (cr,
recorder->cursor_image,
@ -504,6 +514,27 @@ recorder_record_frame (ShellRecorder *recorder)
GST_BUFFER_TIMESTAMP(buffer) = get_wall_time() - recorder->start_time;
/* We could use cogl_read_pixels, but it only currently supports
* COGL_PIXEL_FORMAT_RGBA_8888, while we prefer the native framebuffer
* format. (COGL_PIXEL_FORMAT_ARGB_8888_PRE,
* COGL_PIXEL_FORMAT_BGRA_PRE, depending on endianess)
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1959
*/
/* Flush any primitives that Cogl has batched up */
cogl_flush ();
/* Set the parameters for how data is stored; these are the initial
* values but Cogl will have modified them for its own purposes */
glPixelStorei (GL_PACK_ALIGNMENT, 4);
glPixelStorei (GL_PACK_ROW_LENGTH, 0);
glPixelStorei (GL_PACK_SKIP_PIXELS, 0);
glPixelStorei (GL_PACK_SKIP_ROWS, 0);
if (recorder->have_pack_invert)
glPixelStorei (GL_PACK_INVERT_MESA, TRUE);
glReadBuffer (GL_BACK_LEFT);
glReadPixels (0, 0,
recorder->stage_width, recorder->stage_height,
@ -511,6 +542,9 @@ recorder_record_frame (ShellRecorder *recorder)
GL_UNSIGNED_INT_8_8_8_8_REV,
data);
if (recorder->have_pack_invert)
glPixelStorei (GL_PACK_INVERT_MESA, FALSE);
recorder_draw_cursor (recorder, buffer);
shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
@ -812,6 +846,7 @@ recorder_set_stage (ShellRecorder *recorder,
if (recorder->stage)
{
int error_base;
const char *gl_extensions;
recorder->stage = stage;
g_signal_connect (recorder->stage, "destroy",
@ -835,10 +870,29 @@ recorder_set_stage (ShellRecorder *recorder,
clutter_x11_get_stage_window (stage),
XFixesDisplayCursorNotifyMask);
clutter_stage_ensure_current (stage);
gl_extensions = (const char *)glGetString (GL_EXTENSIONS);
recorder->have_pack_invert = cogl_check_extension ("GL_MESA_pack_invert", gl_extensions);
recorder_get_initial_cursor_position (recorder);
}
}
static void
recorder_set_framerate (ShellRecorder *recorder,
int framerate)
{
if (framerate == recorder->framerate)
return;
if (recorder->current_pipeline)
shell_recorder_close (recorder);
recorder->framerate = framerate;
g_object_notify (G_OBJECT (recorder), "framerate");
}
static void
recorder_set_pipeline (ShellRecorder *recorder,
const char *pipeline)
@ -890,6 +944,9 @@ shell_recorder_set_property (GObject *object,
case PROP_STAGE:
recorder_set_stage (recorder, g_value_get_object (value));
break;
case PROP_FRAMERATE:
recorder_set_framerate (recorder, g_value_get_int (value));
break;
case PROP_PIPELINE:
recorder_set_pipeline (recorder, g_value_get_string (value));
break;
@ -915,6 +972,9 @@ shell_recorder_get_property (GObject *object,
case PROP_STAGE:
g_value_set_object (value, G_OBJECT (recorder->stage));
break;
case PROP_FRAMERATE:
g_value_set_int (value, recorder->framerate);
break;
case PROP_PIPELINE:
g_value_set_string (value, recorder->pipeline_description);
break;
@ -943,6 +1003,17 @@ shell_recorder_class_init (ShellRecorderClass *klass)
"Stage to record",
CLUTTER_TYPE_STAGE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_FRAMERATE,
g_param_spec_int ("framerate",
"Framerate",
"Framerate used for resulting video in frames-per-second",
0,
G_MAXINT,
DEFAULT_FRAMES_PER_SECOND,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_PIPELINE,
g_param_spec_string ("pipeline",
@ -984,7 +1055,7 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
"blue_mask", G_TYPE_INT, 0x0000ff,
#endif
"endianness", G_TYPE_INT, G_BIG_ENDIAN,
"framerate", GST_TYPE_FRACTION, FRAMES_PER_SECOND, 1,
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
"width", G_TYPE_INT, pipeline->recorder->stage_width,
"height", G_TYPE_INT, pipeline->recorder->stage_height,
NULL);
@ -1034,27 +1105,38 @@ recorder_pipeline_add_source (RecorderPipeline *pipeline)
gst_bin_add (GST_BIN (pipeline->pipeline), ffmpegcolorspace);
/* glReadPixels gives us an upside-down buffer, so we have to flip it back
* right-side up. We do this after the color space conversion in the theory
* that we might have a smaller buffer to flip; on the other hand flipping
* YUV 422 is more complicated than flipping RGB. Probably a toss-up.
* right-side up.
*
* When available MESA_pack_invert extension is used to avoid the
* flip entirely, since the data is actually stored in the frame buffer
* in the order that we expect.
*
* We use gst_parse_launch to avoid having to know the enum value for flip-vertical
*/
videoflip = gst_parse_launch_full ("videoflip method=vertical-flip", NULL,
GST_PARSE_FLAG_FATAL_ERRORS,
&error);
if (videoflip == NULL)
if (!pipeline->recorder->have_pack_invert)
{
g_warning("Can't create videoflip element: %s", error->message);
g_error_free (error);
goto out;
videoflip = gst_parse_launch_full ("videoflip method=vertical-flip", NULL,
GST_PARSE_FLAG_FATAL_ERRORS,
&error);
if (videoflip == NULL)
{
g_warning("Can't create videoflip element: %s", error->message);
g_error_free (error);
goto out;
}
gst_bin_add (GST_BIN (pipeline->pipeline), videoflip);
gst_element_link_many (pipeline->src, ffmpegcolorspace, videoflip, NULL);
src_pad = gst_element_get_static_pad (videoflip, "src");
}
else
{
gst_element_link_many (pipeline->src, ffmpegcolorspace, NULL);
src_pad = gst_element_get_static_pad (ffmpegcolorspace, "src");
}
gst_bin_add (GST_BIN (pipeline->pipeline), videoflip);
gst_element_link_many (pipeline->src, ffmpegcolorspace, videoflip,
NULL);
src_pad = gst_element_get_static_pad (videoflip, "src");
if (!src_pad)
{
g_warning("ShellRecorder: can't get src pad to link into pipeline");
@ -1478,6 +1560,24 @@ shell_recorder_new (ClutterStage *stage)
NULL);
}
/**
* shell_recorder_set_framerate:
* @recorder: the #ShellRecorder
* @framerate: Framerate used for resulting video in frames-per-second.
*
* Sets the number of frames per second we configure for the GStreamer pipeline.
*
* The default value is 15.
*/
void
shell_recorder_set_framerate (ShellRecorder *recorder,
int framerate)
{
g_return_if_fail (SHELL_IS_RECORDER (recorder));
recorder_set_framerate (recorder, framerate);
}
/**
* shell_recorder_set_filename:
* @recorder: the #ShellRecorder
@ -1513,8 +1613,8 @@ shell_recorder_set_filename (ShellRecorder *recorder,
/**
* shell_recorder_set_pipeline:
* @recorder: the #ShellRecorder
* @filename: the GStreamer pipeline used to encode recordings
* or %NULL for the defalt value.
* @pipeline: (allow-none): the GStreamer pipeline used to encode recordings
* or %NULL for the default value.
*
* Sets the GStreamer pipeline used to encode recordings.
* It follows the syntax used for gst-launch. The pipeline

View File

@ -30,6 +30,8 @@ GType shell_recorder_get_type (void) G_GNUC_CONST;
ShellRecorder *shell_recorder_new (ClutterStage *stage);
void shell_recorder_set_framerate (ShellRecorder *recorder,
int framerate);
void shell_recorder_set_filename (ShellRecorder *recorder,
const char *filename);
void shell_recorder_set_pipeline (ShellRecorder *recorder,

165
src/shell-slicer.c Normal file
View File

@ -0,0 +1,165 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* SECTION:shell-slicer
* @short_description: Display only part of another actor
*
* A #StBin that has 0 minimum size, and will clip its child
* in the middle.
*/
#include "config.h"
#include "shell-slicer.h"
G_DEFINE_TYPE (ShellSlicer,
shell_slicer,
ST_TYPE_BIN);
static void
shell_slicer_get_preferred_width (ClutterActor *self,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
ClutterActor *child = st_bin_get_child (ST_BIN (self));
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
st_theme_node_adjust_for_height (theme_node, &for_height);
if (min_width_p)
*min_width_p = 0;
if (child == NULL)
{
if (natural_width_p)
*natural_width_p = 0;
}
else
{
_st_actor_get_preferred_width (child, for_height, FALSE,
NULL,
natural_width_p);
}
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
}
static void
shell_slicer_get_preferred_height (ClutterActor *self,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
ClutterActor *child = st_bin_get_child (ST_BIN (self));
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
st_theme_node_adjust_for_width (theme_node, &for_width);
if (min_height_p)
*min_height_p = 0;
if (child == NULL)
{
if (natural_height_p)
*natural_height_p = 0;
}
else
{
_st_actor_get_preferred_height (child, for_width, FALSE,
NULL,
natural_height_p);
}
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
}
static void
shell_slicer_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
ClutterActor *child;
/* Chain up directly to ClutterActor to set actor->allocation. We explicitly skip our parent class
* StBin here because we want to override the allocate function. */
CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ()))->allocate (self, box, flags);
child = st_bin_get_child (ST_BIN (self));
if (child)
clutter_actor_allocate_preferred_size (child, flags);
}
static void
shell_slicer_paint_child (ShellSlicer *self)
{
ClutterActor *child;
ClutterActorBox self_box;
ClutterActorBox child_box;
float width, height, child_width, child_height;
StAlign x_align, y_align;
double x_align_factor, y_align_factor;
child = st_bin_get_child (ST_BIN (self));
if (!child)
return;
st_bin_get_alignment (ST_BIN (self), &x_align, &y_align);
_st_get_align_factors (ST_WIDGET (self), x_align, y_align,
&x_align_factor, &y_align_factor);
clutter_actor_get_allocation_box (CLUTTER_ACTOR (self), &self_box);
clutter_actor_get_allocation_box (child, &child_box);
width = self_box.x2 - self_box.x1;
height = self_box.y2 - self_box.y1;
child_width = child_box.x2 - child_box.x1;
child_height = child_box.y2 - child_box.y1;
cogl_push_matrix ();
cogl_clip_push (0, 0, width, height);
cogl_translate ((int)(0.5 + x_align_factor * (width - child_width)),
(int)(0.5 + y_align_factor * (height - child_height)),
0);
clutter_actor_paint (child);
cogl_clip_pop ();
cogl_pop_matrix ();
}
static void
shell_slicer_paint (ClutterActor *self)
{
/* StWidget paints CSS elements */
CLUTTER_ACTOR_CLASS (g_type_class_peek (st_widget_get_type ()))->paint (self);
shell_slicer_paint_child (SHELL_SLICER (self));
}
static void
shell_slicer_pick (ClutterActor *self,
const ClutterColor *pick_color)
{
shell_slicer_paint_child (SHELL_SLICER (self));
}
static void
shell_slicer_class_init (ShellSlicerClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->get_preferred_width = shell_slicer_get_preferred_width;
actor_class->get_preferred_height = shell_slicer_get_preferred_height;
actor_class->allocate = shell_slicer_allocate;
actor_class->paint = shell_slicer_paint;
actor_class->pick = shell_slicer_pick;
}
static void
shell_slicer_init (ShellSlicer *actor)
{
}

33
src/shell-slicer.h Normal file
View File

@ -0,0 +1,33 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __SHELL_SLICER_H__
#define __SHELL_SLICER_H__
#include "st.h"
#define SHELL_TYPE_SLICER (shell_slicer_get_type ())
#define SHELL_SLICER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_SLICER, ShellSlicer))
#define SHELL_SLICER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_SLICER, ShellSlicerClass))
#define SHELL_IS_SLICER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_SLICER))
#define SHELL_IS_SLICER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_SLICER))
#define SHELL_SLICER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_SLICER, ShellSlicerClass))
typedef struct _ShellSlicer ShellSlicer;
typedef struct _ShellSlicerClass ShellSlicerClass;
typedef struct _ShellSlicerPrivate ShellSlicerPrivate;
struct _ShellSlicer
{
StBin parent;
ShellSlicerPrivate *priv;
};
struct _ShellSlicerClass
{
StBinClass parent_class;
};
GType shell_slicer_get_type (void) G_GNUC_CONST;
#endif /* __SHELL_SLICER_H__ */

View File

@ -8,6 +8,7 @@
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnomeui/gnome-desktop-thumbnail.h>
#include <string.h>
#include <glib.h>
typedef struct
{
@ -17,6 +18,7 @@ typedef struct
GIcon *icon;
gchar *uri;
gchar *thumbnail_uri;
gchar *checksum;
/* This one is common to all */
guint size;
@ -51,6 +53,8 @@ cache_key_hash (gconstpointer a)
base_hash = g_str_hash (akey->uri);
else if (akey->thumbnail_uri)
base_hash = g_str_hash (akey->thumbnail_uri);
else if (akey->checksum)
base_hash = g_str_hash (akey->checksum);
else
g_assert_not_reached ();
return base_hash + 31*akey->size;
@ -76,6 +80,8 @@ cache_key_equal (gconstpointer a,
return strcmp (akey->uri, bkey->uri) == 0;
else if (akey->thumbnail_uri && bkey->thumbnail_uri)
return strcmp (akey->thumbnail_uri, bkey->thumbnail_uri) == 0;
else if (akey->checksum && bkey->checksum)
return strcmp (akey->checksum, bkey->checksum) == 0;
return FALSE;
}
@ -89,6 +95,7 @@ cache_key_dup (CacheKey *key)
ret->icon = g_object_ref (key->icon);
ret->uri = g_strdup (key->uri);
ret->thumbnail_uri = g_strdup (key->thumbnail_uri);
ret->checksum = g_strdup (key->checksum);
ret->size = key->size;
return ret;
}
@ -101,6 +108,7 @@ cache_key_destroy (gpointer a)
g_object_unref (akey->icon);
g_free (akey->uri);
g_free (akey->thumbnail_uri);
g_free (akey->checksum);
g_free (akey);
}
@ -318,7 +326,8 @@ on_image_size_prepared (GdkPixbufLoader *pixbuf_loader,
}
static GdkPixbuf *
impl_load_pixbuf_file (const char *uri,
impl_load_pixbuf_data (const guchar *data,
gsize size,
int available_width,
int available_height,
GError **error)
@ -326,22 +335,10 @@ impl_load_pixbuf_file (const char *uri,
GdkPixbufLoader *pixbuf_loader = NULL;
GdkPixbuf *rotated_pixbuf = NULL;
GdkPixbuf *pixbuf;
GFile *file = NULL;
char *contents = NULL;
gsize size;
gboolean success;
Dimensions available_dimensions;
int width_before_rotation, width_after_rotation;
file = g_file_new_for_uri (uri);
success = g_file_load_contents (file, NULL, &contents, &size, NULL, error);
if (!success)
{
goto out;
}
pixbuf_loader = gdk_pixbuf_loader_new ();
available_dimensions.width = available_width;
@ -349,10 +346,7 @@ impl_load_pixbuf_file (const char *uri,
g_signal_connect (pixbuf_loader, "size-prepared",
G_CALLBACK (on_image_size_prepared), &available_dimensions);
success = gdk_pixbuf_loader_write (pixbuf_loader,
(const guchar *) contents,
size,
error);
success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
if (!success)
goto out;
success = gdk_pixbuf_loader_close (pixbuf_loader, error);
@ -384,10 +378,7 @@ impl_load_pixbuf_file (const char *uri,
g_signal_connect (pixbuf_loader, "size-prepared",
G_CALLBACK (on_image_size_prepared), &available_dimensions);
success = gdk_pixbuf_loader_write (pixbuf_loader,
(const guchar *) contents,
size,
error);
success = gdk_pixbuf_loader_write (pixbuf_loader, data, size, error);
if (!success)
goto out;
@ -401,14 +392,36 @@ impl_load_pixbuf_file (const char *uri,
}
out:
g_free (contents);
if (file)
g_object_unref (file);
if (pixbuf_loader)
g_object_unref (pixbuf_loader);
return rotated_pixbuf;
}
static GdkPixbuf *
impl_load_pixbuf_file (const char *uri,
int available_width,
int available_height,
GError **error)
{
GdkPixbuf *pixbuf = NULL;
GFile *file;
char *contents = NULL;
gsize size;
file = g_file_new_for_uri (uri);
if (g_file_load_contents (file, NULL, &contents, &size, NULL, error))
{
pixbuf = impl_load_pixbuf_data ((const guchar *) contents, size,
available_width, available_height,
error);
}
g_object_unref (file);
g_free (contents);
return pixbuf;
}
static GdkPixbuf *
impl_load_thumbnail (ShellTextureCache *cache,
const char *uri,
@ -655,6 +668,7 @@ typedef struct {
gboolean thumbnail;
char *mimetype;
GtkRecentInfo *recent_info;
char *checksum;
GIcon *icon;
GtkIconInfo *icon_info;
guint width;
@ -1137,6 +1151,128 @@ shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
return CLUTTER_ACTOR (texture);
}
/**
* shell_texture_cache_load_from_data:
* @cache: The texture cache instance
* @data: Image data in PNG, GIF, etc format
* @len: length of @data
* @size: Size in pixels to use for the resulting texture
* @error: Return location for error
*
* Synchronously creates an image from @data. The image is scaled down
* to fit the available width and height dimensions, but the image is
* never scaled up beyond its actual size. The pixbuf is rotated
* according to the associated orientation setting.
*
* Return value: (transfer none): A new #ClutterActor with the image data loaded if it was
* generated succesfully, %NULL otherwise
*/
ClutterActor *
shell_texture_cache_load_from_data (ShellTextureCache *cache,
const guchar *data,
gsize len,
int size,
GError **error)
{
ClutterTexture *texture;
CoglHandle texdata;
GdkPixbuf *pixbuf;
CacheKey key;
gchar *checksum;
texture = create_default_texture (cache);
clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
memset (&key, 0, sizeof(key));
key.size = size;
key.checksum = checksum;
texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
if (texdata == NULL)
{
pixbuf = impl_load_pixbuf_data (data, len, size, size, error);
if (!pixbuf)
{
g_object_unref (texture);
return NULL;
}
texdata = pixbuf_to_cogl_handle (pixbuf);
g_object_unref (pixbuf);
set_texture_cogl_texture (texture, texdata);
g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
}
g_free (key.checksum);
set_texture_cogl_texture (texture, texdata);
return CLUTTER_ACTOR (texture);
}
/**
* shell_texture_cache_load_from_raw:
* @cache: a #ShellTextureCache
* @data: raw pixel data
* @len: the length of @data
* @has_alpha: whether @data includes an alpha channel
* @width: width in pixels of @data
* @height: width in pixels of @data
* @rowstride: rowstride of @data
* @size: size of icon to return
*
* Creates (or retrieves from cache) an icon based on raw pixel data.
*
* Return value: (transfer none): a new #ClutterActor displaying a
* pixbuf created from @data and the other parameters.
**/
ClutterActor *
shell_texture_cache_load_from_raw (ShellTextureCache *cache,
const guchar *data,
gsize len,
gboolean has_alpha,
int width,
int height,
int rowstride,
int size,
GError **error)
{
ClutterTexture *texture;
CoglHandle texdata;
CacheKey key;
gchar *checksum;
texture = create_default_texture (cache);
clutter_actor_set_size (CLUTTER_ACTOR (texture), size, size);
/* In theory, two images of different size could have the same
* pixel data. We ignore that theory.
*/
checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, len);
memset (&key, 0, sizeof(key));
key.size = size;
key.checksum = checksum;
texdata = g_hash_table_lookup (cache->priv->keyed_cache, &key);
if (texdata == NULL)
{
texdata = cogl_texture_new_from_data (width, height, COGL_TEXTURE_NONE,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
rowstride, data);
g_hash_table_insert (cache->priv->keyed_cache, cache_key_dup (&key), texdata);
}
g_free (key.checksum);
set_texture_cogl_texture (texture, texdata);
return CLUTTER_ACTOR (texture);
}
/**
* shell_texture_cache_load_thumbnail:
* @cache:

View File

@ -80,6 +80,21 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
int available_height,
GError **error);
ClutterActor *shell_texture_cache_load_from_data (ShellTextureCache *cache,
const guchar *data,
gsize len,
int size,
GError **error);
ClutterActor *shell_texture_cache_load_from_raw (ShellTextureCache *cache,
const guchar *data,
gsize len,
gboolean has_alpha,
int width,
int height,
int rowstride,
int size,
GError **error);
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
#endif /* __SHELL_TEXTURE_CACHE_H__ */

View File

@ -302,15 +302,15 @@ get_app_for_window_direct (MetaWindow *window)
char *wmclass;
char *with_desktop;
appsys = shell_app_system_get_default ();
wmclass = get_appid_from_window (window);
if (!wmclass)
return _shell_app_new_for_window (window);
return shell_app_system_get_app_for_window (appsys, window);
with_desktop = g_strjoin (NULL, wmclass, ".desktop", NULL);
g_free (wmclass);
appsys = shell_app_system_get_default ();
app = shell_app_system_lookup_heuristic_basename (appsys, with_desktop);
g_free (with_desktop);
@ -323,9 +323,7 @@ get_app_for_window_direct (MetaWindow *window)
}
if (app == NULL)
{
app = _shell_app_new_for_window (window);
}
app = shell_app_system_get_app_for_window (appsys, window);
return app;
}
@ -639,6 +637,43 @@ shell_window_tracker_get_window_app (ShellWindowTracker *monitor,
return app;
}
/**
* shell_app_system_get_from_pid:
* @self; A #ShellAppSystem
* @pid: A Unix process identifier
*
* Look up the application corresponding to a process.
*
* Returns: (transfer full): A #ShellApp, or %NULL if none
*/
ShellApp *
shell_window_tracker_get_app_from_pid (ShellWindowTracker *self,
int pid)
{
ShellGlobal *global = shell_global_get ();
GList *windows, *iter;
windows = shell_global_get_windows (global);
for (iter = windows; iter; iter = iter->next)
{
MutterWindow *win = iter->data;
MetaWindow *metawin;
int windowpid;
ShellApp *app;
metawin = mutter_window_get_meta_window (win);
windowpid = meta_window_get_pid (metawin);
if (windowpid != pid)
continue;
app = shell_window_tracker_get_window_app (self, metawin);
if (app)
return app;
}
return NULL;
}
/**
* shell_window_tracker_get_running_apps:
* @monitor: An app monitor instance

View File

@ -36,6 +36,8 @@ GSList * shell_window_tracker_get_running_apps (ShellWindowTracker *monitor,
ShellApp *shell_window_tracker_get_window_app (ShellWindowTracker *monitor, MetaWindow *metawin);
ShellApp *shell_window_tracker_get_app_from_pid (ShellWindowTracker *monitor, int pid);
gboolean shell_window_tracker_is_window_interesting (MetaWindow *window);
const char *_shell_window_tracker_get_app_context (ShellWindowTracker *tracker, ShellApp *app);

View File

@ -71,59 +71,6 @@ G_DEFINE_TYPE_WITH_CODE (StBin, st_bin, ST_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
clutter_container_iface_init));
void
_st_bin_get_align_factors (StBin *bin,
gdouble *x_align,
gdouble *y_align)
{
StBinPrivate *priv = bin->priv;
gdouble factor;
switch (priv->x_align)
{
case ST_ALIGN_START:
factor = 0.0;
break;
case ST_ALIGN_MIDDLE:
factor = 0.5;
break;
case ST_ALIGN_END:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (x_align)
*x_align = factor;
switch (priv->y_align)
{
case ST_ALIGN_START:
factor = 0.0;
break;
case ST_ALIGN_MIDDLE:
factor = 0.5;
break;
case ST_ALIGN_END:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (y_align)
*y_align = factor;
}
static void
st_bin_add (ClutterContainer *container,
ClutterActor *actor)
@ -199,92 +146,13 @@ st_bin_allocate (ClutterActor *self,
if (priv->child)
{
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
gfloat natural_width, natural_height;
gfloat min_width, min_height;
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox content_box;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align;
ClutterActorBox childbox;
st_theme_node_get_content_box (theme_node, box, &content_box);
_st_bin_get_align_factors (ST_BIN (self), &x_align, &y_align);
available_width = content_box.x2 - content_box.x1;
available_height = content_box.y2 - content_box.y1;
if (available_width < 0)
available_width = 0;
if (available_height < 0)
available_height = 0;
if (priv->x_fill)
{
allocation.x1 = (int) content_box.x1;
allocation.x2 = (int) content_box.x2;
}
if (priv->y_fill)
{
allocation.y1 = (int) content_box.y1;
allocation.y2 = (int) content_box.y2;
}
/* if we are filling horizontally and vertically then we're done */
if (priv->x_fill && priv->y_fill)
{
clutter_actor_allocate (priv->child, &allocation, flags);
return;
}
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (priv->child, available_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
clutter_actor_get_preferred_height (priv->child, child_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
}
else
{
clutter_actor_get_preferred_height (priv->child, available_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
clutter_actor_get_preferred_width (priv->child, child_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
}
if (!priv->x_fill)
{
allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + child_width;
}
if (!priv->y_fill)
{
allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + child_height;
}
clutter_actor_allocate (priv->child, &allocation, flags);
st_theme_node_get_content_box (theme_node, box, &childbox);
_st_allocate_fill (ST_WIDGET (self), priv->child, &childbox,
priv->x_align, priv->y_align,
priv->x_fill, priv->y_fill);
clutter_actor_allocate (priv->child, &childbox, flags);
}
}
@ -309,9 +177,9 @@ st_bin_get_preferred_width (ClutterActor *self,
}
else
{
clutter_actor_get_preferred_width (priv->child, for_height,
min_width_p,
natural_width_p);
_st_actor_get_preferred_width (priv->child, for_height, priv->y_fill,
min_width_p,
natural_width_p);
}
st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
@ -338,9 +206,9 @@ st_bin_get_preferred_height (ClutterActor *self,
}
else
{
clutter_actor_get_preferred_height (priv->child, for_width,
min_height_p,
natural_height_p);
_st_actor_get_preferred_height (priv->child, for_width, priv->x_fill,
min_height_p,
natural_height_p);
}
st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);

View File

@ -528,6 +528,7 @@ get_content_preferred_width (StBoxLayout *self,
{
ClutterActor *child = l->data;
gfloat child_min = 0, child_nat = 0;
gboolean child_fill;
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
@ -540,18 +541,20 @@ get_content_preferred_width (StBoxLayout *self,
continue;
}
clutter_actor_get_preferred_width (child,
(!priv->is_vertical) ? for_height : -1,
&child_min,
&child_nat);
if (priv->is_vertical)
{
_st_actor_get_preferred_width (child, -1, FALSE,
&child_min, &child_nat);
min_width = MAX (child_min, min_width);
natural_width = MAX (child_nat, natural_width);
}
else
{
clutter_container_child_get ((ClutterContainer*) self, child,
"y-fill", &child_fill,
NULL);
_st_actor_get_preferred_width (child, for_height, child_fill,
&child_min, &child_nat);
min_width += child_min;
natural_width += child_nat;
}
@ -606,6 +609,7 @@ get_content_preferred_height (StBoxLayout *self,
{
ClutterActor *child = l->data;
gfloat child_min = 0, child_nat = 0;
gboolean child_fill = FALSE;
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
@ -618,10 +622,17 @@ get_content_preferred_height (StBoxLayout *self,
continue;
}
clutter_actor_get_preferred_height (child,
(priv->is_vertical) ? for_width : -1,
&child_min,
&child_nat);
if (priv->is_vertical)
{
clutter_container_child_get ((ClutterContainer*) self, child,
"x-fill", &child_fill,
NULL);
}
_st_actor_get_preferred_height (child,
(priv->is_vertical) ? for_width : -1,
child_fill,
&child_min,
&child_nat);
if (!priv->is_vertical)
{
@ -713,6 +724,7 @@ compute_shrinks (StBoxLayout *self,
{
ClutterActor *child = l->data;
gfloat child_min, child_nat;
gboolean child_fill;
gboolean fixed;
child = (ClutterActor*) l->data;
@ -722,13 +734,23 @@ compute_shrinks (StBoxLayout *self,
if (CLUTTER_ACTOR_IS_VISIBLE (child) && !fixed)
{
if (priv->is_vertical)
clutter_actor_get_preferred_height (child,
for_length,
&child_min, &child_nat);
{
clutter_container_child_get ((ClutterContainer*) self, child,
"x-fill", &child_fill,
NULL);
_st_actor_get_preferred_height (child,
for_length, child_fill,
&child_min, &child_nat);
}
else
clutter_actor_get_preferred_width (child,
for_length,
&child_min, &child_nat);
{
clutter_container_child_get ((ClutterContainer*) self, child,
"y-fill", &child_fill,
NULL);
_st_actor_get_preferred_width (child,
for_length, child_fill,
&child_min, &child_nat);
}
shrinks[i].shrink_amount = MAX (0., child_nat - child_min);
n_possible_shrink_children++;
@ -943,13 +965,13 @@ st_box_layout_allocate (ClutterActor *actor,
if (priv->is_vertical)
{
clutter_actor_get_preferred_height (child, avail_width,
&child_min, &child_nat);
_st_actor_get_preferred_height (child, avail_width, xfill,
&child_min, &child_nat);
}
else
{
clutter_actor_get_preferred_width (child, avail_height,
&child_min, &child_nat);
_st_actor_get_preferred_width (child, avail_height, yfill,
&child_min, &child_nat);
}
child_allocated = child_nat;
@ -973,7 +995,8 @@ st_box_layout_allocate (ClutterActor *actor,
else
child_box.x2 = content_box.x2;
_st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill);
_st_allocate_fill (ST_WIDGET (actor), child, &child_box,
xalign, yalign, xfill, yfill);
clutter_actor_allocate (child, &child_box, flags);
}
@ -996,7 +1019,8 @@ st_box_layout_allocate (ClutterActor *actor,
else
child_box.y2 = content_box.y2;
_st_allocate_fill (child, &child_box, xalign, yalign, xfill, yfill);
_st_allocate_fill (ST_WIDGET (actor), child, &child_box,
xalign, yalign, xfill, yfill);
clutter_actor_allocate (child, &child_box, flags);
}
@ -1418,3 +1442,36 @@ st_box_layout_get_n_children (StBoxLayout *self)
{
return g_list_length (self->priv->children);
}
void
st_box_layout_move_child (StBoxLayout *self,
ClutterActor *actor,
int pos)
{
StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (self)->priv;
GList *item = NULL;
item = g_list_find (priv->children, actor);
if (item == NULL)
{
g_warning ("Actor of type '%s' is not a child of the StBoxLayout container",
g_type_name (G_OBJECT_TYPE (actor)));
return;
}
priv->children = g_list_delete_link (priv->children, item);
priv->children = g_list_insert (priv->children, actor, pos);
clutter_actor_queue_relayout ((ClutterActor*) self);
}
void
st_box_layout_insert_actor (StBoxLayout *self,
ClutterActor *actor,
int pos)
{
clutter_container_add_actor((ClutterContainer*) self, actor);
st_box_layout_move_child(self, actor, pos);
}

View File

@ -95,6 +95,14 @@ void st_box_layout_destroy_children (StBoxLayout *box);
guint st_box_layout_get_n_children (StBoxLayout *box);
void st_box_layout_move_child (StBoxLayout *self,
ClutterActor *actor,
int pos);
void st_box_layout_insert_actor (StBoxLayout *self,
ClutterActor *actor,
int pos);
G_END_DECLS
#endif /* _ST_BOX_LAYOUT_H */

View File

@ -75,6 +75,7 @@ struct _StButtonPrivate
ClutterActor *old_bg;
gboolean old_bg_parented; /* TRUE if we have adopted old_bg */
gboolean old_bg_animating; /* TRUE if the opacity animation is running and we hold a self-ref */
guint8 old_opacity;
@ -122,6 +123,11 @@ st_button_dispose_old_bg (StButton *button)
}
g_object_unref (priv->old_bg);
priv->old_bg = NULL;
if (priv->old_bg_animating)
{
g_object_unref (button);
priv->old_bg_animating = FALSE;
}
}
}
@ -180,6 +186,13 @@ st_button_style_changed (StWidget *widget)
priv->transition_duration,
"opacity", 0,
NULL);
/* The reference counting here is looped; through the button, old_bg,
* and the animation. However, that's not a problem because we will
* break the cycle when either the animation completes, or when
* we dispose.
*/
priv->old_bg_animating = TRUE;
g_object_ref (button);
g_signal_connect (animation, "completed",
G_CALLBACK (st_animation_completed), button);
}

View File

@ -1,12 +1,114 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "st-private.h"
/* Utility function to modify a child allocation box with respect to the
* x/y-fill child properties. Expects childbox to contain the available
* allocation space.
/**
* _st_actor_get_preferred_width:
* @actor: a #ClutterActor
* @for_height: as with clutter_actor_get_preferred_width()
* @y_fill: %TRUE if @actor will fill its allocation vertically
* @min_width_p: as with clutter_actor_get_preferred_width()
* @natural_width_p: as with clutter_actor_get_preferred_width()
*
* Like clutter_actor_get_preferred_width(), but if @y_fill is %FALSE,
* then it will compute a width request based on the assumption that
* @actor will be given an allocation no taller than its natural
* height.
*/
void
_st_allocate_fill (ClutterActor *child,
_st_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gboolean y_fill,
gfloat *min_width_p,
gfloat *natural_width_p)
{
if (!y_fill && for_height != -1)
{
ClutterRequestMode mode;
gfloat natural_height;
g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
if (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
{
clutter_actor_get_preferred_height (actor, -1, NULL, &natural_height);
if (for_height > natural_height)
for_height = natural_height;
}
}
clutter_actor_get_preferred_width (actor, for_height, min_width_p, natural_width_p);
}
/**
* _st_actor_get_preferred_height:
* @actor: a #ClutterActor
* @for_width: as with clutter_actor_get_preferred_height()
* @x_fill: %TRUE if @actor will fill its allocation horizontally
* @min_height_p: as with clutter_actor_get_preferred_height()
* @natural_height_p: as with clutter_actor_get_preferred_height()
*
* Like clutter_actor_get_preferred_height(), but if @x_fill is
* %FALSE, then it will compute a height request based on the
* assumption that @actor will be given an allocation no wider than
* its natural width.
*/
void
_st_actor_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gboolean x_fill,
gfloat *min_height_p,
gfloat *natural_height_p)
{
if (!x_fill && for_width != -1)
{
ClutterRequestMode mode;
gfloat natural_width;
g_object_get (G_OBJECT (actor), "request-mode", &mode, NULL);
if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (actor, -1, NULL, &natural_width);
if (for_width > natural_width)
for_width = natural_width;
}
}
clutter_actor_get_preferred_height (actor, for_width, min_height_p, natural_height_p);
}
/**
* _st_allocate_fill:
* @parent: the parent #StWidget
* @child: the child (not necessarily an #StWidget)
* @childbox: total space that could be allocated to @child
* @x_alignment: horizontal alignment within @childbox
* @y_alignment: vertical alignment within @childbox
* @x_fill: whether or not to fill @childbox horizontally
* @y_fill: whether or not to fill @childbox vertically
*
* Given @childbox, containing the initial allocation of @child, this
* adjusts the horizontal allocation if @x_fill is %FALSE, and the
* vertical allocation if @y_fill is %FALSE, by:
*
* - reducing the allocation if it is larger than @child's natural
* size.
*
* - adjusting the position of the child within the allocation
* according to @x_alignment/@y_alignment (and flipping
* @x_alignment if @parent has %ST_TEXT_DIRECTION_RTL)
*
* If @x_fill and @y_fill are both %TRUE, or if @child's natural size
* is larger than the initial allocation in @childbox, then @childbox
* will be unchanged.
*
* If you are allocating children with _st_allocate_fill(), you should
* determine their preferred sizes using
* _st_actor_get_preferred_width() and
* _st_actor_get_preferred_height(), not with the corresponding
* Clutter methods.
*/
void
_st_allocate_fill (StWidget *parent,
ClutterActor *child,
ClutterActorBox *childbox,
StAlign x_alignment,
StAlign y_alignment,
@ -18,51 +120,36 @@ _st_allocate_fill (ClutterActor *child,
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align;
if (x_alignment == ST_ALIGN_START)
x_align = 0.0;
else if (x_alignment == ST_ALIGN_MIDDLE)
x_align = 0.5;
else
x_align = 1.0;
if (y_alignment == ST_ALIGN_START)
y_align = 0.0;
else if (y_alignment == ST_ALIGN_MIDDLE)
y_align = 0.5;
else
y_align = 1.0;
available_width = childbox->x2 - childbox->x1;
available_height = childbox->y2 - childbox->y1;
if (available_width < 0)
available_width = 0;
{
available_width = 0;
childbox->x2 = childbox->x1;
}
if (available_height < 0)
available_height = 0;
if (x_fill)
{
allocation.x1 = childbox->x1;
allocation.x2 = (int)(allocation.x1 + available_width);
available_height = 0;
childbox->y2 = childbox->y1;
}
if (y_fill)
{
allocation.y1 = childbox->y1;
allocation.y2 = (int)(allocation.y1 + available_height);
}
/* if we are filling horizontally and vertically then we're done */
/* If we are filling both horizontally and vertically then we don't
* need to do anything else.
*/
if (x_fill && y_fill)
{
*childbox = allocation;
return;
}
return;
_st_get_align_factors (parent, x_alignment, y_alignment,
&x_align, &y_align);
/* The following is based on clutter_actor_get_preferred_size(), but
* modified to cope with the fact that the available size may be
* less than the preferred size.
*/
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
@ -97,18 +184,82 @@ _st_allocate_fill (ClutterActor *child,
if (!x_fill)
{
allocation.x1 = childbox->x1 + (int)((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + (int) child_width;
childbox->x1 += (int)((available_width - child_width) * x_align);
childbox->x2 = childbox->x1 + (int) child_width;
}
if (!y_fill)
{
allocation.y1 = childbox->y1 + (int)((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + (int) child_height;
childbox->y1 += (int)((available_height - child_height) * y_align);
childbox->y2 = childbox->y1 + (int) child_height;
}
}
/**
* _st_get_align_factors:
* @widget: an #StWidget
* @x_align: an #StAlign
* @y_align: an #StAlign
* @x_align_out: (out) (allow-none): @x_align as a #gdouble
* @y_align_out: (out) (allow-none): @y_align as a #gdouble
*
* Converts @x_align and @y_align to #gdouble values. If @widget has
* %ST_TEXT_DIRECTION_RTL, the @x_align_out value will be flipped
* relative to @x_align.
*/
void
_st_get_align_factors (StWidget *widget,
StAlign x_align,
StAlign y_align,
gdouble *x_align_out,
gdouble *y_align_out)
{
if (x_align_out)
{
switch (x_align)
{
case ST_ALIGN_START:
*x_align_out = 0.0;
break;
case ST_ALIGN_MIDDLE:
*x_align_out = 0.5;
break;
case ST_ALIGN_END:
*x_align_out = 1.0;
break;
default:
g_warn_if_reached ();
break;
}
if (st_widget_get_direction (widget) == ST_TEXT_DIRECTION_RTL)
*x_align_out = 1.0 - *x_align_out;
}
*childbox = allocation;
if (y_align_out)
{
switch (y_align)
{
case ST_ALIGN_START:
*y_align_out = 0.0;
break;
case ST_ALIGN_MIDDLE:
*y_align_out = 0.5;
break;
case ST_ALIGN_END:
*y_align_out = 1.0;
break;
default:
g_warn_if_reached ();
break;
}
}
}
/**

View File

@ -44,11 +44,25 @@ G_END_DECLS
ClutterActor *_st_widget_get_dnd_clone (StWidget *widget);
void _st_bin_get_align_factors (StBin *bin,
gdouble *x_align,
gdouble *y_align);
void _st_get_align_factors (StWidget *widget,
StAlign x_align,
StAlign y_align,
gdouble *x_align_out,
gdouble *y_align_out);
void _st_allocate_fill (ClutterActor *child,
void _st_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gboolean y_fill,
gfloat *min_width_p,
gfloat *natural_width_p);
void _st_actor_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gboolean x_fill,
gfloat *min_height_p,
gfloat *natural_height_p);
void _st_allocate_fill (StWidget *parent,
ClutterActor *child,
ClutterActorBox *childbox,
StAlign x_align,
StAlign y_align,

View File

@ -271,7 +271,7 @@ st_scroll_bar_allocate (ClutterActor *actor,
StScrollBarPrivate *priv = ST_SCROLL_BAR (actor)->priv;
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
ClutterActorBox content_box, bw_box, fw_box, trough_box;
gfloat stepper_size;
gfloat bw_stepper_size, fw_stepper_size, min_size, natural_size;
/* Chain up */
CLUTTER_ACTOR_CLASS (st_scroll_bar_parent_class)->
@ -281,52 +281,70 @@ st_scroll_bar_allocate (ClutterActor *actor,
if (priv->vertical)
{
stepper_size = content_box.x2 - content_box.x1;
gfloat width = content_box.x2 - content_box.x1;
clutter_actor_get_preferred_height (priv->bw_stepper, width,
&min_size, &natural_size);
bw_stepper_size = MAX (min_size, natural_size);
/* Backward stepper */
bw_box.x1 = content_box.x1;
bw_box.y1 = content_box.y1;
bw_box.x2 = content_box.x2;
bw_box.y2 = bw_box.y1 + stepper_size;
bw_box.y2 = bw_box.y1 + bw_stepper_size;
clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);
clutter_actor_get_preferred_height (priv->fw_stepper, width,
&min_size, &natural_size);
fw_stepper_size = MAX (min_size, natural_size);
/* Forward stepper */
fw_box.x1 = content_box.x1;
fw_box.y1 = content_box.y2 - stepper_size;
fw_box.y1 = content_box.y2 - fw_stepper_size;
fw_box.x2 = content_box.x2;
fw_box.y2 = content_box.y2;
clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);
/* Trough */
trough_box.x1 = content_box.x1;
trough_box.y1 = content_box.y1 + stepper_size;
trough_box.y1 = content_box.y1 + bw_stepper_size;
trough_box.x2 = content_box.x2;
trough_box.y2 = content_box.y2 - stepper_size;
trough_box.y2 = content_box.y2 - fw_stepper_size;
clutter_actor_allocate (priv->trough, &trough_box, flags);
}
else
{
stepper_size = content_box.y2 - content_box.y1;
gfloat height = content_box.y2 - content_box.y1;
clutter_actor_get_preferred_width (priv->bw_stepper, height,
&min_size, &natural_size);
bw_stepper_size = MAX (min_size, natural_size);
/* Backward stepper */
bw_box.x1 = content_box.x1;
bw_box.y1 = content_box.y1;
bw_box.x2 = bw_box.x1 + stepper_size;
bw_box.x2 = bw_box.x1 + bw_stepper_size;
bw_box.y2 = content_box.y2;
clutter_actor_allocate (priv->bw_stepper, &bw_box, flags);
clutter_actor_get_preferred_width (priv->fw_stepper, height,
&min_size, &natural_size);
fw_stepper_size = MAX (min_size, natural_size);
/* Forward stepper */
fw_box.x1 = content_box.x2 - stepper_size;
fw_box.x1 = content_box.x2 - fw_stepper_size;
fw_box.y1 = content_box.y1;
fw_box.x2 = content_box.x2;
fw_box.y2 = content_box.y2;
clutter_actor_allocate (priv->fw_stepper, &fw_box, flags);
/* Trough */
trough_box.x1 = content_box.x1 + stepper_size;
trough_box.x1 = content_box.x1 + bw_stepper_size;
trough_box.y1 = content_box.y1;
trough_box.x2 = content_box.x2 - stepper_size;
trough_box.x2 = content_box.x2 - fw_stepper_size;
trough_box.y2 = content_box.y2;
clutter_actor_allocate (priv->trough, &trough_box, flags);
}
@ -335,10 +353,12 @@ st_scroll_bar_allocate (ClutterActor *actor,
if (priv->adjustment)
{
StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
float handle_size, position, avail_size;
float handle_size, position, avail_size, stepper_size;
gdouble value, lower, upper, page_size, increment, min_size, max_size;
ClutterActorBox handle_box = { 0, };
stepper_size = bw_stepper_size + fw_stepper_size;
st_adjustment_get_values (priv->adjustment,
&value,
&lower,
@ -365,7 +385,7 @@ st_scroll_bar_allocate (ClutterActor *actor,
if (priv->vertical)
{
avail_size = content_box.y2 - content_box.y1 - stepper_size * 2;
avail_size = content_box.y2 - content_box.y1 - stepper_size;
handle_size = increment * avail_size;
handle_size = CLAMP (handle_size, min_size, max_size);
@ -377,7 +397,7 @@ st_scroll_bar_allocate (ClutterActor *actor,
}
else
{
avail_size = content_box.x2 - content_box.x1 - stepper_size * 2;
avail_size = content_box.x2 - content_box.x1 - stepper_size;
handle_size = increment * avail_size;
handle_size = CLAMP (handle_size, min_size, max_size);

View File

@ -37,6 +37,7 @@
#include "st-scroll-bar.h"
#include "st-scrollable.h"
#include <clutter/clutter.h>
#include <math.h>
static void clutter_container_iface_init (ClutterContainerIface *iface);
@ -64,9 +65,16 @@ struct _StScrollViewPrivate
ClutterActor *hscroll;
ClutterActor *vscroll;
GtkPolicyType hscroll_policy;
GtkPolicyType vscroll_policy;
ClutterActor *top_shadow;
ClutterActor *bottom_shadow;
gfloat row_size;
gfloat column_size;
gboolean vshadows;
gboolean row_size_set : 1;
gboolean column_size_set : 1;
guint mouse_scroll : 1;
@ -77,7 +85,10 @@ enum {
PROP_HSCROLL,
PROP_VSCROLL,
PROP_MOUSE_SCROLL
PROP_HSCROLLBAR_POLICY,
PROP_VSCROLLBAR_POLICY,
PROP_MOUSE_SCROLL,
PROP_VSHADOWS
};
static void
@ -96,25 +107,104 @@ st_scroll_view_get_property (GObject *object,
case PROP_VSCROLL:
g_value_set_object (value, priv->vscroll);
break;
case PROP_HSCROLLBAR_POLICY:
g_value_set_enum (value, priv->hscroll_policy);
break;
case PROP_VSCROLLBAR_POLICY:
g_value_set_enum (value, priv->vscroll_policy);
break;
case PROP_MOUSE_SCROLL:
g_value_set_boolean (value, priv->mouse_scroll);
break;
case PROP_VSHADOWS:
g_value_set_boolean (value, priv->vshadows);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
update_shadow_visibility (GObject *gobject,
GParamSpec *arg1,
gpointer user_data)
{
StAdjustment *vadjust = ST_ADJUSTMENT (gobject);
StScrollViewPrivate *priv = ST_SCROLL_VIEW (user_data)->priv;
gdouble value, lower, upper, page_size;
st_adjustment_get_values (vadjust, &value, &lower, &upper, NULL, NULL, &page_size);
if (fabs (value - lower) > 0.1 && priv->vshadows)
clutter_actor_show (priv->top_shadow);
else
clutter_actor_hide (priv->top_shadow);
if (fabs (upper - value - page_size) > 0.1 && priv->vshadows)
clutter_actor_show (priv->bottom_shadow);
else
clutter_actor_hide (priv->bottom_shadow);
}
/**
* st_scroll_view_set_vshadows:
* @self: a #StScrollView
* @vshadows: Whether to enable vertical shadows
*
* Sets whether to show shadows at the top and bottom of the area. Shadows
* are omitted when fully scrolled to that edge.
*/
void
st_scroll_view_set_vshadows (StScrollView *self,
gboolean vshadows)
{
StAdjustment *vadjust;
StScrollViewPrivate *priv = ST_SCROLL_VIEW (self)->priv;
vshadows = vshadows != FALSE;
if (priv->vshadows == vshadows)
return;
priv->vshadows = vshadows;
vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll));
if (!vadjust)
return;
update_shadow_visibility (G_OBJECT (vadjust), NULL, self);
g_object_notify (G_OBJECT (self), "vshadows");
}
static void
st_scroll_view_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
StScrollView *self = ST_SCROLL_VIEW (object);
StScrollViewPrivate *priv = self->priv;
switch (property_id)
{
case PROP_VSHADOWS:
st_scroll_view_set_vshadows (self, g_value_get_boolean (value));
break;
case PROP_MOUSE_SCROLL:
st_scroll_view_set_mouse_scrolling ((StScrollView *) object,
st_scroll_view_set_mouse_scrolling (self,
g_value_get_boolean (value));
break;
case PROP_HSCROLLBAR_POLICY:
st_scroll_view_set_policy (self,
g_value_get_enum (value),
priv->vscroll_policy);
break;
case PROP_VSCROLLBAR_POLICY:
st_scroll_view_set_policy (self,
priv->hscroll_policy,
g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
@ -145,6 +235,11 @@ st_scroll_view_dispose (GObject *object)
static void
st_scroll_view_finalize (GObject *object)
{
StScrollViewPrivate *priv = ST_SCROLL_VIEW (object)->priv;
g_object_unref (priv->top_shadow);
g_object_unref (priv->bottom_shadow);
G_OBJECT_CLASS (st_scroll_view_parent_class)->finalize (object);
}
@ -161,6 +256,11 @@ st_scroll_view_paint (ClutterActor *actor)
clutter_actor_paint (priv->hscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
clutter_actor_paint (priv->vscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
clutter_actor_paint (priv->top_shadow);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
clutter_actor_paint (priv->bottom_shadow);
}
static void
@ -177,6 +277,11 @@ st_scroll_view_pick (ClutterActor *actor,
clutter_actor_paint (priv->hscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->vscroll))
clutter_actor_paint (priv->vscroll);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
clutter_actor_paint (priv->top_shadow);
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
clutter_actor_paint (priv->bottom_shadow);
}
static double
@ -347,6 +452,25 @@ st_scroll_view_allocate (ClutterActor *actor,
if (priv->child)
clutter_actor_allocate (priv->child, &child_box, flags);
/*Shadows*/
if (CLUTTER_ACTOR_IS_VISIBLE (priv->top_shadow))
{
child_box.x1 = content_box.x1;
child_box.y1 = content_box.y1;
child_box.x2 = MAX (child_box.x1, content_box.x2 - sb_width);
child_box.y2 = MAX (child_box.y1, content_box.y1 + clutter_actor_get_height (priv->top_shadow));
clutter_actor_allocate (priv->top_shadow, &child_box, flags);
}
if (CLUTTER_ACTOR_IS_VISIBLE (priv->bottom_shadow))
{
child_box.x1 = content_box.x1;
child_box.y1 = content_box.y2 - clutter_actor_get_height (priv->bottom_shadow);
child_box.x2 = MAX (child_box.x1, content_box.x2 - sb_width);
child_box.y2 = content_box.y2 + 1;
clutter_actor_allocate (priv->bottom_shadow, &child_box, flags);
}
}
static void
@ -357,6 +481,9 @@ st_scroll_view_style_changed (StWidget *widget)
st_widget_style_changed (ST_WIDGET (priv->hscroll));
st_widget_style_changed (ST_WIDGET (priv->vscroll));
st_widget_style_changed (ST_WIDGET (priv->top_shadow));
st_widget_style_changed (ST_WIDGET (priv->bottom_shadow));
ST_WIDGET_CLASS (st_scroll_view_parent_class)->style_changed (widget);
}
@ -474,6 +601,23 @@ st_scroll_view_class_init (StScrollViewClass *klass)
ST_TYPE_SCROLL_BAR,
G_PARAM_READABLE));
pspec = g_param_spec_enum ("vscrollbar-policy",
"Vertical Scrollbar Policy",
"When the vertical scrollbar is displayed",
GTK_TYPE_POLICY_TYPE,
GTK_POLICY_AUTOMATIC,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_VSCROLLBAR_POLICY, pspec);
pspec = g_param_spec_enum ("hscrollbar-policy",
"Horizontal Scrollbar Policy",
"When the horizontal scrollbar is displayed",
GTK_TYPE_POLICY_TYPE,
GTK_POLICY_AUTOMATIC,
G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_HSCROLLBAR_POLICY, pspec);
pspec = g_param_spec_boolean ("enable-mouse-scrolling",
"Enable Mouse Scrolling",
"Enable automatic mouse wheel scrolling",
@ -483,6 +627,14 @@ st_scroll_view_class_init (StScrollViewClass *klass)
PROP_MOUSE_SCROLL,
pspec);
pspec = g_param_spec_boolean ("vshadows",
"Vertical Shadows",
"Show shadows at the top and and bottom of the area unless fully scrolled to that edge",
FALSE,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_VSHADOWS,
pspec);
}
static void
@ -494,6 +646,9 @@ child_adjustment_changed_cb (StAdjustment *adjustment,
scroll = ST_SCROLL_VIEW (clutter_actor_get_parent (bar));
if (bar == scroll->priv->vscroll)
update_shadow_visibility (G_OBJECT (adjustment), NULL, scroll);
/* Determine if this scroll-bar should be visible */
st_adjustment_get_values (adjustment, NULL,
&lower, &upper,
@ -525,6 +680,9 @@ child_hadjustment_notify_cb (GObject *gobject,
child_adjustment_changed_cb,
priv->hscroll);
if (priv->hscroll_policy == GTK_POLICY_NEVER)
return;
st_scrollable_get_adjustments (ST_SCROLLABLE (actor), &hadjust, NULL);
if (hadjust)
{
@ -537,9 +695,13 @@ child_hadjustment_notify_cb (GObject *gobject,
}
st_scroll_bar_set_adjustment (ST_SCROLL_BAR(priv->hscroll), hadjust);
g_signal_connect (hadjust, "changed", G_CALLBACK (
child_adjustment_changed_cb), priv->hscroll);
child_adjustment_changed_cb (hadjust, priv->hscroll);
if (priv->hscroll_policy == GTK_POLICY_AUTOMATIC)
{
g_signal_connect (hadjust, "changed", G_CALLBACK (
child_adjustment_changed_cb), priv->hscroll);
child_adjustment_changed_cb (hadjust, priv->hscroll);
}
}
}
@ -555,10 +717,16 @@ child_vadjustment_notify_cb (GObject *gobject,
vadjust = st_scroll_bar_get_adjustment (ST_SCROLL_BAR(priv->vscroll));
if (vadjust)
g_signal_handlers_disconnect_by_func (vadjust,
child_adjustment_changed_cb,
priv->vscroll);
{
g_signal_handlers_disconnect_by_func (vadjust,
update_shadow_visibility,
user_data);
g_signal_handlers_disconnect_by_func (vadjust,
child_adjustment_changed_cb,
priv->vscroll);
}
if (priv->vscroll_policy == GTK_POLICY_NEVER)
return;
st_scrollable_get_adjustments (ST_SCROLLABLE(actor), NULL, &vadjust);
if (vadjust)
{
@ -571,9 +739,15 @@ child_vadjustment_notify_cb (GObject *gobject,
}
st_scroll_bar_set_adjustment (ST_SCROLL_BAR(priv->vscroll), vadjust);
g_signal_connect (vadjust, "changed", G_CALLBACK (
child_adjustment_changed_cb), priv->vscroll);
child_adjustment_changed_cb (vadjust, priv->vscroll);
if (priv->vscroll_policy == GTK_POLICY_AUTOMATIC)
{
g_signal_connect (vadjust, "changed", G_CALLBACK (
child_adjustment_changed_cb), priv->vscroll);
g_signal_connect (vadjust, "notify::value", G_CALLBACK (
update_shadow_visibility), user_data);
child_adjustment_changed_cb (vadjust, priv->vscroll);
update_shadow_visibility (G_OBJECT (vadjust), NULL, user_data);
}
}
}
@ -582,12 +756,21 @@ st_scroll_view_init (StScrollView *self)
{
StScrollViewPrivate *priv = self->priv = SCROLL_VIEW_PRIVATE (self);
priv->hscroll_policy = GTK_POLICY_AUTOMATIC;
priv->vscroll_policy = GTK_POLICY_AUTOMATIC;
priv->hscroll = CLUTTER_ACTOR (st_scroll_bar_new (NULL));
priv->vscroll = g_object_new (ST_TYPE_SCROLL_BAR, "vertical", TRUE, NULL);
clutter_actor_set_parent (priv->hscroll, CLUTTER_ACTOR (self));
clutter_actor_set_parent (priv->vscroll, CLUTTER_ACTOR (self));
priv->top_shadow = g_object_new (ST_TYPE_BIN, "style-class", "top-shadow", NULL);
priv->bottom_shadow = g_object_new (ST_TYPE_BIN, "style-class", "bottom-shadow", NULL);
clutter_actor_set_parent (priv->bottom_shadow, CLUTTER_ACTOR (self));
clutter_actor_set_parent (priv->top_shadow, CLUTTER_ACTOR (self));
/* mouse scroll is enabled by default, so we also need to be reactive */
priv->mouse_scroll = TRUE;
g_object_set (G_OBJECT (self), "reactive", TRUE, NULL);
@ -667,6 +850,9 @@ st_scroll_view_foreach_with_internals (ClutterContainer *container,
if (priv->vscroll != NULL)
callback (priv->vscroll, user_data);
callback (priv->top_shadow, user_data);
callback (priv->bottom_shadow, user_data);
}
static void
@ -842,3 +1028,73 @@ st_scroll_view_get_mouse_scrolling (StScrollView *scroll)
return priv->mouse_scroll;
}
/**
* st_scroll_view_set_policy:
* @scroll: A #StScrollView
* @hscroll: Whether to enable horizontal scrolling
* @vscroll: Whether to enable vertical scrolling
*
* Set the scroll policy.
*/
void
st_scroll_view_set_policy (StScrollView *scroll,
GtkPolicyType hscroll,
GtkPolicyType vscroll)
{
StScrollViewPrivate *priv;
StAdjustment *hadjust, *vadjust;
g_return_if_fail (ST_IS_SCROLL_VIEW (scroll));
g_return_if_fail (hscroll != GTK_POLICY_ALWAYS && vscroll != GTK_POLICY_ALWAYS);
priv = ST_SCROLL_VIEW (scroll)->priv;
if (priv->hscroll_policy == hscroll && priv->vscroll_policy == vscroll)
return;
g_object_freeze_notify ((GObject *) scroll);
if (priv->hscroll_policy != hscroll)
{
priv->hscroll_policy = hscroll;
g_object_notify ((GObject *) scroll, "hscrollbar-policy");
}
if (priv->vscroll_policy != vscroll)
{
priv->vscroll_policy = vscroll;
g_object_notify ((GObject *) scroll, "vscrollbar-policy");
}
st_scrollable_get_adjustments (ST_SCROLLABLE (priv->child), &hadjust, &vadjust);
if (priv->hscroll_policy == GTK_POLICY_NEVER)
{
hadjust = NULL;
clutter_actor_hide (priv->hscroll);
}
else if (priv->hscroll_policy == GTK_POLICY_AUTOMATIC)
{
/* We call this function because we need to set up the adjustment
* notification hooks, and the _show will queue a reallocate, from which we'll figure
* out if we need to really show or hide the scrollbar.
*/
child_hadjustment_notify_cb (G_OBJECT (priv->child), NULL, scroll);
clutter_actor_show (priv->hscroll);
}
if (priv->vscroll_policy == GTK_POLICY_NEVER)
{
vadjust = NULL;
clutter_actor_hide (priv->vscroll);
}
else
{
child_vadjustment_notify_cb (G_OBJECT (priv->child), NULL, scroll);
clutter_actor_show (priv->vscroll);
}
st_scrollable_set_adjustments (ST_SCROLLABLE (priv->child), hadjust, vadjust);
g_object_thaw_notify ((GObject *) scroll);
}

View File

@ -84,6 +84,13 @@ void st_scroll_view_set_mouse_scrolling (StScrollView *scroll,
gboolean enabled);
gboolean st_scroll_view_get_mouse_scrolling (StScrollView *scroll);
void st_scroll_view_set_policy (StScrollView *scroll,
GtkPolicyType hscroll,
GtkPolicyType vscroll);
void st_scroll_view_set_vshadows (StScrollView *self,
gboolean vshadows);
G_END_DECLS
#endif /* __ST_SCROLL_VIEW_H__ */

273
src/st/st-shadow-texture.c Normal file
View File

@ -0,0 +1,273 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include <math.h>
#include <string.h>
#include "st-shadow-texture.h"
/**
* SECTION: st-shadow-texture
* @short_description: a class for creating soft shadow textures
*
* #StShadowTexture is a #ClutterTexture holding a soft shadow texture for
* another #ClutterActor.
* It is used to implement the box-shadow property in StWidget and should
* not be used stand-alone.
*/
struct _StShadowTexture {
ClutterTexture parent;
CoglColor color;
gdouble sigma;
gdouble blur_radius;
};
struct _StShadowTextureClass {
ClutterTextureClass parent_class;
};
G_DEFINE_TYPE (StShadowTexture, st_shadow_texture, CLUTTER_TYPE_TEXTURE);
static gdouble *
calculate_gaussian_kernel (gdouble sigma, guint n_values)
{
gdouble *ret, sum;
gdouble exp_divisor;
gint half, i;
g_return_val_if_fail ((int) sigma > 0, NULL);
half = n_values / 2;
ret = g_malloc (n_values * sizeof (gdouble));
sum = 0.0;
exp_divisor = 2 * sigma * sigma;
/* n_values of 1D Gauss function */
for (i = 0; i < n_values; i++)
{
ret[i] = exp (-(i - half) * (i - half) / exp_divisor);
sum += ret[i];
}
/* normalize */
for (i = 0; i < n_values; i++)
ret[i] /= sum;
return ret;
}
static void
st_shadow_texture_create_shadow (StShadowTexture *st,
ClutterActor *actor)
{
CoglHandle texture, material;
guchar *pixels_in, *pixels_out;
gint width_in, height_in, rowstride_in;
gint width_out, height_out, rowstride_out;
g_return_if_fail (ST_IS_SHADOW_TEXTURE (st));
/* Right now we only deal with actors of type ClutterTexture.
It would be nice to extend this to generic actors with some
clutter_texture_new_from_actor magic in the future */
g_return_if_fail (CLUTTER_IS_TEXTURE (actor));
texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (actor));
if (texture == COGL_INVALID_HANDLE)
return;
width_in = cogl_texture_get_width (texture);
height_in = cogl_texture_get_height (texture);
rowstride_in = (width_in + 3) & ~3;
pixels_in = g_malloc0 (rowstride_in * height_in);
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_A_8,
rowstride_in, pixels_in);
if ((guint) st->blur_radius == 0)
{
width_out = width_in;
height_out = height_in;
rowstride_out = rowstride_in;
pixels_out = g_memdup (pixels_in, rowstride_out * height_out);
}
else
{
gdouble *kernel;
guchar *line;
gint n_values, half;
gint x_in, y_in, x_out, y_out, i;
n_values = (gint) 5 * st->sigma;
half = n_values / 2;
width_out = width_in + 2 * half;
height_out = height_in + 2 * half;
rowstride_out = (width_out + 3) & ~3;
pixels_out = g_malloc0 (rowstride_out * height_out);
line = g_malloc0 (rowstride_out);
kernel = calculate_gaussian_kernel (st->sigma, n_values);
/* vertical blur */
for (x_in = 0; x_in < width_in; x_in++)
for (y_out = 0; y_out < height_out; y_out++)
{
guchar *pixel_in, *pixel_out;
gint i0, i1;
y_in = y_out - half;
/* We read from the source at 'y = y_in + i - half'; clamp the
* full i range [0, n_values) so that y is in [0, height_in).
*/
i0 = MAX (half - y_in, 0);
i1 = MIN (height_in + half - y_in, n_values);
pixel_in = pixels_in + (y_in + i0 - half) * rowstride_in + x_in;
pixel_out = pixels_out + y_out * rowstride_out + (x_in + half);
for (i = i0; i < i1; i++)
{
*pixel_out += *pixel_in * kernel[i];
pixel_in += rowstride_in;
}
}
/* horizontal blur */
for (y_out = 0; y_out < height_out; y_out++)
{
memcpy (line, pixels_out + y_out * rowstride_out, rowstride_out);
for (x_out = 0; x_out < width_out; x_out++)
{
gint i0, i1;
guchar *pixel_out, *pixel_in;
/* We read from the source at 'x = x_out + i - half'; clamp the
* full i range [0, n_values) so that x is in [0, width_out).
*/
i0 = MAX (half - x_out, 0);
i1 = MIN (width_out + half - x_out, n_values);
pixel_in = line + x_out + i0 - half;
pixel_out = pixels_out + rowstride_out * y_out + x_out;
*pixel_out = 0;
for (i = i0; i < i1; i++)
{
*pixel_out += *pixel_in * kernel[i];
pixel_in++;
}
}
}
g_free (kernel);
g_free (line);
}
material = cogl_material_new ();
texture = cogl_texture_new_from_data (width_out,
height_out,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_A_8,
rowstride_out,
pixels_out);
cogl_material_set_layer_combine_constant (material, 0, &st->color);
cogl_material_set_layer (material, 0, texture);
/* We ignore the material color, which encodes the overall opacity of the
* actor, so setting an ancestor of the shadow to partially opaque won't
* work. The easiest way to fix this would be to override paint(). */
cogl_material_set_layer_combine (material, 0,
"RGBA = MODULATE (CONSTANT, TEXTURE[A])",
NULL);
clutter_texture_set_cogl_material (CLUTTER_TEXTURE (st), material);
cogl_texture_unref (texture);
cogl_material_unref (material);
g_free (pixels_in);
g_free (pixels_out);
}
/**
* st_shadow_texture_adjust_allocation:
* @shadow: a #StShadowTexture
* @allocation: the original allocation of @shadow
*
* Adjust @allocation to account for size change caused by blurrimg
*/
void
st_shadow_texture_adjust_allocation (StShadowTexture *shadow,
ClutterActorBox *allocation)
{
g_return_if_fail (ST_IS_SHADOW_TEXTURE (shadow));
g_return_if_fail (allocation != NULL);
allocation->x1 -= shadow->blur_radius;
allocation->y1 -= shadow->blur_radius;
allocation->x2 += shadow->blur_radius;
allocation->y2 += shadow->blur_radius;
}
/**
* st_shadow_texture_new:
* @actor: the original actor
* @color: (allow-none): the shadow color
* @blur: the shadow's blur radius
*
* Create a shadow texture for @actor. When %NULL is passed for @color, it
* defaults to fully opaque black.
*
* Returns: a new #ClutterActor holding a shadow texture for @actor
*/
ClutterActor *
st_shadow_texture_new (ClutterActor *actor,
ClutterColor *color,
gdouble blur)
{
StShadowTexture *st = g_object_new (ST_TYPE_SHADOW_TEXTURE, NULL);
if (color)
{
cogl_color_set_from_4ub (&st->color,
color->red, color->green,
color->blue, color->alpha);
cogl_color_premultiply (&st->color);
}
st->blur_radius = blur;
/* we use an approximation of the sigma - blur radius relationship used
in Firefox for doing SVG blurs; see
http://mxr.mozilla.org/mozilla-central/source/gfx/thebes/src/gfxBlur.cpp#280
*/
st->sigma = blur / 1.9;
st_shadow_texture_create_shadow (st, actor);
return CLUTTER_ACTOR (st);
}
static void
st_shadow_texture_init (StShadowTexture *st)
{
st->sigma = 0.0;
st->blur_radius = 0.0;
cogl_color_set_from_4ub (&st->color, 0x0, 0x0, 0x0, 0xff);
}
static void
st_shadow_texture_class_init (StShadowTextureClass *klass)
{
}

View File

@ -0,0 +1,30 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __ST_SHADOW_TEXTURE__
#define __ST_SHADOW_TEXTURE__
#include <clutter/clutter.h>
G_BEGIN_DECLS
typedef struct _StShadowTexture StShadowTexture;
typedef struct _StShadowTextureClass StShadowTextureClass;
#define ST_TYPE_SHADOW_TEXTURE (st_shadow_texture_get_type ())
#define ST_SHADOW_TEXTURE(object) (G_TYPE_CHECK_INSTANCE_CAST((object),ST_TYPE_SHADOW_TEXTURE, StShadowTexture))
#define ST_IS_SHADOW_TEXTURE(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),ST_TYPE_SHADOW_TEXTURE))
#define ST_SHADOW_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ST_TYPE_SHADOW_TEXTURE, StShadowTextureClass))
#define ST_IS_SHADOW_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ST_TYPE_SHADOW_TEXTURE))
#define ST_SHADOW_TEXTURE_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), ST_TYPE_SHADOW_TEXTURE, StShadowTextureClass))
GType st_shadow_texture_get_type (void) G_GNUC_CONST;
ClutterActor *st_shadow_texture_new (ClutterActor *actor,
ClutterColor *color,
gdouble blur_radius);
void st_shadow_texture_adjust_allocation (StShadowTexture *shadow,
ClutterActorBox *allocation);
G_END_DECLS
#endif /* __ST_SHADOW_TEXTURE__ */

89
src/st/st-shadow.c Normal file
View File

@ -0,0 +1,89 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "config.h"
#include "st-shadow.h"
/**
* SECTION: st-shadow
* @short_description: Boxed type for -st-shadow attributes
*
* #StShadow is a boxed type for storing attributes of the -st-shadow
* property, modelled liberally after the CSS3 box-shadow property.
* See http://www.css3.info/preview/box-shadow/
*
*/
/**
* st_shadow_new:
* @color: shadow's color
* @xoffset: horizontal offset
* @yoffset: vertical offset
* @blur: blur radius
*
* Creates a new #StShadow
*
* Returns: the newly allocated shadow. Use st_shadow_free() when done
*/
StShadow *
st_shadow_new (ClutterColor *color,
gdouble xoffset,
gdouble yoffset,
gdouble blur)
{
StShadow *shadow;
shadow = g_slice_new (StShadow);
shadow->color = *color;
shadow->xoffset = xoffset;
shadow->yoffset = yoffset;
shadow->blur = blur;
return shadow;
}
/**
* st_shadow_copy:
* @shadow: a #StShadow
*
* Makes a copy of @shadow.
*
* Returns: an allocated copy of @shadow - the result must be freed with
* st_shadow_free() when done
*/
StShadow *
st_shadow_copy (const StShadow *shadow)
{
g_return_val_if_fail (shadow != NULL, NULL);
return g_slice_dup (StShadow, shadow);
}
/**
* st_shadow_free:
* @shadow: a #StShadow
*
* Frees the shadow structure created with st_shadow_new() or
* st_shadow_copy()
*/
void
st_shadow_free (StShadow *shadow)
{
g_return_if_fail (shadow != NULL);
g_slice_free (StShadow, shadow);
}
GType
st_shadow_get_type (void)
{
static GType _st_shadow_type = 0;
if (G_UNLIKELY (_st_shadow_type == 0))
_st_shadow_type =
g_boxed_type_register_static ("StShadow",
(GBoxedCopyFunc) st_shadow_copy,
(GBoxedFreeFunc) st_shadow_free);
return _st_shadow_type;
}

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