Compare commits

...

230 Commits

Author SHA1 Message Date
87ce301faa Handle changes in window position for workspace thumbnails
Connect to the 'position-set' signal of MetaWindowActor and move
actors when the source windows move.
2011-02-02 23:45:57 -05:00
1ab526dc64 Improve workspace controls slide-in positioning
Intead of using a St.Group and tweening the position of the controls
actor, use a St.GenericLayout and tween a Javascript property. This
allows us to more reliably track the height of the overall workspace
display and propagate it to the controls actor.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:57 -05:00
c11162f794 Don't switch to a workspace when dragging it to launch on that workspace
With workspace thumbnails, we don't switch workspaces when dragging windows
between workspaces or adding new workspaces, so we also shouldn't switch
on launch.

 * Add workspace parameters to shell_doc_system_open(),
   shell_app_activate, shell_app_open_new_window()

 * Pass a 'params' object when activating items in the overview with
   two currently defined parameters: workspace and timestamp. (timestamp
   is only implemented where it is easy and doesn't require interface
   changes - using the global current timestamp for the shell is almost
   always right or at least good enough.)

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:57 -05:00
8e5d613bfa Avoid popping the workspace controls in and out at the end of DND
At the end of a drag operation, we would invoke the code to slide the
controls in (because we were no longer DND'ing and not hovering) and
then immediately afterwards invoke the code to slide it back out when
we got the ENTER event from the end of DND. While the immediately
overridden tween probably won't have any visible effect it's better
to avoid this, so wait to update the zoom state until BEFORE_REDRAW.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:57 -05:00
8786da0044 Remove now unnecessary workspace controls
With automatic workspace management, explicit controls to add and
remove workspaces are no longer necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:57 -05:00
3d5cb0f30a Add automatic workspace management
Automatically add and remove workspaces so that the last workspace is
always empty and no workspaces are empty other than that workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:56 -05:00
fb28f77c85 Don't activate newly added workspaces
With workspace thumbnails, we want to make workspace switching
something that happens largely under the users control, so don't
switch to newly added workspaces in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:56 -05:00
58c8006f1f Add workspace thumbnails to the overview
Add workspace thumbnails to the workspace controls area. The user can
click on the thumbnail to switch workspaces and can also drag windows
out of the thumbnail to other workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:56 -05:00
277cff3013 Move restacking handling from WorkspacesView to WorkspacesDisplay
Moving the base tracking of restacking to WorkspacesDisplay will allow
us to use it to update stacking in the workspace thumbnails as well as
in the main workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:56 -05:00
cde3ce2e27 Use a single "zoomed out" view for both workspace controls hover and DND
Instead of having a separation between popping the controls out on hover
and zooming out for DND, always do both at once. This is necessary because
when we added workspace thumbnails the controls will get bigger, so we need
to make sure we zoom out far enough so that the windows don't overlap the
controls.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:45:54 -05:00
57a4ad2d00 Don't check for Workspaces.WindowClone for window drops
When checking the type of a DND source, instead of checking
'instanceof Workspaces.WindowClone' accept any actor with realWindow
and metaWindow properties. This will be useful to support a separate
type of actor dragged from workspace thumbnails.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:42:46 -05:00
8bc0caa21b Remove workspace indicators
Once we have workspace thumbnails in the overview, workspace indicators
will no longer be needed.

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:42:43 -05:00
ae478c2344 Switch to a vertical layout for workspaces
The new plans for a row of workspace thumbnails on the right side of the
overview means that the mental model we present to the user will be
vertical, so switch the Metacity workspace layout to be vertical and
adjust the keybinding handling, animations, and workspace layout in
the overview to match.

(This commit does not change the workspace switching indicator pending
finalization of what we want to do with that - it still shows workspaces
arranged vertically.)

https://bugzilla.gnome.org/show_bug.cgi?id=640996
2011-02-02 23:42:01 -05:00
0dfdc9371e Fix hover state after DND
During a drag-and-drop, our pointer grab keeps enter/leave events from
being delivered. That means that after the DND ends, whatever actor is
under the pointer won't have received the enter event it should have,
and any state or hover effect dependent on that won't work right.
By remembering the first-leave and last-enter events we can figure out
what widgets we need to call st_widget_sync_hover() on after the drag.

https://bugzilla.gnome.org/show_bug.cgi?id=640974
2011-02-02 23:42:01 -05:00
ac92d0678b update Punjabi Translation by A S Alam 2011-02-03 08:27:11 +05:30
bd9e6a3bdf Updated Norwegian bokmål translation. 2011-02-02 20:34:34 +01:00
2ce93ce39e l10n: add new calendar to POTFILES.in 2011-02-02 13:03:19 +01:00
5b95ccae5f boxpointer: fix multi monitor support
https://bugzilla.gnome.org/show_bug.cgi?id=641195
2011-02-02 02:37:43 +03:00
0310f07eab modalDialog: remove old actions from _actionKeys in setButtons
https://bugzilla.gnome.org/show_bug.cgi?id=640781
2011-02-01 23:41:28 +03:00
e3acaa05be Remove st_container_remove_all & rewrite st_container_destroy_children
1. Both functions leaked the nodes in priv->children
2. st_container_remove_all wasn't properly updating first_child and last_child
3. remove_all() is almost never right since it won't cause signal handlers
   on the children to be removed. In the rare cases where it might be needed
   the caller can simply use clutter_container_remove().
https://bugzilla.gnome.org/show_bug.cgi?id=640781
2011-02-01 23:41:21 +03:00
91d8a32f25 workspace: make WindowClone forward the 'size-changed' event
https://bugzilla.gnome.org/show_bug.cgi?id=640781
2011-02-01 23:41:16 +03:00
457c7adf59 workspacesView: dispose _scrollAdjustment in _onDestroy
https://bugzilla.gnome.org/show_bug.cgi?id=640781
2011-02-01 23:41:11 +03:00
8ebdb7f493 workspacesView: remove duplicate connection to same signal 2011-02-01 23:41:05 +03:00
6c55ca59b0 Group chat sources on the left in the message tray
This will make it easier for users to get back to their chats.

https://bugzilla.gnome.org/show_bug.cgi?id=617234
2011-02-01 15:29:14 -05:00
0e4a47c0aa Enables navigation using arrow keys in notifications with buttons.
Users can now use the keyboard and mouse to navigate with buttons
interchangeably, instead of entirely using only mouse.

https://bugzilla.gnome.org/show_bug.cgi?id=630937
2011-02-01 15:12:00 -05:00
33100cd204 Bump version to 2.91.6 2011-02-01 14:08:29 -05:00
39a8243f27 [l10n] Updated Estonian translation 2011-02-01 19:35:37 +02:00
5f50922d32 Build: Correct version numbers for eds-3.0/1.2
The respective version numbers got swapped in commit 703092f.
2011-02-01 16:37:17 +01:00
1137ca0fce main.js: fix variable naming style for css_stylesheet
Change css_stylesheet to cssStylesheet in various places.
2011-02-01 10:13:35 -05:00
36f3429ad2 Better API for extensions changing CSS
Rename the setter to reflect the fact that it's the stylesheet which is
changing

Add a getter to allow some useful checks
2011-02-01 10:13:35 -05:00
703092f2c9 build: Default to libedataserverui-3.0 instead of 1.2
The official GNOME moduleset builds evolution and e-d-s against
GTK+-3, so libedataserverui-1.2 is no longer part of the release.
As GNOME Shell can actually be build with either version, prefer
libedataserverui-3.0 if it is available and allow falling back
to 1.2. if it isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=641085
2011-02-01 16:12:11 +01:00
fd75c7c7b4 Add an alternate bubble arrow drawing
When the bubble is near the screen border, draw a half arrow at the
corner of the bubble.

https://bugzilla.gnome.org/show_bug.cgi?id=639979
2011-02-01 10:07:05 -05:00
8abbd5dacb tray: Fix handling of SYSTEM_TRAY_CANCEL_MESSAGE
We were not looking at the right field for the message ID: the ID is in
the 4th field for BEGIN_MESSAGE, but 2nd field for CANCEL_MESSAGE.
2011-02-01 12:13:47 +01:00
ed0fa7e1b7 tray: Stop using gdk_display_add_client_message_filter()
It just got removed in GTK+ 3, and we actually don't need it since we
look for ClientMessage in na_tray_manager_window_filter() anyway.
2011-02-01 12:13:12 +01:00
15f1245927 Updating Galician translations 2011-02-01 02:45:13 +01:00
25434e42d0 calendar: Fix grid non-US week layouts
http://people.freedesktop.org/~david/calendar-grid-non-US-locale-collapse-bug.png

This was discovered when working on bug 641049:

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

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 15:53:56 -05:00
d6749589e8 calendar: Fix event list for week starts other than Sunday
In non-US locales, Monday is generally considered the first day
of the week. Take this into account when building the event
lists displayed under "This week"/"Next week".

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

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 15:47:05 -05:00
8fea88879a calendar: Fix prev/next buttons to not skip months
When the current day does not exist in the next/prev month (like 31 Feb),
the next/prev buttons end up skipping the month.

Fix that by going to the last day of the month instead.

https://bugzilla.gnome.org/show_bug.cgi?id=641067
2011-01-31 21:31:17 +01:00
d9e778f501 Calendar: Fix UTC/local mixup
See https://bugzilla.gnome.org/show_bug.cgi?id=632109#c56

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 11:52:27 -05:00
885b6ffaef Calendar: Implement new mockup
https://bugzilla.gnome.org/show_bug.cgi?id=632109

Signed-off-by: David Zeuthen <davidz@redhat.com>
2011-01-31 11:52:27 -05:00
4c64920f45 build: Remove gtk-theme-engine-clearlooks
The default engine is now Adwaita in gnome-themes-standard, so
remove it from the moduleset. It has already been removed from the
gnome-suites-core-3.0 set.
2011-01-31 16:08:59 +01:00
7369ea6125 Make sure we only emit 'destroy' for a notification once
There are multiple code passes that can result in Notification::destroy()
being called, such as a notification being closed by the application
when it exits and the associated source being removed at the same time.
However, we should only emit 'destroy' for the notification and
do the associated work once.
2011-01-30 18:53:19 -05:00
20b7d34577 Avoid passing 'source' as an argument to Notification::destroy()
Notification::destroy() now takes 'reason' as an optional argument.
Calling Notification::destroy() directly when connecting to 'destroy'
on Source, as we did before, was inadvertently passing 'source' as an
argument to the function.

https://bugzilla.gnome.org/show_bug.cgi?id=640976
2011-01-30 18:53:07 -05:00
6cc4c33b13 Updated Hebrew translation. 2011-01-30 23:04:00 +02:00
5abf9a0425 Add an API to allow extension to set a theme
Add a setTheme function to Main that allows to set a CSS stylesheet
which overrides the GNOME Shell default one

https://bugzilla.gnome.org/show_bug.cgi?id=630428
2011-01-30 16:01:15 -05:00
17a0b27109 appSwitcher: Use shorter icon hover timeout
Using a timeout of 750ms seems to be too long,
a shorter one like 200ms still solves the original problem
without getting in the way of other uses.
2011-01-30 20:29:27 +01:00
2bcdae4d5d Include new GTK+ header for X11 extensions
Due to recent GTK+ changes X11 specific code was moved into different
headers. As Socket/Plug is X11 only this broke our calls to GtkSocket
in the tray code. Fix this by including the new gtkx.h header.
2011-01-30 13:53:03 -05:00
0244c6d5b8 Revert "KeyboardStatus: handle modifier key indicators"
The 'show-keyboard-leds-indicator' key has been removed from
the schema.

This reverts commit 20f49e8c89.
2011-01-29 19:34:12 +01:00
bc6be40fdd Updated Italian translation 2011-01-29 16:07:10 +01:00
8c22b58611 update Punjabi Translation by A S Alam 2011-01-29 07:42:22 +05:30
074fe3ea70 Updated Spanish translation 2011-01-28 19:50:02 +01:00
5666fdefce Add a missing colon
Fixes a syntax error.
2011-01-28 13:31:16 -05:00
e9613b0340 Emit NotificationClosed for a notification iff we destroy it
This fixes emitting NotificationClosed for resident notifications
that are clicked, but are not actually destroyed.

This also ensures that we emit NotificationClosed in all cases when
a notification is destroyed, which can happen when:
- a non-resident notification is clicked
- an action is invoked on a non-resident notification
- an application the notification was associated with is focused
- a transient notification is done showing
- a notification was requested to be closed by the application
- a tray icon the notification was associated with is removed

https://bugzilla.gnome.org/show_bug.cgi?id=638071
2011-01-28 13:02:20 -05:00
8a030e8fc4 Mark lock indicator icons as keyboard ones
Those 3 possible status icons from gnome-settings-daemon should
not be showing up in gnome-shell, as they already have native versions.
2011-01-28 01:47:38 +00:00
9c23bf02bd Prevent a11y-kdb status icon from showing 2011-01-28 01:47:15 +00:00
8468fe87eb gnome-settings-daemon's xrandr icon went away
There's no xrandr icon in gnome-settings-daemon any more.
2011-01-28 01:19:01 +00:00
9617e83d88 run-dialog: Center error message vertically
Commit 912a30c56 left error message and icon aligned to the top,
but it looks better when the message is centered vertically.
2011-01-27 22:05:46 +01:00
912a30c566 Clean up the presentation of errors in the run dialog
Removes redundant text, better icon, and shows are better error when
a command isn't found than "No such file or directory".
2011-01-27 15:46:03 -05:00
2cd84da835 desktop-file: Remove "Utility" from categories
GNOME Shell is a core component of the desktop rather than a
utility, so adjust the desktop file to reflect that.

https://bugzilla.gnome.org/show_bug.cgi?id=640688
2011-01-27 11:37:39 +01:00
64fad9a394 QA of Galician translations 2011-01-27 03:33:43 +01:00
3b797b32bc Bump required clutter version to 1.5.15
This is required for Clutter.BindCoordinate.POSITION
2011-01-26 20:46:46 +01:00
f6ae48ec70 XDND: Use only one constraint for the cursor window position
ClutterBindConstraint now supports POSITION, so use that instead
of separate X and Y constraints.
2011-01-26 20:41:26 +01:00
61869d7db1 Unselect search button if there is search result
https://bugzilla.gnome.org/show_bug.cgi?id=640464
2011-01-26 04:38:18 +03:00
e2e90a550e Overview: Adjust to window size changes
Windows may change their size while the overview is open, e.g. when
switching panels in the control center. Make sure that the preview's
position and overlay are updated in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=640560
2011-01-25 21:53:33 +01:00
80ceead18d Updated Norwegian bokmål translation. 2011-01-25 20:47:57 +01:00
ed8884e192 [l10n] Updated Estonian translation 2011-01-25 20:41:22 +02:00
3f6165799f gs-menu: Do not exclude "Core" category
With the current rule set, we exclude applications in the "Core"
category - this includes Nautilus, which we want to show up at
least until "Finding and Reminding" is implemented, so remove
the exclude rule for now.
2011-01-25 19:39:58 +01:00
d2a40d6885 appSwitcher: Make sure we don't leave a stale timeout handler 2011-01-25 15:32:43 +01:00
eb8fc738af swipe-scrolling: Take threshold into account during drag
On button-release, a threshold is used to determine if the gesture
should be considered a click and thus ignored. While the drag is
active though, the controlled actor is dragged immediately. As a
result, dragging by a tiny amount does not trigger a snap back when
the action is interpreted as a click. As a fix, do not update the
dragged actor's position until the same threshold is passed.

https://bugzilla.gnome.org/show_bug.cgi?id=640494
2011-01-25 10:31:52 +01:00
b9e1d917da swipe-scroll: Don't eat button-release events on click
The main overview group starts capturing events on button-press
events to implement swipe-scrolling. While reactive children of
the group which handle both button-press and button-release events
don't trigger swipe-scrolling, children that only rely on
button-release have stopped working - at least the primary/secondary
icons of the search entry are affected. While the capture handler
already checks the pointer movement between press and release to
determine whether the action should be considered a click rather
than a drag, it still blocks the release event from propagating.
Instead, only block release events for drag actions, but not for
clicks.

https://bugzilla.gnome.org/show_bug.cgi?id=640493
2011-01-25 10:31:52 +01:00
f721e80685 Modifying Colin Walters UID. (cwalters to walters) into gnome-shell.doap.
This was causing some 'no route to host' mail sent to RT. AndreaVeri on
behalf of the AccountsTeam
2011-01-25 00:06:58 +01:00
361a115729 recorder: Call cairo_surface_mark_dirty on the cursor surface
Cairo surfaces have to be marked dirty after directly accessing
them.

This fixes the problem of the cursor not being in the recordings.
2011-01-24 23:03:59 +01:00
d107b84be4 view-selector: Prelight view titles on hover
The titles are clickable, indicate this to the user by prelighting
them on hover.
2011-01-24 20:36:25 +01:00
4cb967f3ac shell-app-usage: fix tracking code
We were checking if the app was running, but then marking it as
recently-seen either way. Fix it to only update it when the app is
running.

https://bugzilla.gnome.org/show_bug.cgi?id=640447
2011-01-24 13:35:03 -05:00
6f070319a0 shell-doc-system: fix %-escaping code in shell_doc_system_open()
It was escaping app_exec into app_exec_quoted, but then forgot about
it and went back to using app_exec.

https://bugzilla.gnome.org/show_bug.cgi?id=640447
2011-01-24 13:35:03 -05:00
13edecde6c Remove set-but-unused variables, to appease gcc 4.6
https://bugzilla.gnome.org/show_bug.cgi?id=640447
2011-01-24 13:35:03 -05:00
75d1230dd1 AppSwitcher: Delay activating appIcons when the thumbnail list is open
When aiming for the thumbnails with the mouse one might cross an
icon by accident which causes the thumbnail list to be closed, which is
frustrating.

Fix this by delaying the icon activation when the thumbnail list is
open.

https://bugzilla.gnome.org/show_bug.cgi?id=636650
2011-01-24 19:33:22 +01:00
779d5462f2 StThemeDrawing: clip background to border
Previously, trying to use a background image and border on
the same node resulted in the background drawing over the border.

This commit adds support for background images to

st_theme_node_render_background_with_border

and changes the code to call that function when appropriate.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
03757c1fcb st-private: add cairo code for drawing shadow
This does the same thing as the cogl equivalent
code, but for handling fallbacks.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
1faee65a68 st-private: split pixel blurring code out
The guts are somewhat complicated, and
are potentially reusable for future cairo
fallback code.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
f7ab90b93b StTextureCache: add api to load image to cairo surface
Loading a pixbuf in a way that cairo can use it is a
pretty involved process that involves a lot of code, and pixel
fiddling.

This commit adds the mechanism to StTextureCache so we can reuse
the existing pixbuf handling code there, and also get caching.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
a7fa7d748d StThemeNodeDrawing: generalize render_gradient to render_background_with_border
A lot of the border drawing logic in st_theme_node_render_gradient is
applicable to other non-solid background types than gradients.

This commit refactors that code so that support for other non-solid
background types can be more easily integrated later.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
2b6d4ff279 StThemeNodeDrawing: clip background image shadow to outline
When drawing the background image shadow, we need to clip it
to the node's background color, gradient, or borders if present.

If the background color is transparent, and there aren't any
borders, then we don't clip the shadow since there is nothing
to confine it.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
06cea89dae StThemeNodeDrawing: clip background image to node allocation
When drawing the background image, we need to make sure
we don't draw outside the bounding rectangle of the node.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
260ca64e94 StThemeNode: Don't make border images and gradients mutually exclusive
Since we no longer use the same material for both purposes,
we can now remove the restriction that they are mutually exclusive.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
6dc4adfc13 StThemeNode: split border_texture into two vars
The border_texture (and border_material) variable is being
overloaded for two purposes: it's used as a source
to 9-slice the border from, and it's used as place to prerender
the background and border together for gradients.

While we only do one or the other for any given node, the two cases
are distinct, and should use distinct variables for readability.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
e727c184ef StThemeNode: Split -st-shadow into three attributes
Currently, "-st-shadow" can mean one of three very
different things:

1) shadow based on alpha of the background image
2) shadow the "border box" of the node
3) shadow applied to the content of a StIcon

It isn't well defined which of the above 3 cases
-st-shadow will mean for any given node, however.

This commit splits the property into three
different properties, "box-shadow",
"-st-background-image-shadow", and "icon-shadow"
to make it all very explicit.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
412c50b939 tests: showcase borders with non-solid backgrounds
This commit adds a few more examples to borders.js
that render borders with various combinations of
gradients, background images, shadows, and
border-images.

https://bugzilla.gnome.org/show_bug.cgi?id=636976
2011-01-24 12:23:11 -05:00
8dcd70edbe St: Use clutter_actor_get_request_mode
Use clutter_actor_get_request_mode rather than g_object_get
since we have it in the required clutter version.

https://bugzilla.gnome.org/show_bug.cgi?id=640415
2011-01-24 14:41:52 +01:00
1b383c7285 search-display: Enable swipe scrolling
If a search gives many results from various providers, the result
area will be scrollable, so enable swipe-scrolling here as well.

https://bugzilla.gnome.org/show_bug.cgi?id=635034
2011-01-24 02:59:46 +01:00
e96a90b161 app-display: Enable swipe-scrolling in the app view
With general support for swipe-scrolling in the overview, there is
no reason to limit the behavior to workspaces. It is equally useful
for scrolling through the grid of available applications, so enable
swipe-scrolling for the app view.

https://bugzilla.gnome.org/show_bug.cgi?id=635034
2011-01-24 02:59:46 +01:00
d64d491f63 workspaces-view: Use overview swipe-scrolling
Remove the swipe-scrolling implementation in WorkspacesView and
use the new overview facility.

https://bugzilla.gnome.org/show_bug.cgi?id=635034
2011-01-24 02:59:39 +01:00
a6da22fa70 overview: Add a facility for swipe-scrolling
The workspaces view allows to drag the active workspace to swipe-scroll
to the next or previous workspace. While this behavior can come in handy
in general, there are good reasons to move the functionality to the
overview:

 - Finding a spot on a workspace to start a drag can be hard,
   especially when the workspace contains a single window
 - With the new layout, workspaces have no visible border, making
   it hard to predict where a drag can be initiated
 - The same behavior is equally useful for other elements

So add setScrollAdjustment() to the overview, which allows setting
an adjustment controlled with swipe-scrolling (either horizontally
or vertically); only a single adjustment can be controlled at a
time. A swipe-scroll can be initiated on any part of the background that
is not occupied by a reactive actor. For cases where further control
is needed, 'swipe-scroll-start' and 'swipe-scroll-end' signals are
emitted.

https://bugzilla.gnome.org/show_bug.cgi?id=635034
2011-01-24 02:59:32 +01:00
56cf7a6628 Updated Arabic translation 2011-01-23 13:29:55 +02:00
5b71788a84 Updated Hebrew translation. 2011-01-23 02:43:13 +02:00
39f7aa8457 Updated Spanish translation 2011-01-22 16:41:46 +01:00
c6baee2622 recorder: Switch to webm
The vp8 codec provides better performance in pretty much all cases compared
to theora while still being free (as in not patent encumbered).

Also add a %T placeholder to the pipeline string which will be replaced
with the a thread count based on the target system.

https://bugzilla.gnome.org/show_bug.cgi?id=632595
2011-01-21 19:46:38 +01:00
20f49e8c89 KeyboardStatus: handle modifier key indicators
Introduce a generic framework for on/off indicators that are shown
in the panel, next to the system status area, and use it for
showing the status of modifier keys.

https://bugzilla.gnome.org/show_bug.cgi?id=600771
2011-01-21 19:38:30 +01:00
d6a6e6220a recorder: Force full stage redraws during recording
Partial redraws can result into artifacts in the recording,
so disable them while recording.

https://bugzilla.gnome.org/show_bug.cgi?id=640206
2011-01-21 19:10:31 +01:00
3b333c37fd Updated Italian translation 2011-01-21 01:18:36 +01:00
289d577bc1 st: Report correct paint volumes during transitions
StWidget reports a paint volume large enough to paint the current
theme node. As CSS transitions also paint the previous theme node,
the reported paint volume may be incorrect, resulting in screen
artifacts when painting outside the reported volume.

Add st_theme_node_transition_get_paint_box() to calculate an allocation
large enough to paint both theme nodes, and use it to report the correct
paint volume during transitions.

https://bugzilla.gnome.org/show_bug.cgi?id=640085
2011-01-20 23:24:41 +01:00
00ba937171 StScrollView: Implement real fade effect
Implement an edge fade effect (top/bottom) using a
ClutterOffscreenEffect subclass, replacing the former
shadow hack.

https://bugzilla.gnome.org/show_bug.cgi?id=639460
2011-01-20 20:53:20 +01:00
df3560143d overview: Always return a value in _onDragMotion()
Drag monitor functions are supposed to return a value, but
_onDragMotion() does not always do so. Add the missing return
value and remove unnecessary else.
2011-01-20 17:04:38 +01:00
bdeb20f7c9 open-search-system: Remove unused parameter
Remove the 'title' parameter from the OpenSearchSystem constructor,
as the prototype's _init() method does not use it.
2011-01-20 17:04:37 +01:00
1dd35b7d08 environment: Fix runtime crash due to GTK+ change
As Gdk.Device.get_state() does not work properly from Javascript,
we used to block it in the environment. The method now has been
annotated with (skip), causing shell to crash on startup as only
existing methods may be blocked.
Just remove the block in question, as the annotation prevents the
use of that method anyway.
2011-01-20 16:44:16 +01:00
450291b856 Adding StLabel a11y support
Right now is just redefine atk_object_get_name.

If someone wonders why not implement AtkText interface, or expose the
internal ClutterText, here a extract from AtkText doc:

"AtkText should be implemented by AtkObjects on behalf of widgets that
have text content which is either attributed or otherwise
non-trivial. AtkObjects whose text content is simple, unattributed,
and very brief may expose that content via atk_object_get_name
instead;"

StLabel is attributed, but is still simple and brief. In the same way
the atk_object_get_name redefinition is required, so this patch is the
first step. We can implement AtkText in the future.

https://bugzilla.gnome.org/show_bug.cgi?id=626658
2011-01-20 13:02:14 +01:00
125adb4d32 StWidgetAccessible: accessibility support for StWidget
It includes:

 * Expose a proper focusable state, instead of the default one from
   cally, using StWidget::can_focus, and also notifying the state change

 * Management of the selected stated, using the current pseudo_class.

 * Defines a new virtual method on StWidget: get_accessible_type. In
   this way it is not required to reimplement get_accessible just for
   a accessible type change. get_accessible is reimplemented using this.
   You can see that as a substitute of the atk object factory

https://bugzilla.gnome.org/show_bug.cgi?id=636716
2011-01-20 12:56:46 +01:00
13cc58937e Added a11y initialization code
This basically:
  * Checks a11y configuration properties
  * Checks if clutter has a11y enabled
  * Loads atk-bridge

It also ensure proper NO_GAIL and NO_AT_BRIDGE values on gnome-shell
startup script

https://bugzilla.gnome.org/show_bug.cgi?id=612599
2011-01-20 12:56:36 +01:00
ee6a852996 XDND: Don't reset switch timeout when pointer is over the same window
Currently we reset the timeout on every mouse movement which means
the user has to keep the mouse at the exact same position for 1.25
seconds.

Be more tolerant and allow the user to move the mouse over the
window without reseting the timeout, which should make activating
windows easier.

https://bugzilla.gnome.org/show_bug.cgi?id=638896
2011-01-20 09:57:50 +01:00
2cfe978e1f Updated Arabic translation 2011-01-19 22:47:57 +02:00
0625655456 Updated Arabic translation 2011-01-19 22:40:24 +02:00
39a1f5cfe0 Updated Spanish translation 2011-01-19 20:27:21 +01:00
961fdd861f Hard code Cantarell as the default UI font.
- specify an overall font-family for all children of the stage and
  for places where we just want to use a size, use font-size.
- also shrink the humongous 16px panel and menu size to a reasonable 14.
- scale up the icons to be 16px by default again

Based on a patch by Jakub Steiner <jimmac@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=634226
2011-01-19 11:54:03 -05:00
28adc03cce StIcon: round icon size to an integer
Instead of converting a CSS-specified length to an integer by truncation,
round. This means that sizes specified by converting a pixel value into
non-px terms will work reliably instead of potentially being off-by-one.
2011-01-19 11:54:03 -05:00
68c482ec32 notification: be compatible with various names of the icon data hint
The hint changed its name during various iterations of the
notification daemon spec; be compatible with all of them.

https://bugzilla.gnome.org/show_bug.cgi?id=639959
2011-01-19 17:31:23 +01:00
a739f89dd1 texture-cache: add a missing array annotation 2011-01-19 16:43:50 +01:00
5c7042cff3 Updated Galician translations 2011-01-19 15:01:58 +01:00
255d4634a9 util: Fix regex used to match for URLs
Commit a65a0f03d4 changed the literal RegExp to a string-based
RegExp(). As backslashes are treated specially inside strings,
translating an expression as /\s/ to '\s' results in a faulty
regex of /s/, so escape backslashes where necessary.
https://bugzilla.gnome.org/show_bug.cgi?id=639914
2011-01-19 05:06:53 +03:00
cb4c2ab824 Don't reset y position of expanded notifications when updating them
This fixes the problem of chat notifications collapsing and then expanding
again when receiving multiple messages in the expanded new notification.

https://bugzilla.gnome.org/show_bug.cgi?id=629557
2011-01-18 15:08:46 -05:00
4c449124ee windowManager: Skip disposed windows in _switchWorkspaceDone
Avoid reparenting already disposed windows.

https://bugzilla.gnome.org/show_bug.cgi?id=639853
2011-01-18 19:35:01 +01:00
c74536c9b3 configure.ac: remove an old reference to Tidy 2011-01-18 11:49:09 -05:00
df10ef532f build: Add cups development package to dependencies
Needed by gnome-control-center.
2011-01-18 17:20:19 +01:00
6e18d18a81 Updated Hebrew translation. 2011-01-18 13:05:41 +02:00
4bc078b5fd StTextureCache: Fix compilation warning 2011-01-18 01:32:02 +03:00
cf49882e96 search: Use Util.spawn rather then Shell.Process
Shell.Process has been removed in favor of Util.spawn* so use that
instead.
2011-01-17 23:11:06 +01:00
b0c6cf3fc5 add ability to search in web from search view
It use OpenSearch to define the search engines.
https://bugzilla.gnome.org/show_bug.cgi?id=623708
2011-01-18 00:41:59 +03:00
883f51be93 runDialog: use fileUtils.listDirAsync in CommandCompleter
https://bugzilla.gnome.org/show_bug.cgi?id=623708
2011-01-18 00:41:50 +03:00
ad52d783bd places: Do not use nautilus' 'desktop-is-home-dir' setting
g_settings_schema_new() aborts if the requested schema is not found,
so the previous approach of handling the case of unstable nautilus
not being installed did not work.
Instead, remove the use of the setting altogether - the original intent
was to not have separate items for Desktop and Home in the places
section if the nautilus key was set. As the section has been removed
anyway, the impact of always adding the desktop folder is minimal
(e.g. searching for "desktop" will match the desktop folder even
if it's set to the home folder).
2011-01-17 21:05:13 +01:00
05f9be046f BluetoothStatus: add a separator above Settings menu entry
Close bug #639704
2011-01-17 21:02:03 +01:00
26aaecc33d places: Fail gracefully when not using unstable nautilus
The latest development version of nautilus has been ported to
GSettings, which we now use as well for the desktop-is-home-dir
preference. Obviously, the required schema is only available if
a recent enough nautilus version is installed. Instead of adding
yet another module to the moduleset, catch the exception and
ignore the preference in case the schema is not available.

https://bugzilla.gnome.org/show_bug.cgi?id=639689
2011-01-17 17:46:37 +01:00
f91138d0a2 places: Port to GSettings
'Places' follows the nautilus preference of whether the Desktop
should be a separate directory or the home folder should be used.
Nautilus has been ported to GSettings a while ago, so follow suit.

https://bugzilla.gnome.org/show_bug.cgi?id=639689
2011-01-17 15:54:24 +01:00
89d89ae1cf places: Remove obsolete code
The dash no longer contains a places section, so remove the now
unused code.

https://bugzilla.gnome.org/show_bug.cgi?id=639689
2011-01-17 10:33:28 +01:00
e67fbcdc79 Updated Spanish translation 2011-01-16 21:28:44 +01:00
f4572eedd0 altTab: Query the correct monitor's size
We always display the appSwitcher on the primary monitor,
so always query for its size rather than that of the focused
one.
2011-01-16 20:38:43 +01:00
988b515ad2 Updated Galician translations 2011-01-16 17:10:21 +01:00
2205a395e7 update for translation 2011-01-16 11:08:08 +05:30
108b582f0d [l10n] Updated Estonian translation 2011-01-16 10:20:20 +02:00
6ebd808e8b [Build] Bump vala to 0.11.4 2011-01-15 21:57:31 +01:00
343c1133f4 Updated Norwegian bokmål translation 2011-01-15 12:44:30 +01:00
fea2044eb8 Updated Greek translation 2011-01-15 11:51:02 +02:00
6b353ece82 [l10n] updated Italian translation 2011-01-15 01:22:47 +01:00
5b3f40102f kbd-status: s/Preferences/Settings in menu entry
In order to match similar menu entries from other menus.
2011-01-15 01:04:06 +01:00
b2ab3de80e [l10n] updates POTFILES.in 2011-01-15 00:59:43 +01:00
56f6c9c5f6 genericDisplay: Remove unused module
GenericDisplay used to provide a common base class for places and
recent items, none of which exists anymore. As of current mockups,
display items in "Finding and Reminding" should be based on
BaseIcon / IconGrid instead.
2011-01-14 22:30:02 +01:00
39b0c88c76 doc-display: Remove UI of the old dash display
Currently recent items only show up in search results. It is planned
to bring them back in the context of "Finding and Reminding", but
the UI in the corresponding mockups differs significantly from the
removed UI, so that it doesn't seem useful to keep it around.
2011-01-14 22:29:32 +01:00
1fca8a8b95 css: Remove places and recent items
They no longer exist so they should be removed from css as well.
2011-01-14 22:04:32 +01:00
d442494f3a Dash: Remove unused properties 2011-01-14 21:25:06 +01:00
1f1fe36b89 Updated Galician translations 2011-01-14 16:33:17 +01:00
d21f04b8b4 kbd-status: Close the menu when switching layouts
Layout items in the menu overwrite PopupBaseMenuItem.activate(),
so the menu stays open when selecting a layout from the menu.
Chain up to the parent class' method to make the items behave properly.

https://bugzilla.gnome.org/show_bug.cgi?id=639474
2011-01-14 07:18:39 +01:00
e73e4375b8 endSessionDialog: Add logout/shutdown dialog
This commit adds a dialog for gnome-session to
privately use when initiating log outs and shut
downs.

Coordination is done over the bus.

https://bugzilla.gnome.org/show_bug.cgi?id=637187
2011-01-14 00:11:17 -05:00
2905b0318d runDialog: animate to new height on error
When an error message is displayed the run dialog
pops to the new height instantly.  It needs a
a transition.

This commit makes the dialog quickly grow to its
ultimate height, making room for the error message,
before showing it.

https://bugzilla.gnome.org/show_bug.cgi?id=637187
2011-01-14 00:11:17 -05:00
ab1ecb5ba2 runDialog: subclass from modalDialog
Now that we have a modalDialog base class in gnome-shell,
it makes sense to use it for the run dialog.

Note, the run dialog doesn't currently have buttons, so
it isn't exercising all the API of the base class.

https://bugzilla.gnome.org/show_bug.cgi?id=637187
2011-01-14 00:11:17 -05:00
47b8d16067 modalDialog: Add modal dialog base class
This is a base class to make it easier to
gain a consistent look for system modal dialogs.

It handles creating a darkened backdrop behind the dialog, setting
up buttons in the dialog, keynav, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=637187
2011-01-14 00:11:10 -05:00
dc020628b5 main: add timestamp parameter to push/popModal
Right now popModal() passes global.get_current_time() for
its begin_modal() call.  global.get_current_time() is the
timestamp of the last gdk or clutter event processed by the
shell's mutter process.  These values could potentially be
be too stale to use if pushModal() were to get called in
response to an event by another process.

This commit changes pushModal() to have an optional timestamp
argument, which can be used to associate the call with the
event that initiated it.

https://bugzilla.gnome.org/show_bug.cgi?id=637187
2011-01-13 23:36:22 -05:00
bed063eea1 generic-container: Queue a redraw in skip_paint()
When changing a child's visibility with skip_paint(), the change
will not be visible until a redraw is triggered. Queue a redraw,
so that the function has an immediate effect.

https://bugzilla.gnome.org/show_bug.cgi?id=639461
2011-01-14 01:07:42 +01:00
ed76e52918 Revert "kbd-status: Close the menu when switching layouts"
This reverts commit e0f58c615b.

Pushed accidentally.
2011-01-14 01:06:49 +01:00
e0f58c615b kbd-status: Close the menu when switching layouts
Layout items in the menu overwrite PopupBaseMenuItem.activate(),
so the menu stays open when selecting a layout from the menu.
Chain up to the parent class' method to make the items behave properly.

https://bugzilla.gnome.org/show_bug.cgi?id=639474
2011-01-14 01:01:30 +01:00
a681a2ba02 Remove _onKeyPress() function in Notification
Its usage was removed in commit 4dd4c9f99f -
"Use more actor.grab_key_focus() and less stage.connect('key-press-event')".
2011-01-13 18:33:01 -05:00
856207c154 LookingGlass: fix a Clutter warning
After destroying an actor, it is no more parented anywhere, so we
cannot allocate it.

https://bugzilla.gnome.org/show_bug.cgi?id=633028
2011-01-13 22:55:20 +01:00
00d897f282 Require gjs 0.7.8
We use the js-version property, among other things.
2011-01-13 16:38:30 -05:00
49a09657c5 Updated Hebrew translation. 2011-01-13 23:23:16 +02:00
38fb51a99e app-display: Expose BaseIcon params in AppWellIcon
AppWellIcon is used both in the dash and view selector. As the dash
requires manual sizing, it is not possible to set the icon size used
in the view selector in the CSS, but icons will use the default size
(unless set manually as in the dash).

Expose the params parameter of BaseIcon and enable manual resizing
only for AppWellIcons in the dash.

https://bugzilla.gnome.org/show_bug.cgi?id=639428
2011-01-13 18:27:23 +01:00
99a865fb0f ShellApp: is_on_workspace() should be TRUE for workspaceless apps
If a starting-up app has not requested a particular workspace, then
shell_app_is_on_workspace() should return TRUE for any workspace.

Otherwise we will never get startup notification for them, since the
app menu only shows apps that are starting on the current workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:16:38 -05:00
b919dd7271 shell-app-system.h: clean up (indentation, order, etc)
https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:16:37 -05:00
9ddf19a1a4 shell: remove ShellProcess
ShellProcess only existed to work around gjs bugs that have long since
been fixed, and has now been obsoleted by Util.spawn*. Kill it.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:14:40 -05:00
23353fb77a Util.killall: add utility for killing unwanted processes
Since we have to use pkill, kludgily, for the right combination of
portability and featurefulness, put the code in one place rather than
duplicating it everywhere.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:14:40 -05:00
8bdfb8df68 util: add Util.spawn and friends
Add Util.spawn, Util.spawnCommandLine, and Util.spawnDesktop for
spawning a command/argv/.desktop file in the background, automatically
handling errors via MessageTray.SystemNotificationSource(), and
Util.trySpawn, Util.trySpawnCommandLine, and Utils.trySpawnDesktop
that don't do automatic error handling (but do at least clean up the
error message in the exception a bit).

Update various other bits of code around the shell to use the new
methods.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:14:40 -05:00
a65a0f03d4 util: rename from utils, avoid RegExp literal
Rename imports.misc.utils to imports.misc.util for more consistency
(eg, with shell-util).

Also, use the string-based RegExp() constructor rather than a RegExp
literal, since the literal is extremely difficult to parse correctly,
and confuses emacs and probably other editors and thus messes up
autoindentation, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:14:40 -05:00
7322a4e4ef messageTray: add SystemNotificationSource, moved from overview.js
Move the overview's "System Information" source here, so it can be
used by non-overview code as well.

https://bugzilla.gnome.org/show_bug.cgi?id=635089
2011-01-13 12:14:40 -05:00
870be026d8 Install a GDK event handler to catch events queued by IBus
With IBus, key events sometimes get sent to the server than
redelivered via gdk_event_put(). Since we expect all key events to
be delivered via the GDK event filter Mutter installs, this results
in key input not working.

To fix this, install an event handler with gdk_event_handler_set()
to intercept events being set from GDK to GTK+, pull out the
key events and send them back to Clutter.

Partially based on a patch by Daiki Ueno

https://bugzilla.gnome.org/show_bug.cgi?id=621659
2011-01-13 12:00:55 -05:00
e4fc899aca Require the latest g-i
Necessary for correct handling of (out caller-allocates) among
other things.
2011-01-12 16:33:01 -05:00
5412ce276c ExtensionSystem: introduce versioning
Require that all extensions have a "shell-version" property in their
metadata, which is an array of supported Shell versions.
Extensions can target a specific version triple or an entire stable
version.
Optionally, they can also require a specific GJS version, to ensure
compatibility.

https://bugzilla.gnome.org/show_bug.cgi?id=639255
2011-01-12 20:34:25 +01:00
6200daa5bb Propagate version to Javascript files
Add an entry in config.js.in for PACKAGE_VERSION and GJS_VERSION,
to be used by the notification daemon and in the future by the
extension system.

https://bugzilla.gnome.org/show_bug.cgi?id=639255
2011-01-12 20:32:30 +01:00
4207536377 Status Area: add keyboard layout selector
Add an indicator for the current keyboard layout, based on
libgnomekbd. The indicator is shown when more than one group
is loaded in X and it is not disabled in GSettings.

https://bugzilla.gnome.org/show_bug.cgi?id=600771
2011-01-12 20:27:25 +01:00
90e042e30c Updated Arabic translation 2011-01-12 11:29:54 +02:00
4e45e28ea0 shell: disable libgnome-bluetooth debug spew
Centralize all the debug-spew-disabling here, and add
libgnome-bluetooth to the list.

https://bugzilla.gnome.org/show_bug.cgi?id=639236
2011-01-11 19:06:55 -05:00
d7a19fdd1b Bump version to 2.91.5 2011-01-11 18:13:36 -05:00
428d2fdb76 gnome-shell-build-setup.sh: Add libgtop
Add libgtop, a new build dependency for gnome-control-center.
2011-01-11 18:10:08 -05:00
d77409876c Clean generated stamp-st.h 2011-01-11 18:05:08 -05:00
81714ce1a3 Notifications with CRITICAL urgency are no longer timed out
Notifications with CRITICAL urgency should not pop down until the user interacts with them.

https://bugzilla.gnome.org/show_bug.cgi?id=630942
2011-01-11 16:38:46 -05:00
6bae9ed20d gnome-shell.css: specify font size for overview view selector area
Previously this was inheriting the default size, which is specified in
pts, and so would make the text larger than its 16px containing box if
you have high DPI.

https://bugzilla.gnome.org/show_bug.cgi?id=639213
2011-01-11 09:18:15 -05:00
44f70646d3 main: clean up handling of metacity keybindings during grabs
Although certain keys (like Ctrl-Alt-Tab and Alt-F2) should work in
the overview, we generally don't want them to work from inside each
others grabs. In particular, typing Left or Right from inside
Ctrl-Alt-Tab should navigate among focus groups, not switch
workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=636971
2011-01-10 15:24:54 -05:00
ed83b5494c main: allow Alt-F1 to exit the overview
Also, change _globalKeyPressHandler to handle KEY_PRESS, not
KEY_RELEASE, for consistency with other code (and so that the
combination of an Alt-F1 press and release doesn't first enter the
overview and then immediately exit it).

https://bugzilla.gnome.org/show_bug.cgi?id=636371
2011-01-10 15:24:54 -05:00
84bac4414c ShellGtkEmbed: revert to old actor/window position-syncing code
Synchronizing the actor and window position on paint resulted in lots
of syncing, and also resulted in the window mistakenly being left at
0,0 if the actor wasn't visible when the window first mapped.

Revert back to the old way of doing it, by tying into
clutter_actor_allocate, which was only failing before because of a bug
elsewhere.

https://bugzilla.gnome.org/show_bug.cgi?id=635695
2011-01-10 15:22:50 -05:00
4c4a703e63 messageTray: use alignment rather than gravity to position the summary
Actors in clutter are supposed to be re-allocated with
Clutter.AllocationFlags.ABSOLUTE_ORIGIN_CHANGED if they move relative
to the screen, even if they don't move relative to their parent.
Currently this does not work correctly for actors inside containers
with non-northwest gravity. This is probably a fixable bug, but
gravity has messed up other things in the past too, so let's just not
use it.

This change ensures that summary trayicons are re-allocated when the
summary animates, and is part of the fix for
https://bugzilla.gnome.org/show_bug.cgi?id=635695
2011-01-10 15:22:50 -05:00
c08021d91f [l10n] Updated Estonian translation 2011-01-09 20:38:25 +02:00
df5ec16842 Updated Hebrew translation. 2011-01-09 18:51:03 +02:00
055a34877e Favorites: Refine default list
Change the default list to:

Firefox, Evolution, Empathy, Rhythmbox, Shotwell, OOWriter, Nautilus

https://bugzilla.gnome.org/show_bug.cgi?id=638990
2011-01-08 15:14:25 +01:00
a538027fe7 Translation: update Punjabi 2011-01-08 08:25:16 +05:30
77289737c5 Add an 'rt' command to the Run dialog to reload the theme
This should be useful for theme authors who want to quickly reload
the theme without restarting the whole shell.

Signed-off-by: Federico Mena Quintero <federico@gnome.org>

https://bugzilla.gnome.org/show_bug.cgi?id=630428
2011-01-07 15:21:48 -05:00
512798f9c6 Factor out a function to load the default theme
We will use this function elsewhere when the theme needs to be reloaded.

https://bugzilla.gnome.org/show_bug.cgi?id=630428
2011-01-07 15:21:48 -05:00
5322e9a643 notificationDaemon: Fix trayIcon check
Correctly detect non tray icons and use the ShellApp's icon in that case.
2011-01-07 16:24:44 +01:00
34f8568547 [l10n] Updated Estonian translation 2011-01-07 13:34:46 +02:00
66e0e5b370 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-01-07 09:44:17 +08:00
960af783f7 Updated galician translations 2011-01-06 23:33:55 +01:00
1a884535ad BluetoothStatus: fix typo
The function to hide a menu item is .actor.hide(), not just .hide()
2011-01-06 20:35:21 +01:00
b2bb0bf10f BluetoothStatus: hide the icon when no adapter is present
There is no point in showing the bluetooth status, when the required
hardware is missing. Just hide in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=638306
2011-01-06 19:54:28 +01:00
4de15b2b57 PopupMenuManager: only navigate visible menus
When doing keyboard navigation, ignore menus whose sourceActor is
hidden.
This is needed to hide status icons, as otherwise the menu would
appear despite having no icon.

https://bugzilla.gnome.org/show_bug.cgi?id=638306
2011-01-06 19:54:28 +01:00
493844d005 PopupMenu: fix addMenuItem with explicit position
Only real menu items should be considered, fix this using the new
API in StBoxLayout.

https://bugzilla.gnome.org/show_bug.cgi?id=637681
2011-01-06 19:50:53 +01:00
046308c582 StBoxLayout: add insert_before
Add st_container_move_before internal API, and
st_box_layout_insert_before, that inserts an actor before another
in the container.

https://bugzilla.gnome.org/show_bug.cgi?id=637681
2011-01-06 19:50:53 +01:00
cedcbc5fcf BluetoothStatus: hide the device separator if no devices are shown
When BluetoothApplet::show-full-menu property is notified (when you
switch from a disabled adapter / no adapter to an active one), we
would show all the menu, including the device separator, without
checking if any devices actually existed.

https://bugzilla.gnome.org/show_bug.cgi?id=637690
2011-01-06 19:48:28 +01:00
a46baeed0b altTab: fix destroy-without-showing case
If the switcher is destroyed without ever being fully shown (either
because it couldn't get a keyboard grab, or just because there are no
apps to display), destroy it immediately rather than tweening it
towards destruction, since its contents haven't been built yet and
_allocate() will throw errors if it runs.
2011-01-06 13:38:41 -05:00
cff503922c DashDND: Don't allow positioning before or after self
Don't allow the icon to be dropped immediately next to
itself.

https://bugzilla.gnome.org/show_bug.cgi?id=637104
2011-01-06 14:31:45 +01:00
ce2efc6a67 Overview: Change tab title style to match mockups
https://bugzilla.gnome.org/show_bug.cgi?id=638815
2011-01-06 14:08:43 +01:00
778aa6be09 Updated Spanish translation 2011-01-06 10:58:45 +01:00
0052657a22 Overview: Update warping code to new gdk api 2011-01-05 23:45:02 +01:00
f60b995236 Chats should jump to the top of the notification queue.
This is to ensure users get notified as soon as chats are received.
Notifications with critical urgency still have the highest priority.

https://bugzilla.gnome.org/show_bug.cgi?id=630934
2011-01-05 17:23:01 -05:00
ceedc7e32c Implement cross overview drag & drop
The gnome-panel allows the user to hover over a tasklist entry
while draging to activate a minimized or obscured window and drop onto it.

Implement a similar behaviour by allowing draging to the activities button or
the hotcorner (and thus opening the overview), which allows the user to
activate any window (even on different workspaces) as a drop target.

https://bugzilla.gnome.org/show_bug.cgi?id=601731
2011-01-05 23:19:56 +01:00
62507c9759 Add a facility to show the stage without grabbing
When the user is doing a drag-and-drop, we want to temporarily show the
stage to allow them to drag to a different window. But we're not "really"
in the overview, and getting a grab would conflict with the X client doing
the drag and drop.

So add a showTemporarily()/hideTemporarily() pair of methods that show
the overview without grabbing.

This adds a lot more possibilities for asynchronous race conditions, so
rework the code to be more robust against multiple calls to show*()
and hide*(). The interpretation is now that all calls to show*() and
hide*() affect the state, but if we have conflicting calls to show and
hide we wait until the current animation is finished before correcting
to the right visual state.

https://bugzilla.gnome.org/show_bug.cgi?id=601731
2011-01-05 23:19:51 +01:00
7beb7e0f65 gnome-shell.in: Really never add empty elements to LD_LIBRARY_PATH
This complements the fix from c6eb2761, to make sure that we don't use
the pre-existing $LD_LIBRARY_PATH if it's set but empty.

Both commits fix CVE-2010-4000.

https://bugzilla.gnome.org/show_bug.cgi?id=638728
2011-01-05 10:54:38 +01:00
ad67225bf8 Updated Norwegian bokmål translation 2011-01-04 19:43:32 +01:00
dd0f721694 calendar: Use AlignConstraint to center the popup
This fixes warnings like:

(mutter:12238): Clutter-WARNING **: The actor 'calendarPopup' is
currently inside an allocation cycle; calling clutter_actor_queue_relayout()
is not recommended

https://bugzilla.gnome.org/show_bug.cgi?id=637829
2011-01-04 17:20:16 +01:00
24f1e87813 clock: Use settings from gsettings-desktop-schemas
A key for 12hr/24hr clock format has been added to gsettings-desktop-schemas,
so use that instead of the one from the shell clock schema.

As the setting can be controlled from the Date and Time panel of
gnome-control-center now, drop the temporary preference dialog
as well.

https://bugzilla.gnome.org/show_bug.cgi?id=633200
2011-01-04 17:14:00 +01:00
68a0d7897f Build: stop updating timestamp of st.h when not needed
Use the same approach as other generated headers (a temporary file,
compare to the existing, then copy), to avoid touching st.h, so
that other dependent objects are not rebuilt, if not needed.
It should speed up building when switching git branches, as often
config.status or automake are run, causing Makefiles to be recreated.

https://bugzilla.gnome.org/show_bug.cgi?id=638453
2011-01-04 00:17:26 +01:00
d9d56b7492 [l10n] Updated Estonian translation 2011-01-02 20:24:26 +02:00
96a0b9d416 Updated Norwegian bokmål translation from Torstein Adolf Winterseth 2011-01-02 19:20:31 +01:00
d48f064636 [l10n] Updated German translation 2011-01-01 23:21:35 +01:00
4e0a1c1152 Updated Swedish translation 2010-12-31 12:58:28 +01:00
272cbc1485 Updated Swedish translation 2010-12-31 12:58:22 +01:00
0ba7188625 Remove Gtk 2 compatibility code
It is useless now that we require Gtk 3.

https://bugzilla.gnome.org/show_bug.cgi?id=638315
2010-12-30 21:36:37 +01:00
6a2f038515 Updated Vietnamese translation 2010-12-29 21:29:16 +07:00
9f04009f80 po/vi.po: import from Damned Lies 2010-12-29 21:26:17 +07:00
2763d8dcc1 Fix error from blocking removed Gdk.Display.get_device_state.
Gdk.Display.get_device_state() was removed in favor of a
non-GdkModifierType returning Gdk.Device.get_position(). But block
Gdk.Device.get_state() which does return a GdkModifierType mask.

https://bugzilla.gnome.org/show_bug.cgi?id=638158
2010-12-28 07:53:39 -05:00
f8eb881728 Update Punjabi Translation 2010-12-27 07:13:19 +05:30
0406b91bd5 Update Simlified Chinese translation. 2010-12-25 12:55:31 +00:00
e6678dadd8 Updated Spanish translation 2010-12-23 19:54:37 +01:00
a2fb8a8dce Added UG translation 2010-12-23 19:08:24 +01:00
5f212b1ae2 BluetoothStatus: update only devices that actually changed
When receiving a "devices-changed" signal from BluetoothApplet,
check if some device item corresponds to an existing one, destroy
the remaining and add the new ones.
With this patch, signal emission when no device actually changed
(which happen due to bluetoothd creating temporary devices) result
in a no-op.

https://bugzilla.gnome.org/show_bug.cgi?id=637690
2010-12-23 18:29:58 +01:00
23432e616d BluetoothStatus: move the sendto item to the bottom
Kill one separator by merging all global actions items at the end
of the menu, which ends up divided in three sections: status,
devices and actions.

https://bugzilla.gnome.org/show_bug.cgi?id=637690
2010-12-23 18:29:58 +01:00
7d44c666ff altTab: use 'selected' pseudo-style for selected item
This makes it consistent with other parts of the UI and will let the
a11y code use the rule "has_style_pseudo_class('selected') =>
ATK_STATE_SELECTED"

https://bugzilla.gnome.org/show_bug.cgi?id=637830
2010-12-23 09:50:40 -05:00
160 changed files with 19412 additions and 7478 deletions

5
.gitignore vendored
View File

@ -18,8 +18,6 @@ config
configure configure
data/gnome-shell.desktop data/gnome-shell.desktop
data/gnome-shell.desktop.in data/gnome-shell.desktop.in
data/gnome-shell-clock-preferences.desktop
data/gnome-shell-clock-preferences.desktop.in
data/gschemas.compiled data/gschemas.compiled
data/org.gnome.shell.gschema.xml data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid data/org.gnome.shell.gschema.valid
@ -46,12 +44,13 @@ src/Makefile
src/Makefile.in src/Makefile.in
src/gnomeshell-taskpanel src/gnomeshell-taskpanel
src/gnome-shell src/gnome-shell
src/gnome-shell-clock-preferences
src/run-js-test src/run-js-test
src/test-recorder src/test-recorder
src/test-recorder.ogg src/test-recorder.ogg
src/test-theme src/test-theme
src/st.h src/st.h
src/stamp-st.h
src/stamp-st.h.tmp
stamp-h1 stamp-h1
tests/run-test.sh tests/run-test.sh
xmldocs.make xmldocs.make

View File

@ -1,11 +1,14 @@
AC_PREREQ(2.63) AC_PREREQ(2.63)
AC_INIT([gnome-shell],[2.91.4],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell]) AC_INIT([gnome-shell],[2.91.6],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c]) AC_CONFIG_SRCDIR([src/shell-global.c])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config]) AC_CONFIG_AUX_DIR([config])
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign]) AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
@ -57,16 +60,21 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder) AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.5.8 CLUTTER_MIN_VERSION=1.5.15
GOBJECT_INTROSPECTION_MIN_VERSION=0.6.11 GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=0.7 GJS_MIN_VERSION=0.7.8
MUTTER_MIN_VERSION=2.91.4 MUTTER_MIN_VERSION=2.91.4
GTK_MIN_VERSION=2.91.7 GTK_MIN_VERSION=2.91.7
GIO_MIN_VERSION=2.25.9 GIO_MIN_VERSION=2.25.9
LIBECAL_REQUIRED=1.6.0
LIBEDATASERVER_REQUIRED=1.2.0
LIBEDATASERVERUI2_REQUIRED=1.2.0
LIBEDATASERVERUI3_REQUIRED=2.91.6
# Collect more than 20 libraries for a prize! # Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
gio-unix-2.0 dbus-glib-1 gio-unix-2.0 dbus-glib-1 libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION gtk+-3.0 >= $GTK_MIN_VERSION
mutter-plugins >= $MUTTER_MIN_VERSION mutter-plugins >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION gjs-internals-1.0 >= $GJS_MIN_VERSION
@ -78,6 +86,10 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
libcanberra) libcanberra)
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
saved_CFLAGS=$CFLAGS saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS saved_LIBS=$LIBS
CFLAGS=$MUTTER_PLUGIN_CFLAGS CFLAGS=$MUTTER_PLUGIN_CFLAGS
@ -87,7 +99,6 @@ AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
CFLAGS=$saved_CFLAGS CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS LIBS=$saved_LIBS
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0) PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0) PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
PKG_CHECK_MODULES(TRAY, gtk+-3.0) PKG_CHECK_MODULES(TRAY, gtk+-3.0)
@ -107,6 +118,16 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 2.90.0],
AC_SUBST([HAVE_BLUETOOTH],[0]) AC_SUBST([HAVE_BLUETOOTH],[0])
AC_MSG_RESULT([no])]) AC_MSG_RESULT([no])])
# Default to libedataserverui-3.0, but allow falling back to 1.2
PKG_CHECK_EXISTS(libedataserverui-3.0,
[EDS_API=3.0
LIBEDATASERVERUI_REQUIRED=$LIBEDATASERVERUI3_REQUIRED],
[EDS_API=1.2
LIBEDATASERVERUI_REQUIRED=$LIBEDATASERVERUI2_REQUIRED])
PKG_CHECK_MODULES(LIBECAL, libecal-1.2 >= $LIBECAL_REQUIRED libedataserver-1.2 >= $LIBEDATASERVER_REQUIRED libedataserverui-$EDS_API >= $LIBEDATASERVERUI_REQUIRED)
AC_SUBST(LIBECAL_CFLAGS)
AC_SUBST(LIBECAL_LIBS)
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
# FIXME: metacity-plugins.pc should point directly to its .gir file # FIXME: metacity-plugins.pc should point directly to its .gir file
MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins` MUTTER_LIB_DIR=`$PKG_CONFIG --variable=libdir mutter-plugins`

View File

@ -1,5 +1,5 @@
desktopdir=$(datadir)/applications desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop gnome-shell-clock-preferences.desktop desktop_DATA = gnome-shell.desktop
# We substitute in bindir so it works as an autostart # We substitute in bindir so it works as an autostart
# file when built in a non-system prefix # file when built in a non-system prefix
@ -12,7 +12,10 @@ desktop_DATA = gnome-shell.desktop gnome-shell-clock-preferences.desktop
%.desktop:%.desktop.in %.desktop:%.desktop.in
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@ $(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
dist_pkgdata_DATA = clock-preferences.ui searchprovidersdir = $(pkgdatadir)/search_providers
dist_searchproviders_DATA = \
search_providers/google.xml \
search_providers/wikipedia.xml
imagesdir = $(pkgdatadir)/images imagesdir = $(pkgdatadir)/images
dist_images_DATA = \ dist_images_DATA = \
@ -21,19 +24,18 @@ dist_images_DATA = \
themedir = $(pkgdatadir)/theme themedir = $(pkgdatadir)/theme
dist_theme_DATA = \ dist_theme_DATA = \
theme/add-workspace.svg \ theme/calendar-arrow-left.svg \
theme/calendar-arrow-right.svg \
theme/close-window.svg \ theme/close-window.svg \
theme/close.svg \ theme/close.svg \
theme/corner-ripple.png \ theme/corner-ripple.png \
theme/dash-placeholder.svg \ theme/dash-placeholder.svg \
theme/dialog-error.svg \
theme/filter-selected.svg \ theme/filter-selected.svg \
theme/gnome-shell.css \ theme/gnome-shell.css \
theme/mosaic-view-active.svg \ theme/mosaic-view-active.svg \
theme/mosaic-view.svg \ theme/mosaic-view.svg \
theme/move-window-on-new.svg \ theme/move-window-on-new.svg \
theme/process-working.png \ theme/process-working.png \
theme/remove-workspace.svg \
theme/running-indicator.svg \ theme/running-indicator.svg \
theme/scroll-button-down-hover.png \ theme/scroll-button-down-hover.png \
theme/scroll-button-down.png \ theme/scroll-button-down.png \
@ -88,7 +90,6 @@ install-data-local:
EXTRA_DIST = \ EXTRA_DIST = \
gnome-shell.desktop.in.in \ gnome-shell.desktop.in.in \
gnome-shell-clock-preferences.desktop.in.in \
$(menu_DATA) \ $(menu_DATA) \
$(gconfschema_DATA) \ $(gconfschema_DATA) \
$(shaders_DATA) \ $(shaders_DATA) \
@ -97,7 +98,6 @@ EXTRA_DIST = \
CLEANFILES = \ CLEANFILES = \
gnome-shell.desktop.in \ gnome-shell.desktop.in \
gnome-shell-clock-preferences.desktop.in \
$(desktop_DATA) \ $(desktop_DATA) \
$(gsettings_SCHEMAS) \ $(gsettings_SCHEMAS) \
gschemas.compiled gschemas.compiled

View File

@ -1,188 +0,0 @@
<?xml version="1.0"?>
<interface domain="gnome-shell">
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="prefs-dialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">Clock Preferences</property>
<property name="window_position">center</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="top_padding">6</property>
<property name="left_padding">12</property>
<property name="right_padding">6</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="spacing">12</property>
<child>
<object class="GtkRadioButton" id="12hr_radio">
<property name="label" translatable="yes">_12 hour format</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="24hr_radio">
<property name="label" translatable="yes">_24 hour format</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<property name="group">12hr_radio</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label_format">
<property name="visible">True</property>
<property name="label" translatable="yes">Clock Format</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="top_padding">6</property>
<property name="left_padding">12</property>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="date_check">
<property name="label" translatable="yes">Show the _date</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="seconds_check">
<property name="label" translatable="yes">Show seco_nds</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label_display">
<property name="visible">True</property>
<property name="label" translatable="yes">Panel Display</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="padding">6</property>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="prefs_close_button">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">prefs_close_button</action-widget>
</action-widgets>
</object>
</interface>

View File

@ -1,15 +0,0 @@
[Desktop Entry]
_Name=Clock
_Comment=Customize the panel clock
Exec=@bindir@/gnome-shell-clock-preferences
Icon=gnome-panel-clock
Terminal=false
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Settings;DesktopSettings;
OnlyShowIn=GNOME;
X-GNOME-ShellOnly=true
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@

View File

@ -7,7 +7,7 @@ X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@ X-GNOME-Bugzilla-Version=@VERSION@
Categories=GNOME;GTK;Utility;Core; Categories=GNOME;GTK;Core;
OnlyShowIn=GNOME; OnlyShowIn=GNOME;
NoDisplay=true NoDisplay=true
X-GNOME-Autostart-Phase=WindowManager X-GNOME-Autostart-Phase=WindowManager

View File

@ -77,10 +77,6 @@
<OnlyUnallocated/> <OnlyUnallocated/>
<Include> <Include>
<And> <And>
<Or>
<Category>Documentation</Category>
<Not><Category>Core</Category></Not>
</Or>
<Not><Category>Settings</Category></Not> <Not><Category>Settings</Category></Not>
<Not><Category>Screensaver</Category></Not> <Not><Category>Screensaver</Category></Not>
</And> </And>

View File

@ -30,13 +30,17 @@
</_description> </_description>
</key> </key>
<key name="favorite-apps" type="as"> <key name="favorite-apps" type="as">
<default>[ 'mozilla-firefox.desktop', 'evolution.desktop', 'openoffice.org-writer.desktop' ]</default> <default>[ 'mozilla-firefox.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'openoffice.org-writer.desktop', 'nautilus.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary> <_summary>List of desktop file IDs for favorite applications</_summary>
<_description> <_description>
The applications corresponding to these identifiers The applications corresponding to these identifiers
will be displayed in the favorites area. will be displayed in the favorites area.
</_description> </_description>
</key> </key>
<key name="disabled-open-search-providers" type="as">
<default>[]</default>
<_summary>disabled OpenSearch providers</_summary>
</key>
<key name="command-history" type="as"> <key name="command-history" type="as">
<default>[]</default> <default>[]</default>
<_summary>History for command (Alt-F2) dialog</_summary> <_summary>History for command (Alt-F2) dialog</_summary>
@ -59,51 +63,18 @@
<schema id="org.gnome.shell.clock" path="/apps/gnome-shell/clock/" <schema id="org.gnome.shell.clock" path="/apps/gnome-shell/clock/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key name="format" type="s">
<default l10n="messages" context="hour_format">
<!-- TRANSLATORS: This is the default hour format, choose ONLY '12-hour' or '24-hour'. -->
"12-hour"
</default>
<_summary>Hour format</_summary>
<_description>
This key specifies the hour format used by the panel clock.
Possible values are "12-hour", "24-hour", "unix" and "custom". If set
to "unix", the clock will display time in seconds since Epoch,
i.e. 1970-01-01. If set to "custom", the clock will display time
according to the format specified in the custom_format key. Note that
if set to either "unix" or "custom", the show_date and show_seconds
keys are ignored.
</_description>
<choices>
<choice value="12-hour"/>
<choice value="24-hour"/>
<choice value="unix"/>
<choice value="custom"/>
</choices>
</key>
<key name="custom-format" type="s">
<default>''</default>
<_summary>Custom format of the clock</_summary>
<_description>
This key specifies the format used by the panel clock when the format
key is set to "custom". You can use conversion specifiers understood
by strftime() to obtain a specific format. See the strftime() manual
for more information.
</_description>
</key>
<key name="show-seconds" type="b"> <key name="show-seconds" type="b">
<default>false</default> <default>false</default>
<_summary>Show time with seconds</_summary> <_summary>Show time with seconds</_summary>
<_description> <_description>
If true and format is either "12-hour" or "24-hour", display seconds in time. If true, display seconds in time.
</_description> </_description>
</key> </key>
<key name="show-date" type="b"> <key name="show-date" type="b">
<default>false</default> <default>false</default>
<_summary>Show date in clock</_summary> <_summary>Show date in clock</_summary>
<_description> <_description>
If true and format is either "12-hour" or "24-hour", If true, display date in the clock, in addition to time.
display date in the clock, in addition to time.
</_description> </_description>
</key> </key>
</schema> </schema>
@ -130,11 +101,13 @@
take care of its own output - this might be used to send the output 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 icecast server via shout2send or similar. When unset or set
to an empty value, the default pipeline will be used. This is currently to an empty value, the default pipeline will be used. This is currently
'videorate ! theoraenc ! oggmux' and records to Ogg Theora. 'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux'
and records to WEBM using the VP8 codec. %T is used as a placeholder
for a guess at the optimal thread count on the system.
</_description> </_description>
</key> </key>
<key name="file-extension" type="s"> <key name="file-extension" type="s">
<default>'ogv'</default> <default>'webm'</default>
<_summary>File extension used for storing the screencast</_summary> <_summary>File extension used for storing the screencast</_summary>
<_description> <_description>
The filename for recorded screencasts will be a unique filename The filename for recorded screencasts will be a unique filename

View File

@ -0,0 +1,7 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Google</ShortName>
<Description>Google Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
<Url type="text/html" method="GET" template="http://www.google.com/search?q={searchTerms}"/>
</OpenSearchDescription>

View File

@ -0,0 +1,44 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Wikipedia</ShortName>
<Description>Wikipedia, the free encyclopedia</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAEAgQAhIOEAMjHyABIR0gA6ejpAGlqaQCpqKkAKCgoAPz9%2FAAZGBkAmJiYANjZ2ABXWFcAent6ALm6uQA8OjwAiIiIiIiIiIiIiI4oiL6IiIiIgzuIV4iIiIhndo53KIiIiB%2FWvXoYiIiIfEZfWBSIiIEGi%2FfoqoiIgzuL84i9iIjpGIoMiEHoiMkos3FojmiLlUipYliEWIF%2BiDe0GoRa7D6GPbjcu1yIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</Image>
<Url type="text/html" method="GET" template="http://{language}.wikipedia.org/wiki/Special:Search?search={searchTerms}"/>
<!-- The criterion for being below is being listed with more than 100,000
articles on http://meta.wikimedia.org/wiki/List_of_Wikipedias -->
<Language>ar</Language>
<Language>bg</Language>
<Language>ca</Language>
<Language>cs</Language>
<Language>da</Language>
<Language>de</Language>
<Language>en</Language>
<Language>eo</Language>
<Language>es</Language>
<Language>fa</Language>
<Language>fi</Language>
<Language>fr</Language>
<Language>he</Language>
<Language>hu</Language>
<Language>id</Language>
<Language>it</Language>
<Language>ja</Language>
<Language>ko</Language>
<Language>lt</Language>
<Language>nl</Language>
<Language>no</Language>
<Language>pl</Language>
<Language>pt</Language>
<Language>ro</Language>
<Language>ru</Language>
<Language>sk</Language>
<Language>sl</Language>
<Language>sr</Language>
<Language>sv</Language>
<Language>tr</Language>
<Language>uk</Language>
<Language>vi</Language>
<Language>vo</Language>
<Language>war</Language>
<Language>zh</Language>
</OpenSearchDescription>

View File

@ -1,98 +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="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>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,82 @@
<?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="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48+devel r9942 custom"
sodipodi:docname="New document 4">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="8.984481"
inkscape:cy="5.6224906"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:window-width="930"
inkscape:window-height="681"
inkscape:window-x="1892"
inkscape:window-y="272"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid17403"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<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"
transform="translate(0,-1036.3622)">
<path
sodipodi:type="star"
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.43015847;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="path18028"
sodipodi:sides="3"
sodipodi:cx="84.5"
sodipodi:cy="337.5"
sodipodi:r1="5"
sodipodi:r2="2.5"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 88.830127,340 80.169873,340 84.5,332.5 z"
transform="matrix(0,1.3621708,0.99186247,0,-325.48222,929.32667)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,82 @@
<?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="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48+devel r9942 custom"
sodipodi:docname="arrow-left.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="7.7366092"
inkscape:cy="6.4536271"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
borderlayer="true"
inkscape:showpageshadow="false"
inkscape:window-width="930"
inkscape:window-height="681"
inkscape:window-x="1892"
inkscape:window-y="272"
inkscape:window-maximized="0">
<inkscape:grid
type="xygrid"
id="grid17403"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<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"
transform="translate(0,-1036.3622)">
<path
sodipodi:type="star"
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.43015847;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="path18028"
sodipodi:sides="3"
sodipodi:cx="84.5"
sodipodi:cy="337.5"
sodipodi:r1="5"
sodipodi:r2="2.5"
sodipodi:arg1="0.52359878"
sodipodi:arg2="1.5707963"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="M 88.830127,340 80.169873,340 84.5,332.5 z"
transform="matrix(0,1.3621708,-0.99186247,0,342.48324,929.32667)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,222 +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: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="24"
height="24"
id="svg4908"
sodipodi:version="0.32"
inkscape:version="0.47 r22583"
sodipodi:docname="dialog-error.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="/home/andreas/project/gnome-icon-theme/scalable/actions/process-stop.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90"
version="1.0">
<defs
id="defs4910">
<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="perspective25" />
<radialGradient
gradientTransform="matrix(1.349881,0,0,1.349881,-3.498814,-1.810859)"
gradientUnits="userSpaceOnUse"
r="9.7183542"
fy="4.9892726"
fx="9.6893959"
cy="4.9892726"
cx="9.6893959"
id="radialGradient5177"
xlink:href="#linearGradient5171"
inkscape:collect="always" />
<radialGradient
gradientTransform="matrix(2.417917,0,0,2.417917,-14.17917,-4.903184)"
gradientUnits="userSpaceOnUse"
r="9.7785711"
fy="3.458019"
fx="10"
cy="3.458019"
cx="10"
id="radialGradient5157"
xlink:href="#linearGradient5151"
inkscape:collect="always" />
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.928125,0,0,0.3143011,0.7718789,12.358015)"
r="9.0598059"
fy="18.022524"
fx="10.739184"
cy="18.022524"
cx="10.739184"
id="radialGradient5145"
xlink:href="#linearGradient5139"
inkscape:collect="always" />
<linearGradient
id="linearGradient5139"
inkscape:collect="always">
<stop
id="stop5141"
offset="0"
style="stop-color:black;stop-opacity:1;" />
<stop
id="stop5143"
offset="1"
style="stop-color:black;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient5151"
inkscape:collect="always">
<stop
id="stop5153"
offset="0"
style="stop-color:white;stop-opacity:1;" />
<stop
id="stop5155"
offset="1"
style="stop-color:white;stop-opacity:0;" />
</linearGradient>
<linearGradient
id="linearGradient5171">
<stop
id="stop5173"
offset="0"
style="stop-color:#fe3a00;stop-opacity:1" />
<stop
id="stop5175"
offset="1"
style="stop-color:#c00;stop-opacity:1;" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="24.442987"
inkscape:cy="10.142308"
inkscape:current-layer="g7001"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1674"
inkscape:window-height="970"
inkscape:window-x="0"
inkscape:window-y="26"
width="48px"
height="48px"
inkscape:window-maximized="0" />
<metadata
id="metadata4913">
<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>Stop Process</dc:title>
<dc:date>December 2006</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:creator>
<dc:contributor>
<cc:Agent>
<dc:title>Andreas Nilsson</dc:title>
</cc:Agent>
</dc:contributor>
<cc:license
rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
<dc:subject>
<rdf:Bag>
<rdf:li>stop</rdf:li>
<rdf:li>halt</rdf:li>
</rdf:Bag>
</dc:subject>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
<cc:permits
rdf:resource="http://web.resource.org/cc/Reproduction" />
<cc:permits
rdf:resource="http://web.resource.org/cc/Distribution" />
<cc:requires
rdf:resource="http://web.resource.org/cc/Notice" />
<cc:permits
rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
<cc:requires
rdf:resource="http://web.resource.org/cc/ShareAlike" />
<cc:requires
rdf:resource="http://web.resource.org/cc/SourceCode" />
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-24)">
<g
inkscape:label="Layer 1"
id="g7001"
transform="matrix(1.4566048,0,0,1.4455352,0.4112881,1.2324709)">
<path
transform="matrix(0.91468137,0,0,0.70055266,-1.8812476,17.474032)"
d="m 19.79899,18.022524 a 9.0598059,3.0935922 0 1 1 -18.1196115,0 9.0598059,3.0935922 0 1 1 18.1196115,0 z"
sodipodi:ry="3.0935922"
sodipodi:rx="9.0598059"
sodipodi:cy="18.022524"
sodipodi:cx="10.739184"
id="path5137"
style="color:#000000;fill:url(#radialGradient5145);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
<path
transform="matrix(0.87347736,0,0,0.83068052,-0.79308842,15.602788)"
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
sodipodi:ry="9.25"
sodipodi:rx="9.25"
sodipodi:cy="9.625"
sodipodi:cx="10"
id="path4262"
style="color:#000000;fill:url(#radialGradient5177);fill-opacity:1;fill-rule:nonzero;stroke:#a40000;stroke-width:0.47435912;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
sodipodi:type="arc" />
<path
sodipodi:type="arc"
style="opacity:0.35393258;color:#000000;fill:none;stroke:url(#radialGradient5157);stroke-width:0.49999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
id="path5149"
sodipodi:cx="10"
sodipodi:cy="9.625"
sodipodi:rx="9.25"
sodipodi:ry="9.25"
d="m 19.25,9.625 a 9.25,9.25 0 1 1 -18.5,0 9.25,9.25 0 1 1 18.5,0 z"
transform="matrix(0.82868359,0,0,0.78808147,-0.34515141,16.012803)" />
<path
sodipodi:nodetypes="cc"
id="path5159"
d="m 4.834121,20.642783 6.215127,5.91061"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219134;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.21219146;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
d="M 11.04925,20.622826 4.8159529,26.553393"
id="path5161"
sodipodi:nodetypes="cc" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -17,6 +17,10 @@
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
stage {
font-family: cantarell, sans-serif;
}
.shell-link { .shell-link {
color: #0000ff; color: #0000ff;
text-decoration: underline; text-decoration: underline;
@ -101,7 +105,7 @@ StTooltip StLabel {
.popup-menu { .popup-menu {
color: #ffffff; color: #ffffff;
font-size: 16px; font-size: 14px;
min-width: 200px; min-width: 200px;
} }
@ -151,7 +155,7 @@ StTooltip StLabel {
} }
.popup-menu-icon { .popup-menu-icon {
icon-size: 1em; icon-size: 1.14em;
} }
/* Switches (to be used in menus) */ /* Switches (to be used in menus) */
@ -178,7 +182,6 @@ StTooltip StLabel {
#panel { #panel {
color: #ffffff; color: #ffffff;
font-size: 16px;
background-color: black; background-color: black;
} }
@ -209,7 +212,7 @@ StTooltip StLabel {
border-radius: 5px; border-radius: 5px;
border-radius-bottomleft: 0px; border-radius-bottomleft: 0px;
border-radius-bottomright: 0px; border-radius-bottomright: 0px;
font: 16px sans-serif; font-size: 14px;
font-weight: bold; font-weight: bold;
transition-duration: 100; transition-duration: 100;
} }
@ -242,7 +245,7 @@ StTooltip StLabel {
} }
.system-status-icon { .system-status-icon {
icon-size: 1em; icon-size: 1.14em;
} }
/* Overview */ /* Overview */
@ -257,44 +260,23 @@ StTooltip StLabel {
spacing: 25px; spacing: 25px;
} }
.workspace-indicator-panel {
spacing: 8px;
}
.workspace-indicator {
width: 24px;
height: 16px;
background: rgba(255,255,255,0.2);
}
.workspace-indicator.active {
background: rgba(255,255,255,0.8);
}
.workspace-controls { .workspace-controls {
width: 48px;
font-size: 32px; font-size: 32px;
font-weight: bold; font-weight: bold;
color: #ffffff; color: #ffffff;
border: 2px solid rgba(128, 128, 128, 0.4); border: 1px solid #424242;
border-right: 0px; border-right: 0px;
border-radius: 9px 0px 0px 9px; border-radius: 9px 0px 0px 9px;
background: #071524;
} }
.add-workspace { .workspace-thumbnails {
background-color: rgba(128, 128, 128, 0.4); spacing: 7px;
padding: 8px;
} }
.add-workspace:hover { .workspace-thumbnail-indicator {
background-color: rgba(128, 128, 128, 0.6); outline: 2px solid white;
}
.remove-workspace {
height: 48px;
}
.remove-workspace:hover {
background-color: rgba(128, 128, 128, 0.2);
} }
.window-caption { .window-caption {
@ -310,7 +292,7 @@ StTooltip StLabel {
background-image: url("close-window.svg"); background-image: url("close-window.svg");
height: 24px; height: 24px;
width: 24px; width: 24px;
-st-shadow: -2px 2px 6px rgba(0,0,0,0.5); -st-background-image-shadow: -2px 2px 6px rgba(0,0,0,0.5);
-shell-close-overlap: 16px; -shell-close-overlap: 16px;
} }
@ -338,6 +320,7 @@ StTooltip StLabel {
#viewSelector { #viewSelector {
spacing: 16px; spacing: 16px;
font-size: 16px;
} }
#viewSelectorTabBar { #viewSelectorTabBar {
@ -370,7 +353,7 @@ StTooltip StLabel {
background-gradient-direction: vertical; background-gradient-direction: vertical;
color: rgb(64, 64, 64); color: rgb(64, 64, 64);
font-weight: bold; font-weight: bold;
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9); box-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
transition-duration: 0; transition-duration: 0;
} }
@ -384,10 +367,18 @@ StTooltip StLabel {
color: #888a85; color: #888a85;
font-weight: bold; font-weight: bold;
padding: 0px 12px; padding: 0px 12px;
height: 24px;
}
.view-tab-title:hover {
color: #bbb;
} }
.view-tab-title:selected { .view-tab-title:selected {
color: white; color: #000000;
background-color: #c2c7cd;
border-radius: 4px;
height: 24px;
} }
.view-tab-boxpointer { .view-tab-boxpointer {
@ -436,40 +427,30 @@ StTooltip StLabel {
spacing: 4px; spacing: 4px;
} }
/* GenericDisplay */ .search-providers-box {
.generic-display-container {
spacing: 4px; spacing: 4px;
} }
.generic-display-item { .dash-search-button {
height: 50px; background-gradient-direction: vertical;
border-radius: 4px; background-gradient-start: rgba(255, 255, 255, 0.2);
color: #ffffff; background-gradient-end: rgba(255, 255, 255, 0);
font-size: 14px; /* border: 1px solid #808080;*/
spacing: 4px; border-radius: 10px;
height: 32px;
width: 300px;
} }
.generic-display-item:selected { .dash-search-button:selected,
background-color: rgba(79,111,173,0.66); .dash-search-button:hover {
background-gradient-direction: vertical;
background-gradient-start: rgba(255, 255, 255, 0.4);
background-gradient-end: rgba(255, 255, 255, 0.2);
} }
.generic-display-item-text { .dash-search-button-label {
spacing: 4px; color: #cccccc;
} font-size: 16px;
.generic-display-item-description {
font-size: 12px;
color: #bababa;
}
.generic-display-details {
font-size: 14px;
color: #ffffff;
}
.generic-display-details-name {
font-weight: bold;
} }
/* Apps */ /* Apps */
@ -508,7 +489,7 @@ StTooltip StLabel {
.remove-favorite-icon:hover { .remove-favorite-icon:hover {
color: white; color: white;
-st-shadow: black 0px 2px 2px; icon-shadow: black 0px 2px 2px;
} }
.app-well-app > .overview-icon, .app-well-app > .overview-icon,
@ -549,57 +530,6 @@ StTooltip StLabel {
font-size: 12px font-size: 12px
} }
/* Places */
.places-section {
spacing-columns: 4px;
spacing-rows: 4px;
}
.places-item-box {
spacing: 2px;
}
.places-item {
border-radius: 4px;
padding: 2px;
border: 1px solid #181818;
padding-left: 4px;
padding-right: 4px;
transition-duration: 100;
}
.places-item:hover {
border: 1px solid #666666;
background-gradient-direction: vertical;
background-gradient-start: rgba(61,61,61,0.8);
background-gradient-end: rgba(24,24,24,0.2);
transition-duration: 100;
}
/* Recent items */
.recent-docs-item-box {
spacing: 2px;
}
.recent-docs-item {
border-radius: 4px;
padding: 2px;
border: 1px solid #181818;
padding-left: 4px;
padding-right: 4px;
transition-duration: 100;
}
.recent-docs-item:hover {
border: 1px solid #666666;
background-gradient-direction: vertical;
background-gradient-start: rgba(61,61,61,0.8);
background-gradient-end: rgba(24,24,24,0.2);
transition-duration: 100;
}
/* LookingGlass */ /* LookingGlass */
#LookingGlassDialog #LookingGlassDialog
@ -723,6 +653,17 @@ StTooltip StLabel {
/* Calendar popup */ /* Calendar popup */
#calendarArea {
/* this is the width of the entire popup */
width: 600px;
}
.calendar-vertical-separator {
-stipple-width: 1px;
-stipple-color: #505050;
width: 1.5em;
}
#calendarPopup { #calendarPopup {
border-radius: 5px; border-radius: 5px;
background: rgba(0,0,0,0.9); background: rgba(0,0,0,0.9);
@ -735,37 +676,155 @@ StTooltip StLabel {
} }
.calendar { .calendar {
spacing-rows: 5px; padding: .4em 1.75em;
spacing-columns: 3px; spacing-rows: 0px;
spacing-columns: 0px;
} }
.calendar-change-month { .calendar-month-label {
color: #666666;
font-size: 10px;
padding: 2px; padding: 2px;
} }
.calendar-change-month:hover { .calendar-change-month-back {
background: #314a6c; width: 20px;
border-radius: 5px; height: 20px;
background-image: url("calendar-arrow-left.svg");
border-radius: 4px;
}
.calendar-change-month-back:hover {
background-color: #999999;
}
.calendar-change-month-back:active {
background-color: #aaaaaa;
} }
.calendar-change-month:active { .calendar-change-month-forward {
background: #213050; width: 20px;
border-radius: 5px; height: 20px;
background-image: url("calendar-arrow-right.svg");
border-radius: 4px;
}
.calendar-change-month-forward:hover {
background-color: #999999;
}
.calendar-change-month-forward:active {
background-color: #aaaaaa;
} }
.datemenu-date-label {
padding: .4em 1.75em;
font-size: 16px;
color: #ffffff;
}
.calendar-day-base {
font-size: 10px;
text-align: center;
width: 24px;
height: 24px;
}
.calendar-day-base:hover {
background: #777777;
}
.calendar-day-base:active {
background: #555555;
}
.calendar-day-heading {
color: #666666;
}
.calendar-week-number {
color: #666666;
font-weight: bold;
}
/* Hack used in lieu of border-collapse - see calendar.js */
.calendar-day { .calendar-day {
padding: 1px 2px; border: 1px solid #333333;
color: #cccccc;
border-top-width: 0;
border-left-width: 0;
}
.calendar-day-top {
border-top-width: 1px;
}
.calendar-day-left {
border-left-width: 1px;
}
.calendar-work-day {
}
.calendar-nonwork-day {
background-color: rgba(128, 128, 128, .1);
} }
.calendar-today { .calendar-today {
color: #ffffff;
font-weight: bold; font-weight: bold;
background: #ffffff; background-gradient-direction: vertical;
color: black; background-gradient-start: #3c3c3c;
border-radius: 5px; background-gradient-end: #131313;
} }
.calendar-other-month-day { .calendar-other-month-day {
color: #cccccc; color: #333333;
}
.calendar-day-with-events {
font-weight: bold;
}
.events-header-vbox {
spacing: 10px;
}
.events-header {
height: 40px;
}
.events-header-hbox {
spacing: 8px;
padding: 0.3em;
}
.events-day-header {
font-size: 14px;
color: rgba(153, 153, 153, 1.0);
}
.events-day-dayname {
font-size: 12px;
color: rgba(153, 153, 153, 1.0);
text-align: left;
}
.events-day-time {
font-size: 12px;
font-weight: bold;
color: #fff;
text-align: right;
}
.events-day-task {
font-size: 12px;
color: rgba(153, 153, 153, 1.0);
}
.events-day-name-box {
width: 20px;
}
.events-time-box {
width: 70px;
}
.events-event-box {
} }
.url-highlighter { .url-highlighter {
@ -841,6 +900,10 @@ StTooltip StLabel {
border: 1px solid #a1a1a1; border: 1px solid #a1a1a1;
} }
.notification-button:focus {
background-color: #666666;
}
.notification-button:active { .notification-button:active {
border: 1px solid #a1a1a1; border: 1px solid #a1a1a1;
background-color: #2b2b2b; background-color: #2b2b2b;
@ -853,6 +916,10 @@ StTooltip StLabel {
} }
.notification-icon-button:hover { .notification-icon-button:hover {
border: 2px rgba(161,161,161,0.7);
}
.notification-icon-button:focus {
background: rgba(192,192,192,0.7); background: rgba(192,192,192,0.7);
} }
@ -904,7 +971,7 @@ StTooltip StLabel {
color: #545454; color: #545454;
background-color: #e8e8e8; background-color: #e8e8e8;
caret-color: #545454; caret-color: #545454;
-st-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9); box-shadow: 0px 0px 6px 2px rgba(255,255,255,0.9);
} }
/* The spacing and padding on the summary is tricky; we want to keep /* The spacing and padding on the summary is tricky; we want to keep
@ -939,15 +1006,11 @@ StTooltip StLabel {
} }
.source-title { .source-title {
font: 12px sans-serif; font-size: 12px;
font-weight: bold; font-weight: bold;
padding-left: 4px; padding-left: 4px;
} }
.calendar-calendarweek {
color: #666666;
}
/* App Switcher */ /* App Switcher */
#altTabPopup { #altTabPopup {
padding: 8px; padding: 8px;
@ -960,7 +1023,7 @@ StTooltip StLabel {
border-radius: 24px; border-radius: 24px;
padding: 20px; padding: 20px;
font: 12px sans-serif; font-size: 12px;
color: white; color: white;
} }
@ -993,6 +1056,15 @@ StTooltip StLabel {
border-radius: 8px; border-radius: 8px;
} }
.switcher-list .item-box:outlined {
padding: 6px;
border: 2px solid rgba(85,85,85,1.0);
}
.switcher-list .item-box:selected {
background: rgba(255,255,255,0.33);
}
.switcher-list .thumbnail-box { .switcher-list .thumbnail-box {
padding: 2px; padding: 2px;
spacing: 4px; spacing: 4px;
@ -1002,18 +1074,6 @@ StTooltip StLabel {
width: 256px; width: 256px;
} }
.switcher-list .outlined-item-box {
padding: 6px;
border: 2px solid rgba(85,85,85,1.0);
border-radius: 8px;
}
.switcher-list .selected-item-box {
padding: 8px;
border-radius: 8px;
background: rgba(255,255,255,0.33);
}
.switcher-list .separator { .switcher-list .separator {
width: 1px; width: 1px;
background: rgba(255,255,255,0.33); background: rgba(255,255,255,0.33);
@ -1078,41 +1138,146 @@ StTooltip StLabel {
border-radius: 8px; border-radius: 8px;
} }
/* Run Dialog */ /* Modal Dialogs */
.run-dialog-label { .modal-dialog {
font: 12px sans-serif; font-size: 12pt;
color: white; border-radius: 24px;
background-color: rgba(0.0, 0.0, 0.0, 0.9);
border: 2px solid #868686;
color: #ffffff;
padding-right: 42px;
padding-left: 42px;
padding-bottom: 30px;
padding-top: 30px;
} }
.run-dialog-error-icon { .modal-dialog-button {
background-image: url("dialog-error.svg"); border: 1px solid #8b8b8b;
width: 36px; border-radius: 18px;
height: 36px; font-size: 14px;
margin-left: 10px;
margin-right: 10px;
padding-left: 32px;
padding-right: 32px;
padding-top: 8px;
padding-bottom: 8px;
background-gradient-direction: vertical;
background-gradient-start: #29323b;
background-gradient-end: #121a24;
}
.modal-dialog-button:active,
.modal-dialog-button:pressed {
border-color: #a5a5a5;
background-gradient-start: #121a24;
background-gradient-end: #29323b;
}
.modal-dialog-button:focus {
border: 2px solid #a5a5a5;
padding-left: 31px;
padding-right: 31px;
padding-top: 7px;
padding-bottom: 7px;
}
/* Run Dialog */
.run-dialog-label {
font-size: 12px;
color: white;
} }
.run-dialog-error-label { .run-dialog-error-label {
font: 16px sans-serif; font-size: 12px;
color: white; color: white;
} }
.run-dialog-error-box {
padding-top: 15px;
spacing: 5px;
}
.run-dialog-entry { .run-dialog-entry {
font: 14px sans-serif; font-size: 14px;
font-weight: bold; font-weight: bold;
width: 320px; width: 320px;
color: white; color: white;
} }
.run-dialog { .run-dialog {
padding: 8px; border-radius: 16px;
border: 1px solid rgba(128,128,128,0.40);
border-radius: 4px; padding-right: 21px;
background: rgba(0,0,0,0.8); padding-left: 21px;
padding-bottom: 15px;
padding-top: 15px;
} }
.lightbox { .lightbox {
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
} }
/* End Session Dialog */
.end-session-dialog-subject {
font-size: 12pt;
font-weight: bold;
color: #666666;
padding-top: 10px;
padding-left: 17px;
padding-bottom: 30px;
}
.end-session-dialog-description {
font-size: 10pt;
color: white;
padding-left: 17px;
padding-right: 40px;
width: 16em;
}
.end-session-dialog-logout-icon {
border: 2px solid #8b8b8b;
border-radius: 5px;
width: 32px;
height: 32px;
}
.end-session-dialog-shutdown-icon {
width: 32px;
height: 32px;
}
.end-session-dialog-app-list {
font-size: 10pt;
max-height: 200px;
padding-top: 42px;
padding-bottom: 42px;
padding-left: 17px;
padding-right: 32px;
}
.end-session-dialog-app-list-item {
padding-right: 1em;
}
.end-session-dialog-app-list-item-icon {
padding-right: 17px;
}
.end-session-dialog-app-list-item-name {
font-size: 10pt;
}
.end-session-dialog-app-list-item-description {
font-size: 8pt;
color: #444444;
}
/* Magnifier */ /* Magnifier */
.magnifier-zoom-region { .magnifier-zoom-region {

View File

@ -1,92 +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="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>

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -33,7 +33,7 @@
<foaf:Person> <foaf:Person>
<foaf:name>Colin Walters</foaf:name> <foaf:name>Colin Walters</foaf:name>
<foaf:mbox rdf:resource="mailto:walters@verbum.org" /> <foaf:mbox rdf:resource="mailto:walters@verbum.org" />
<gnome:userid>cwalters</gnome:userid> <gnome:userid>walters</gnome:userid>
</foaf:Person> </foaf:Person>
</maintainer> </maintainer>
<maintainer> <maintainer>

View File

@ -9,9 +9,8 @@ nobase_dist_js_DATA = \
misc/gnomeSession.js \ misc/gnomeSession.js \
misc/params.js \ misc/params.js \
misc/telepathy.js \ misc/telepathy.js \
misc/utils.js \ misc/util.js \
perf/core.js \ perf/core.js \
prefs/clockPreferences.js \
ui/altTab.js \ ui/altTab.js \
ui/appDisplay.js \ ui/appDisplay.js \
ui/appFavorites.js \ ui/appFavorites.js \
@ -20,11 +19,12 @@ nobase_dist_js_DATA = \
ui/chrome.js \ ui/chrome.js \
ui/ctrlAltTab.js \ ui/ctrlAltTab.js \
ui/dash.js \ ui/dash.js \
ui/dateMenu.js \
ui/dnd.js \ ui/dnd.js \
ui/docDisplay.js \ ui/docDisplay.js \
ui/endSessionDialog.js \
ui/environment.js \ ui/environment.js \
ui/extensionSystem.js \ ui/extensionSystem.js \
ui/genericDisplay.js \
ui/iconGrid.js \ ui/iconGrid.js \
ui/lightbox.js \ ui/lightbox.js \
ui/link.js \ ui/link.js \
@ -33,6 +33,7 @@ nobase_dist_js_DATA = \
ui/magnifierDBus.js \ ui/magnifierDBus.js \
ui/main.js \ ui/main.js \
ui/messageTray.js \ ui/messageTray.js \
ui/modalDialog.js \
ui/notificationDaemon.js \ ui/notificationDaemon.js \
ui/overview.js \ ui/overview.js \
ui/panel.js \ ui/panel.js \
@ -47,6 +48,7 @@ nobase_dist_js_DATA = \
ui/statusIconDispatcher.js \ ui/statusIconDispatcher.js \
ui/statusMenu.js \ ui/statusMenu.js \
ui/status/accessibility.js \ ui/status/accessibility.js \
ui/status/keyboard.js \
ui/status/power.js \ ui/status/power.js \
ui/status/volume.js \ ui/status/volume.js \
ui/status/bluetooth.js \ ui/status/bluetooth.js \
@ -56,5 +58,7 @@ nobase_dist_js_DATA = \
ui/windowAttentionHandler.js \ ui/windowAttentionHandler.js \
ui/windowManager.js \ ui/windowManager.js \
ui/workspace.js \ ui/workspace.js \
ui/workspaceThumbnail.js \
ui/workspacesView.js \ ui/workspacesView.js \
ui/workspaceSwitcherPopup.js ui/workspaceSwitcherPopup.js \
ui/xdndHandler.js

View File

@ -1,3 +1,10 @@
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */ /* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
/* The name of this package (not localized) */
const PACKAGE_NAME = '@PACKAGE_NAME@';
/* The version of this package */
const PACKAGE_VERSION = '@PACKAGE_VERSION@';
/* The version of GJS we're linking to */
const GJS_VERSION = '@GJS_VERSION@';
/* 1 if gnome-bluetooth is available, 0 otherwise */
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@; const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;

View File

@ -29,8 +29,8 @@ DocInfo.prototype = {
return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo); return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
}, },
launch : function() { launch : function(workspaceIndex) {
Shell.DocSystem.get_default().open(this.recentInfo); Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex);
}, },
matchTerms: function(terms) { matchTerms: function(terms) {
@ -60,8 +60,7 @@ function getDocManager() {
} }
/** /**
* DocManager wraps the DocSystem, primarily to expose DocInfo objects * DocManager wraps the DocSystem, primarily to expose DocInfo objects.
* which conform to the GenericDisplay item API.
*/ */
function DocManager() { function DocManager() {
this._init(); this._init();

View File

@ -2,6 +2,7 @@
const DBus = imports.dbus; const DBus = imports.dbus;
const Lang = imports.lang; const Lang = imports.lang;
const Signals = imports.signals;
const PresenceIface = { const PresenceIface = {
name: 'org.gnome.SessionManager.Presence', name: 'org.gnome.SessionManager.Presence',
@ -43,3 +44,60 @@ Presence.prototype = {
} }
}; };
DBus.proxifyPrototype(Presence.prototype, PresenceIface); DBus.proxifyPrototype(Presence.prototype, PresenceIface);
// Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form
// of new inhibitors)
const InhibitorIface = {
name: 'org.gnome.SessionManager.Inhibitor',
properties: [{ name: 'app_id',
signature: 's',
access: 'readonly' },
{ name: 'client_id',
signature: 's',
access: 'readonly' },
{ name: 'reason',
signature: 's',
access: 'readonly' },
{ name: 'flags',
signature: 'u',
access: 'readonly' },
{ name: 'toplevel_xid',
signature: 'u',
access: 'readonly' },
{ name: 'cookie',
signature: 'u',
access: 'readonly' }],
};
function Inhibitor(objectPath) {
this._init(objectPath);
}
Inhibitor.prototype = {
_init: function(objectPath) {
DBus.session.proxifyObject(this,
"org.gnome.SessionManager",
objectPath);
this.isLoaded = false;
this._loadingPropertiesCount = InhibitorIface.properties.length;
for (let i = 0; i < InhibitorIface.properties.length; i++) {
let propertyName = InhibitorIface.properties[i].name;
this.GetRemote(propertyName, Lang.bind(this,
function(value, exception) {
if (exception)
return;
this[propertyName] = value;
this._loadingPropertiesCount--;
if (this._loadingPropertiesCount == 0) {
this.isLoaded = true;
this.emit("is-loaded");
}
}));
}
},
};
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
Signals.addSignalMethods(Inhibitor.prototype);

180
js/misc/util.js Normal file
View File

@ -0,0 +1,180 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
// findUrls:
// @str: string to find URLs in
//
// Searches @str for URLs and returns an array of objects with %url
// properties showing the matched URL string, and %pos properties indicating
// the position within @str where the URL was found.
//
// Return value: the list of match objects, as described above
function findUrls(str) {
let res = [], match;
while ((match = _urlRegexp.exec(str)))
res.push({ url: match[0], pos: match.index });
return res;
}
// spawn:
// @argv: an argv array
//
// Runs @argv in the background, handling any errors that occur
// when trying to start the program.
function spawn(argv) {
try {
trySpawn(argv);
} catch (err) {
_handleSpawnError(argv[0], err);
}
}
// spawnCommandLine:
// @command_line: a command line
//
// Runs @command_line in the background, handling any errors that
// occur when trying to parse or start the program.
function spawnCommandLine(command_line) {
try {
let [success, argc, argv] = GLib.shell_parse_argv(command_line);
trySpawn(argv);
} catch (err) {
_handleSpawnError(command_line, err);
}
}
// spawnDesktop:
// @id: a desktop file ID
//
// Spawns the desktop file identified by @id using startup notification,
// etc, handling any errors that occur when trying to find or start
// the program.
function spawnDesktop(id) {
try {
trySpawnDesktop(id);
} catch (err) {
_handleSpawnError(id, err);
}
}
// trySpawn:
// @argv: an argv array
//
// Runs @argv in the background. If launching @argv fails,
// this will throw an error.
function trySpawn(argv)
{
try {
GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH,
null, null);
} catch (err) {
if (err.code == GLib.SpawnError.G_SPAWN_ERROR_NOENT) {
err.message = _("Command not found");
} else {
// The exception from gjs contains an error string like:
// Error invoking GLib.spawn_command_line_async: Failed to
// execute child process "foo" (No such file or directory)
// We are only interested in the part in the parentheses. (And
// we can't pattern match the text, since it gets localized.)
err.message = err.message.replace(/.*\((.+)\)/, '$1');
}
throw err;
}
}
// trySpawnCommandLine:
// @command_line: a command line
//
// Runs @command_line in the background. If launching @command_line
// fails, this will throw an error.
function trySpawnCommandLine(command_line) {
let success, argc, argv;
try {
[success, argc, argv] = GLib.shell_parse_argv(command_line);
} catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
throw err;
}
trySpawn(argv);
}
// trySpawnDesktop:
// @id: a desktop file ID
//
// Spawns the desktop file identified by @id using startup notification.
// On error, throws an exception.
function trySpawnDesktop(id) {
let app;
// shell_app_system_load_from_desktop_file() will end up returning
// a stupid error message if the desktop file doesn't exist, but
// that's the only case it returns an error for, so we just
// substitute our own error in instead
try {
app = Shell.AppSystem.get_default().load_from_desktop_file(id + '.desktop');
} catch (err) {
throw new Error(_("No such application"));
}
try {
app.launch();
} catch(err) {
// see trySpawn
err.message = err.message.replace(/.*\((.+)\)/, '$1');
throw err;
}
}
function _handleSpawnError(command, err) {
let title = _("Execution of '%s' failed:").format(command);
let source = new MessageTray.SystemNotificationSource();
Main.messageTray.add(source);
let notification = new MessageTray.Notification(source, title, err.message);
notification.setTransient(true);
source.notify(notification);
}
// killall:
// @processName: a process name
//
// Kills @processName. If no process with the given name is found,
// this will fail silently.
function killall(processName) {
try {
// 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 can match
// '/usr/bin/processName' but not 'gedit processName.c' or
// whatever...
let argv = ['pkill', '-f', '^([^ ]*/)?' + processName + '($| )'];
GLib.spawn_sync(null, argv, null, GLib.SpawnFlags.SEARCH_PATH, null, null);
// It might be useful to return success/failure, but we'd need
// a wrapper around WIFEXITED and WEXITSTATUS. Since none of
// the current callers care, we don't bother.
} catch (e) {
logError(e, 'Failed to kill ' + processName);
}
}

View File

@ -1,19 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
const _urlRegexp = /\b(([a-z][\w-]+:(\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)([^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/gi;
// findUrls:
// @str: string to find URLs in
//
// Searches @str for URLs and returns an array of objects with %url
// properties showing the matched URL string, and %pos properties indicating
// the position within @str where the URL was found.
//
// Return value: the list of match objects, as described above
function findUrls(str) {
let res = [], match;
while ((match = _urlRegexp.exec(str)))
res.push({ url: match[0], pos: match.index });
return res;
}

View File

@ -1,97 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Signals = imports.signals;
const Gettext = imports.gettext;
const FORMAT_KEY = 'format';
const SHOW_DATE_KEY = 'show-date';
const SHOW_SECONDS_KEY = 'show-seconds';
function ClockPreferences(uiFile) {
this._init(uiFile);
};
ClockPreferences.prototype = {
_init: function(uiFile) {
let builder = new Gtk.Builder();
builder.add_from_file(uiFile);
this._dialog = builder.get_object('prefs-dialog');
this._dialog.connect('response', Lang.bind(this, this._onResponse));
this._12hrRadio = builder.get_object('12hr_radio');
this._24hrRadio = builder.get_object('24hr_radio');
this._dateCheck = builder.get_object('date_check');
this._secondsCheck = builder.get_object('seconds_check');
delete builder;
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
this._notifyId = this._settings.connect('changed',
Lang.bind(this,
this._updateDialog));
this._12hrRadio.connect('toggled', Lang.bind(this,
function() {
let format = this._12hrRadio.active ? '12-hour' : '24-hour';
this._settings.set_string(FORMAT_KEY, format);
}));
this._dateCheck.connect('toggled', Lang.bind(this,
function() {
this._settings.set_boolean(SHOW_DATE_KEY,
this._dateCheck.active);
}));
this._secondsCheck.connect('toggled', Lang.bind(this,
function() {
this._settings.set_boolean(SHOW_SECONDS_KEY,
this._secondsCheck.active);
}));
this._updateDialog();
},
show: function() {
this._dialog.show_all();
},
_updateDialog: function() {
let format = this._settings.get_string(FORMAT_KEY);
this._12hrRadio.active = (format == "12-hour");
this._24hrRadio.active = (format == "24-hour");
this._dateCheck.active = this._settings.get_boolean(SHOW_DATE_KEY);
this._secondsCheck.active = this._settings.get_boolean(SHOW_SECONDS_KEY);
},
_onResponse: function() {
this._dialog.destroy();
this._settings.disconnect(this._notifyId);
this.emit('destroy');
}
};
Signals.addSignalMethods(ClockPreferences.prototype);
function main(params) {
if ('progName' in params)
GLib.set_prgname(params['progName']);
if ('localeDir' in params)
Gettext.bindtextdomain('gnome-shell', params['localeDir']);
Gtk.init(null, null);
let clockPrefs = new ClockPreferences(params['uiFile']);
clockPrefs.connect('destroy',
function() {
Gtk.main_quit();
});
clockPrefs.show();
Gtk.main();
}

View File

@ -15,6 +15,8 @@ const POPUP_APPICON_SIZE = 96;
const POPUP_SCROLL_TIME = 0.10; // seconds const POPUP_SCROLL_TIME = 0.10; // seconds
const POPUP_FADE_TIME = 0.1; // seconds const POPUP_FADE_TIME = 0.1; // seconds
const APP_ICON_HOVER_TIMEOUT = 200; // milliseconds
const DISABLE_HOVER_TIMEOUT = 500; // milliseconds const DISABLE_HOVER_TIMEOUT = 500; // milliseconds
const THUMBNAIL_DEFAULT_SIZE = 256; const THUMBNAIL_DEFAULT_SIZE = 256;
@ -34,7 +36,8 @@ function AltTabPopup() {
AltTabPopup.prototype = { AltTabPopup.prototype = {
_init : function() { _init : function() {
this.actor = new Shell.GenericContainer({ name: 'altTabPopup', this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
reactive: true }); reactive: true,
visible: false });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth)); 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('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
@ -49,6 +52,8 @@ AltTabPopup.prototype = {
this._thumbnailTimeoutId = 0; this._thumbnailTimeoutId = 0;
this._motionTimeoutId = 0; this._motionTimeoutId = 0;
this.thumbnailsVisible = false;
// Initially disable hover so we ignore the enter-event if // Initially disable hover so we ignore the enter-event if
// the switcher appears underneath the current pointer location // the switcher appears underneath the current pointer location
this._disableHover(); this._disableHover();
@ -132,7 +137,7 @@ AltTabPopup.prototype = {
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside)); this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll)); this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
this._appSwitcher = new AppSwitcher(apps); this._appSwitcher = new AppSwitcher(apps, this);
this.actor.add_actor(this._appSwitcher.actor); this.actor.add_actor(this._appSwitcher.actor);
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated)); this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered)); this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
@ -365,15 +370,18 @@ AltTabPopup.prototype = {
}, },
destroy : function() { destroy : function() {
Tweener.addTween(this.actor, if (this.actor.visible) {
{ opacity: 0, Tweener.addTween(this.actor,
time: POPUP_FADE_TIME, { opacity: 0,
transition: 'easeOutQuad', time: POPUP_FADE_TIME,
onComplete: Lang.bind(this, transition: 'easeOutQuad',
function() { onComplete: Lang.bind(this,
this.actor.destroy(); function() {
}) this.actor.destroy();
}); })
});
} else
this.actor.destroy();
}, },
_onDestroy : function() { _onDestroy : function() {
@ -453,11 +461,15 @@ AltTabPopup.prototype = {
}, },
_destroyThumbnails : function() { _destroyThumbnails : function() {
Tweener.addTween(this._thumbnails.actor, let thumbnailsActor = this._thumbnails.actor;
Tweener.addTween(thumbnailsActor,
{ opacity: 0, { opacity: 0,
time: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad', transition: 'easeOutQuad',
onComplete: function() { this.destroy(); } onComplete: Lang.bind(this, function() {
thumbnailsActor.destroy();
this.thumbnailsVisible = false;
})
}); });
this._thumbnails = null; this._thumbnails = null;
}, },
@ -473,7 +485,8 @@ AltTabPopup.prototype = {
Tweener.addTween(this._thumbnails.actor, Tweener.addTween(this._thumbnails.actor,
{ opacity: 255, { opacity: 255,
time: THUMBNAIL_FADE_TIME, time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad' transition: 'easeOutQuad',
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
}); });
} }
}; };
@ -587,16 +600,20 @@ SwitcherList.prototype = {
this._list.add_actor(bbox); this._list.add_actor(bbox);
let n = this._items.length; let n = this._items.length;
bbox.connect('clicked', Lang.bind(this, function () { bbox.connect('clicked', Lang.bind(this, function() { this._onItemClicked(n); }));
this._itemActivated(n); bbox.connect('enter-event', Lang.bind(this, function() { this._onItemEnter(n); }));
}));
bbox.connect('enter-event', Lang.bind(this, function () {
this._itemEntered(n);
}));
this._items.push(bbox); this._items.push(bbox);
}, },
_onItemClicked: function (index) {
this._itemActivated(index);
},
_onItemEnter: function (index) {
this._itemEntered(index);
},
addSeparator: function () { addSeparator: function () {
let box = new St.Bin({ style_class: 'separator' }); let box = new St.Bin({ style_class: 'separator' });
this._separator = box; this._separator = box;
@ -604,16 +621,18 @@ SwitcherList.prototype = {
}, },
highlight: function(index, justOutline) { highlight: function(index, justOutline) {
if (this._highlighted != -1) if (this._highlighted != -1) {
this._items[this._highlighted].style_class = 'item-box'; this._items[this._highlighted].remove_style_pseudo_class('outlined');
this._items[this._highlighted].remove_style_pseudo_class('selected');
}
this._highlighted = index; this._highlighted = index;
if (this._highlighted != -1) { if (this._highlighted != -1) {
if (justOutline) if (justOutline)
this._items[this._highlighted].style_class = 'outlined-item-box'; this._items[this._highlighted].add_style_pseudo_class('outlined');
else else
this._items[this._highlighted].style_class = 'selected-item-box'; this._items[this._highlighted].add_style_pseudo_class('selected');
} }
let monitor = global.get_primary_monitor(); let monitor = global.get_primary_monitor();
@ -813,14 +832,14 @@ AppIcon.prototype = {
} }
}; };
function AppSwitcher(apps) { function AppSwitcher(apps, altTabPopup) {
this._init(apps); this._init(apps, altTabPopup);
} }
AppSwitcher.prototype = { AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype, __proto__ : SwitcherList.prototype,
_init : function(apps) { _init : function(apps, altTabPopup) {
SwitcherList.prototype._init.call(this, true); SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, sort by time, add to the popup // Construct the AppIcons, sort by time, add to the popup
@ -852,6 +871,8 @@ AppSwitcher.prototype = {
this._curApp = -1; this._curApp = -1;
this._iconSize = 0; this._iconSize = 0;
this._altTabPopup = altTabPopup;
this._mouseTimeOutId = 0;
}, },
_getPreferredHeight: function (actor, forWidth, alloc) { _getPreferredHeight: function (actor, forWidth, alloc) {
@ -859,17 +880,19 @@ AppSwitcher.prototype = {
while(this._items.length > 1 && this._items[j].style_class != 'item-box') { while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++; j++;
} }
let iconPadding = this._items[j].get_theme_node().get_horizontal_padding(); let themeNode = this._items[j].get_theme_node();
let iconPadding = themeNode.get_horizontal_padding();
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1); let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = iconNaturalHeight + iconPadding; let iconSpacing = iconNaturalHeight + iconPadding + iconBorder;
let totalSpacing = this._list.spacing * (this._items.length - 1); let totalSpacing = this._list.spacing * (this._items.length - 1);
if (this._separator) if (this._separator)
totalSpacing += this._separator.width + this._list.spacing; totalSpacing += this._separator.width + this._list.spacing;
// We just assume the whole screen here due to weirdness happing with the passed width // We just assume the whole screen here due to weirdness happing with the passed width
let focus = global.get_focus_monitor(); let primary = global.get_primary_monitor();
let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding(); let parentPadding = this.actor.get_parent().get_theme_node().get_horizontal_padding();
let availWidth = focus.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding(); let availWidth = primary.width - parentPadding - this.actor.get_theme_node().get_horizontal_padding();
let height = 0; let height = 0;
for(let i = 0; i < iconSizes.length; i++) { for(let i = 0; i < iconSizes.length; i++) {
@ -914,6 +937,29 @@ AppSwitcher.prototype = {
} }
}, },
// We override SwitcherList's _onItemEnter method to delay
// activation when the thumbnail list is open
_onItemEnter: function (index) {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
Lang.bind(this, function () {
this._enterItem(index);
this._mouseTimeOutId = 0;
return false;
}));
} else
this._itemEntered(index);
},
_enterItem: function(index) {
let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor))
this._itemEntered(index);
},
// We override SwitcherList's highlight() method to also deal with // We override SwitcherList's highlight() method to also deal with
// the AppSwitcher->ThumbnailList arrows. Apps with only 1 window // the AppSwitcher->ThumbnailList arrows. Apps with only 1 window
// will hide their arrows by default, but show them when their // will hide their arrows by default, but show them when their

View File

@ -40,9 +40,18 @@ AlphabeticalView.prototype = {
this.actor = new St.ScrollView({ x_fill: true, this.actor = new St.ScrollView({ x_fill: true,
y_fill: false, y_fill: false,
y_align: St.Align.START, y_align: St.Align.START,
vshadows: true }); vfade: true });
this.actor.add_actor(box); this.actor.add_actor(box);
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this.actor.connect('notify::mapped', Lang.bind(this,
function() {
if (!this.actor.mapped)
return;
let adjustment = this.actor.vscroll.adjustment;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(adjustment, direction);
}));
}, },
_removeAll: function() { _removeAll: function() {
@ -214,14 +223,20 @@ BaseAppSearchProvider.prototype = {
'icon': app.create_icon_texture(Search.RESULT_ICON_SIZE)}; 'icon': app.create_icon_texture(Search.RESULT_ICON_SIZE)};
}, },
activateResult: function(id) { activateResult: function(id, params) {
params = Params.parse(params, { workspace: null,
timestamp: null });
let app = this._appSys.get_app(id); let app = this._appSys.get_app(id);
app.activate(); app.activate(params.workspace ? params.workspace.index() : -1);
}, },
dragActivateResult: function(id) { dragActivateResult: function(id, params) {
params = Params.parse(params, { workspace: null,
timestamp: null });
let app = this._appSys.get_app(id); let app = this._appSys.get_app(id);
app.open_new_window(); app.open_new_window(params.workspace ? params.workspace.get_index() : -1);
} }
}; };
@ -281,21 +296,21 @@ PrefsSearchProvider.prototype = {
} }
}; };
function AppIcon(app) { function AppIcon(app, params) {
this._init(app); this._init(app, params);
} }
AppIcon.prototype = { AppIcon.prototype = {
__proto__: IconGrid.BaseIcon.prototype, __proto__: IconGrid.BaseIcon.prototype,
_init : function(app) { _init : function(app, params) {
this.app = app; this.app = app;
let label = this.app.get_name(); let label = this.app.get_name();
IconGrid.BaseIcon.prototype._init.call(this, IconGrid.BaseIcon.prototype._init.call(this,
label, label,
{ setSizeManually: true }); params);
}, },
createIcon: function(iconSize) { createIcon: function(iconSize) {
@ -303,12 +318,12 @@ AppIcon.prototype = {
} }
}; };
function AppWellIcon(app) { function AppWellIcon(app, iconParams) {
this._init(app); this._init(app, iconParams);
} }
AppWellIcon.prototype = { AppWellIcon.prototype = {
_init : function(app) { _init : function(app, iconParams) {
this.app = app; this.app = app;
this.actor = new St.Clickable({ style_class: 'app-well-app', this.actor = new St.Clickable({ style_class: 'app-well-app',
reactive: true, reactive: true,
@ -316,7 +331,7 @@ AppWellIcon.prototype = {
y_fill: true }); y_fill: true });
this.actor._delegate = this; this.actor._delegate = this;
this.icon = new AppIcon(app); this.icon = new AppIcon(app, iconParams);
this.actor.set_child(this.icon.actor); this.actor.set_child(this.icon.actor);
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
@ -388,7 +403,7 @@ AppWellIcon.prototype = {
if (newWorkspace != null) { if (newWorkspace != null) {
newWorkspace.activate(global.get_current_time()); newWorkspace.activate(global.get_current_time());
this.emit('launching'); this.emit('launching');
this.app.open_new_window(); this.app.open_new_window(-1);
Main.overview.hide(); Main.overview.hide();
} }
} else if (button == 3) { } else if (button == 3) {
@ -476,9 +491,9 @@ AppWellIcon.prototype = {
if (modifiers & Clutter.ModifierType.CONTROL_MASK if (modifiers & Clutter.ModifierType.CONTROL_MASK
&& this.app.state == Shell.AppState.RUNNING) { && this.app.state == Shell.AppState.RUNNING) {
this.app.open_new_window(); this.app.open_new_window(-1);
} else { } else {
this.app.activate(); this.app.activate(-1);
} }
Main.overview.hide(); Main.overview.hide();
}, },
@ -488,8 +503,11 @@ AppWellIcon.prototype = {
return this._menu.menuEventFilter(event); return this._menu.menuEventFilter(event);
}, },
shellWorkspaceLaunch : function() { shellWorkspaceLaunch : function(params) {
this.app.open_new_window(); params = Params.parse(params, { workspace: null,
timestamp: null });
this.app.open_new_window(params.workspace ? params.workspace.index() : -1);
}, },
getDragActor: function() { getDragActor: function() {
@ -621,7 +639,7 @@ AppIconMenu.prototype = {
}, },
_findMetaWindowForActor: function (actor) { _findMetaWindowForActor: function (actor) {
if (actor._delegate instanceof Workspace.WindowClone) if (actor._delegate.metaWindow)
return actor._delegate.metaWindow; return actor._delegate.metaWindow;
else if (actor.get_meta_window) else if (actor.get_meta_window)
return actor.get_meta_window(); return actor.get_meta_window();
@ -658,7 +676,7 @@ AppIconMenu.prototype = {
let metaWindow = child._window; let metaWindow = child._window;
this.emit('activate-window', metaWindow); this.emit('activate-window', metaWindow);
} else if (child == this._newWindowMenuItem) { } else if (child == this._newWindowMenuItem) {
this._source.app.open_new_window(); this._source.app.open_new_window(-1);
this.emit('activate-window', null); this.emit('activate-window', null);
} else if (child == this._toggleFavoriteMenuItem) { } else if (child == this._toggleFavoriteMenuItem) {
let favs = AppFavorites.getAppFavorites(); let favs = AppFavorites.getAppFavorites();

View File

@ -27,6 +27,7 @@ BoxPointer.prototype = {
_init: function(arrowSide, binProperties) { _init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide; this._arrowSide = arrowSide;
this._arrowOrigin = 0; this._arrowOrigin = 0;
this._arrowCorner = null;
this.actor = new St.Bin({ x_fill: true, this.actor = new St.Bin({ x_fill: true,
y_fill: true }); y_fill: true });
this._container = new Shell.GenericContainer(); this._container = new Shell.GenericContainer();
@ -212,47 +213,140 @@ BoxPointer.prototype = {
cr.translate(rise, 0); cr.translate(rise, 0);
} }
cr.moveTo(borderRadius, halfBorder); let [x1, y1] = [halfBorder, halfBorder];
let [x2, y2] = [boxWidth - halfBorder, boxHeight - halfBorder];
cr.moveTo(x1 + borderRadius, y1);
if (this._arrowSide == St.Side.TOP) { if (this._arrowSide == St.Side.TOP) {
cr.lineTo(this._arrowOrigin - halfBase, halfBorder); if (this._arrowCorner == St.Corner.TOPLEFT) {
cr.lineTo(this._arrowOrigin, halfBorder - rise); cr.moveTo(x1, y1);
cr.lineTo(this._arrowOrigin + halfBase, halfBorder); cr.lineTo(x1, y1 - rise);
} cr.lineTo(x1 + halfBase, y1);
cr.lineTo(boxWidth - borderRadius, halfBorder); cr.lineTo(x2 - borderRadius, y1);
} else if (this._arrowCorner == St.Corner.TOPRIGHT) {
cr.lineTo(x2 - halfBase, y1);
cr.lineTo(x2, y1 - rise);
} else if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
cr.lineTo(this._arrowOrigin, y1);
cr.lineTo(this._arrowOrigin, y1 - rise);
cr.lineTo(this._arrowOrigin + halfBase, y1);
cr.lineTo(x2 - borderRadius, y1);
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
cr.lineTo(this._arrowOrigin - halfBase, y1);
cr.lineTo(this._arrowOrigin, y1 - rise);
cr.lineTo(this._arrowOrigin, y1);
cr.lineTo(x2 - borderRadius, y1);
} else {
cr.lineTo(this._arrowOrigin - halfBase, y1);
cr.lineTo(this._arrowOrigin, y1 - rise);
cr.lineTo(this._arrowOrigin + halfBase, y1);
cr.lineTo(x2 - borderRadius, y1);
}
} else
cr.lineTo(x2 - borderRadius, y1);
cr.arc(boxWidth - borderRadius - halfBorder, borderRadius + halfBorder, borderRadius, // top-right corner
3*Math.PI/2, Math.PI*2); if (this._arrowCorner != St.Corner.TOPRIGHT)
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
3*Math.PI/2, Math.PI*2);
if (this._arrowSide == St.Side.RIGHT) { if (this._arrowSide == St.Side.RIGHT) {
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin - halfBase); if (this._arrowCorner == St.Corner.TOPRIGHT) {
cr.lineTo(boxWidth - halfBorder + rise, this._arrowOrigin); cr.lineTo(x2, y1);
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin + halfBase); cr.lineTo(x2 + rise, y1);
} cr.lineTo(x2, y1 + halfBase);
cr.lineTo(boxWidth - halfBorder, boxHeight - borderRadius); cr.lineTo(x2, y2 - borderRadius);
} else if (this._arrowCorner == St.Corner.BOTTOMRIGHT) {
cr.moveTo(x2, y2 - halfBase);
cr.lineTo(x2 + rise, y2);
} else if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
cr.lineTo(x2, this._arrowOrigin);
cr.lineTo(x2 + rise, this._arrowOrigin);
cr.lineTo(x2, this._arrowOrigin + halfBase);
cr.lineTo(x2, y2 - borderRadius);
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
cr.lineTo(x2, this._arrowOrigin - halfBase);
cr.lineTo(x2 + rise, this._arrowOrigin);
cr.lineTo(x2, this._arrowOrigin);
cr.lineTo(x2, y2 - borderRadius);
} else {
cr.lineTo(x2, this._arrowOrigin - halfBase);
cr.lineTo(x2 + rise, this._arrowOrigin);
cr.lineTo(x2, this._arrowOrigin + halfBase);
cr.lineTo(x2, y2 - borderRadius);
}
} else
cr.lineTo(x2, y2 - borderRadius);
cr.arc(boxWidth - borderRadius - halfBorder, boxHeight - borderRadius - halfBorder, borderRadius, // bottom-right corner
0, Math.PI/2); if (this._arrowCorner != St.Corner.BOTTOMRIGHT)
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
0, Math.PI/2);
if (this._arrowSide == St.Side.BOTTOM) { if (this._arrowSide == St.Side.BOTTOM) {
cr.lineTo(this._arrowOrigin + halfBase, boxHeight - halfBorder); if (this._arrowCorner == St.Corner.BOTTOMLEFT) {
cr.lineTo(this._arrowOrigin, boxHeight - halfBorder + rise); cr.lineTo(x1 + halfBase, y2);
cr.lineTo(this._arrowOrigin - halfBase, boxHeight - halfBorder); cr.lineTo(x1, y2 + rise);
} } else if (this._arrowCorner == St.Corner.BOTTOMRIGHT) {
cr.lineTo(borderRadius, boxHeight - halfBorder); cr.lineTo(x2, y2 + rise);
cr.lineTo(x2 - halfBase, y2);
cr.lineTo(x1 + borderRadius, y2);
} else if (this._arrowOrigin < (x1 + (borderRadius + halfBase))) {
cr.lineTo(this._arrowOrigin + halfBase, y2);
cr.lineTo(this._arrowOrigin, y2 + rise);
cr.lineTo(this._arrowOrigin, y2);
cr.lineTo(x1 + borderRadius, y2);
} else if (this._arrowOrigin > (x2 - (borderRadius + halfBase))) {
cr.lineTo(this._arrowOrigin, y2);
cr.lineTo(this._arrowOrigin, y2 + rise);
cr.lineTo(this._arrowOrigin - halfBase, y2);
cr.lineTo(x1 + borderRadius, y2);
} else {
cr.lineTo(this._arrowOrigin + halfBase, y2);
cr.lineTo(this._arrowOrigin, y2 + rise);
cr.lineTo(this._arrowOrigin - halfBase, y2);
cr.lineTo(x1 + borderRadius, y2);
}
} else
cr.lineTo(x1 + borderRadius, y2);
cr.arc(borderRadius + halfBorder, boxHeight - borderRadius - halfBorder, borderRadius, // bottom-left corner
Math.PI/2, Math.PI); if (this._arrowCorner != St.Corner.BOTTOMLEFT)
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
Math.PI/2, Math.PI);
if (this._arrowSide == St.Side.LEFT) { if (this._arrowSide == St.Side.LEFT) {
cr.lineTo(halfBorder, this._arrowOrigin + halfBase); if (this._arrowCorner == St.Corner.TOPLEFT) {
cr.lineTo(halfBorder - rise, this._arrowOrigin); cr.lineTo(x2, y1 + halfBase);
cr.lineTo(halfBorder, this._arrowOrigin - halfBase); cr.lineTo(x1 - rise, y1);
} } else if (this._arrowCorner == St.Corner.BOTTOMLEFT) {
cr.lineTo(halfBorder, borderRadius); cr.lineTo(x1 + rise, y2);
cr.moveTo(x1, y2 - halfBase);
} else if (this._arrowOrigin < (y1 + (borderRadius + halfBase))) {
cr.lineTo(x1, this._arrowOrigin + halfBase);
cr.lineTo(x1 - rise, this._arrowOrigin);
cr.lineTo(x1, this._arrowOrigin);
cr.lineTo(x1, y1 + borderRadius);
} else if (this._arrowOrigin > (y2 - (borderRadius + halfBase))) {
cr.lineTo(x1, this._arrowOrigin);
cr.lineTo(x1 - rise, this._arrowOrigin);
cr.lineTo(x1, this._arrowOrigin - halfBase);
cr.lineTo(x1, y1 + borderRadius);
} else {
cr.lineTo(x1, this._arrowOrigin + halfBase);
cr.lineTo(x1 - rise, this._arrowOrigin);
cr.lineTo(x1, this._arrowOrigin - halfBase);
cr.lineTo(x1, y1 + borderRadius);
}
} else
cr.lineTo(x1, y1 + borderRadius);
cr.arc(borderRadius + halfBorder, borderRadius + halfBorder, borderRadius, // top-left corner
Math.PI, 3*Math.PI/2); if (this._arrowCorner != St.Corner.TOPLEFT)
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
Math.PI, 3*Math.PI/2);
else
cr.lineTo(x1, y1);
Clutter.cairo_set_source_color(cr, backgroundColor); Clutter.cairo_set_source_color(cr, backgroundColor);
cr.fillPreserve(); cr.fillPreserve();
@ -269,7 +363,7 @@ BoxPointer.prototype = {
// Position correctly relative to the sourceActor // Position correctly relative to the sourceActor
let [sourceX, sourceY] = sourceActor.get_transformed_position(); let [sourceX, sourceY] = sourceActor.get_transformed_position();
let [sourceWidth, sourceHeight] = sourceActor.get_transformed_size(); let [sourceWidth, sourceHeight] = sourceActor.get_transformed_size();
let [sourceCenterX, sourceCenterY] = [sourceX + (sourceWidth / 2), sourceY + (sourceHeight / 2)];
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size(); let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
// We also want to keep it onscreen, and separated from the // We also want to keep it onscreen, and separated from the
@ -277,10 +371,14 @@ BoxPointer.prototype = {
// separated from its sourceActor // separated from its sourceActor
let primary = global.get_primary_monitor(); let primary = global.get_primary_monitor();
let themeNode = this.actor.get_theme_node(); let themeNode = this.actor.get_theme_node();
let arrowRise = themeNode.get_length('-arrow-rise'); let halfBorder = themeNode.get_length('-arrow-border-width') / 2;
let halfBase = themeNode.get_length('-arrow-base') / 2;
let borderRadius = themeNode.get_length('-arrow-border-radius'); let borderRadius = themeNode.get_length('-arrow-border-radius');
let margin = 2 * borderRadius + halfBorder;
let resX, resY; let resX, resY;
this._arrowCorner = null;
switch (this._arrowSide) { switch (this._arrowSide) {
case St.Side.TOP: case St.Side.TOP:
@ -304,40 +402,58 @@ BoxPointer.prototype = {
case St.Side.BOTTOM: case St.Side.BOTTOM:
switch (alignment) { switch (alignment) {
case St.Align.START: case St.Align.START:
resX = sourceX - 2 * borderRadius; resX = sourceCenterX - (halfBase + borderRadius + halfBorder);
break; break;
case St.Align.MIDDLE: case St.Align.MIDDLE:
resX = sourceX - Math.floor((natWidth - sourceWidth) / 2); resX = sourceCenterX - (natWidth / 2);
break; break;
case St.Align.END: case St.Align.END:
resX = sourceX - (natWidth - sourceWidth) + 2 * borderRadius; resX = sourceCenterX - natWidth + (halfBase + borderRadius + halfBorder);
break; break;
} }
if (sourceCenterX < margin) {
// Not enough space to the top
this._arrowCorner = (this._arrowSide == St.Side.TOP) ? St.Corner.TOPLEFT : St.Corner.BOTTOMLEFT;
resX = primary.x + 10;
} else if (sourceCenterX > (primary.x + primary.width - margin)) {
// Not enough space to the botom
this._arrowCorner = (this._arrowSide == St.Side.TOP) ? St.Corner.TOPRIGHT : St.Corner.BOTTOMRIGHT;
resX = primary.x + primary.width - (10 + natWidth);
}
resX = Math.min(resX, primary.x + primary.width - natWidth - arrowRise - gap); resX = Math.max(resX, primary.x + 10);
resX = Math.max(resX, primary.x); resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
this.setArrowOrigin(sourceCenterX - resX);
this.setArrowOrigin((sourceX - resX) + Math.floor(sourceWidth / 2));
break; break;
case St.Side.LEFT: case St.Side.LEFT:
case St.Side.RIGHT: case St.Side.RIGHT:
switch (alignment) { switch (alignment) {
case St.Align.START: case St.Align.START:
resY = sourceY - 2 * borderRadius; resY = sourceCenterY - (halfBase + borderRadius + halfBorder);
break; break;
case St.Align.MIDDLE: case St.Align.MIDDLE:
resY = sourceY - Math.floor((natHeight - sourceHeight) / 2); resY = sourceCenterY - (natHeight / 2);
break; break;
case St.Align.END: case St.Align.END:
resY = sourceY - (natHeight - sourceHeight) + 2 * borderRadius; resY = sourceCenterY - natHeight + (halfBase + borderRadius + halfBorder);
break; break;
} }
if (sourceCenterY < margin) {
// Not enough space to the left
this._arrowCorner = (this._arrowSide == St.Side.LEFT) ? St.Corner.TOPLEFT : St.Corner.TORIGHT;
resY = 10;
}
else if (sourceCenterY > (primary.y + primary.height - margin)) {
// Not enough space to the right
this._arrowCorner = (this._arrowSide == St.Side.LEFT) ? St.Corner.BOTTOMLEFT : St.Corner.BOTTOMRIGHT;
resY = primary.y + primary.height - (10 + natHeight);
}
resY = Math.min(resY, primary.y + primary.height - natHeight - arrowRise - gap); resY = Math.max(resY, primary.y + 10);
resY = Math.max(resY, primary.y); resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
this.setArrowOrigin((sourceY - resY) + Math.floor(sourceHeight / 2)); this.setArrowOrigin(sourceCenterY - resY);
break; break;
} }

View File

@ -4,19 +4,78 @@ const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Lang = imports.lang; const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Signals = imports.signals;
const Pango = imports.gi.Pango; const Pango = imports.gi.Pango;
const Gettext_gtk30 = imports.gettext.domain('gtk30'); const Gettext_gtk30 = imports.gettext.domain('gtk30');
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const MSECS_IN_DAY = 24 * 60 * 60 * 1000; const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const WEEKDATE_HEADER_WIDTH_DIGITS = 3; const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
const SHOW_WEEKDATE_KEY = 'show-weekdate'; const SHOW_WEEKDATE_KEY = 'show-weekdate';
// in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format';
function _sameDay(dateA, dateB) { function _sameDay(dateA, dateB) {
return (dateA.getDate() == dateB.getDate() && return (dateA.getDate() == dateB.getDate() &&
dateA.getMonth() == dateB.getMonth() && dateA.getMonth() == dateB.getMonth() &&
dateA.getYear() == dateB.getYear()); dateA.getYear() == dateB.getYear());
} }
function _sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear());
}
/* TODO: maybe needs config - right now we assume that Saturday and
* Sunday are non-work days (not true in e.g. Israel, it's Sunday and
* Monday there)
*/
function _isWorkDay(date) {
return date.getDay() != 0 && date.getDay() != 6;
}
function _getBeginningOfDay(date) {
let ret = new Date(date.getTime());
ret.setHours(0);
ret.setMinutes(0);
ret.setSeconds(0);
ret.setMilliseconds(0);
return ret;
}
function _getEndOfDay(date) {
let ret = new Date(date.getTime());
ret.setHours(23);
ret.setMinutes(59);
ret.setSeconds(59);
ret.setMilliseconds(999);
return ret;
}
function _formatEventTime(event, clockFormat) {
let ret;
if (event.allDay) {
/* Translators: Shown in calendar event list for all day events */
ret = _("All Day");
} else {
switch (clockFormat) {
case '24h':
ret = event.date.toLocaleFormat('%H:%M');
break;
default:
/* explicit fall-through */
case '12h':
ret = event.date.toLocaleFormat('%l:%M %p');
break;
}
}
return ret;
}
function _getCalendarWeekForDate(date) { function _getCalendarWeekForDate(date) {
// Based on the algorithms found here: // Based on the algorithms found here:
// http://en.wikipedia.org/wiki/Talk:ISO_week_date // http://en.wikipedia.org/wiki/Talk:ISO_week_date
@ -43,12 +102,259 @@ function _getDigitWidth(actor){
return width; return width;
} }
function Calendar() { function _getCalendarDayAbbreviation(dayNumber) {
let abbreviations = [
/* Translators: Calendar grid abbreviation for Sunday.
*
* NOTE: These abbreviations are always shown together and in
* order, e.g. "S M T W T F S".
*/
_("S"),
/* Translators: Calendar grid abbreviation for Monday */
_("M"),
/* Translators: Calendar grid abbreviation for Tuesday */
_("T"),
/* Translators: Calendar grid abbreviation for Wednesday */
_("W"),
/* Translators: Calendar grid abbreviation for Thursday */
_("T"),
/* Translators: Calendar grid abbreviation for Friday */
_("F"),
/* Translators: Calendar grid abbreviation for Saturday */
_("S")
];
return abbreviations[dayNumber];
}
function _getEventDayAbbreviation(dayNumber) {
let abbreviations = [
/* Translators: Event list abbreviation for Sunday.
*
* NOTE: These abbreviations are normally not shown together
* so they need to be unique (e.g. Tuesday and Thursday cannot
* both be 'T').
*/
_("Su"),
/* Translators: Event list abbreviation for Monday */
_("M"),
/* Translators: Event list abbreviation for Tuesday */
_("T"),
/* Translators: Event list abbreviation for Wednesday */
_("W"),
/* Translators: Event list abbreviation for Thursday */
_("Th"),
/* Translators: Event list abbreviation for Friday */
_("F"),
/* Translators: Event list abbreviation for Saturday */
_("S")
];
return abbreviations[dayNumber];
}
// Abstraction for an appointment/event in a calendar
function CalendarEvent(date, summary, allDay) {
this._init(date, summary, allDay);
}
CalendarEvent.prototype = {
_init: function(date, summary, allDay) {
this.date = date;
this.summary = summary;
this.allDay = allDay;
}
};
// Interface for appointments/events - e.g. the contents of a calendar
//
// First, an implementation with no events
function EmptyEventSource() {
this._init(); this._init();
} }
Calendar.prototype = { EmptyEventSource.prototype = {
_init: function() { _init: function() {
},
requestRange: function(begin, end) {
},
getEvents: function(begin, end) {
let result = [];
return result;
},
hasEvents: function(day) {
return false;
}
};
Signals.addSignalMethods(EmptyEventSource.prototype);
// Second, wrap native Evolution event source
function EvolutionEventSource() {
this._init();
}
EvolutionEventSource.prototype = {
_init: function() {
this._native = new Shell.EvolutionEventSource();
this._native.connect('changed', Lang.bind(this, function() {
this.emit('changed');
}));
},
requestRange: function(begin, end) {
this._native.request_range(begin.getTime(), end.getTime());
},
getEvents: function(begin, end) {
let result = [];
let nativeEvents = this._native.get_events(begin.getTime(), end.getTime());
for (let n = 0; n < nativeEvents.length; n++) {
let nativeEvent = nativeEvents[n];
result.push(new CalendarEvent(new Date(nativeEvent.msec_begin), nativeEvent.summary, nativeEvent.all_day));
}
return result;
},
hasEvents: function(day) {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let events = this.getEvents(dayBegin, dayEnd);
if (events.length == 0)
return false;
return true;
}
};
Signals.addSignalMethods(EvolutionEventSource.prototype);
// Finally, an implementation with fake events
function FakeEventSource() {
this._init();
}
FakeEventSource.prototype = {
_init: function() {
this._fakeEvents = [];
// Generate fake events
//
let midnightToday = _getBeginningOfDay(new Date());
let summary = '';
// '10-oclock pow-wow' is an event occuring IN THE PAST every four days at 10am
for (let n = 0; n < 10; n++) {
let t = new Date(midnightToday.getTime() - n * 4 * 86400 * 1000);
t.setHours(10);
summary = '10-oclock pow-wow (n=' + n + ')';
this._fakeEvents.push(new CalendarEvent(t, summary, false));
}
// '11-oclock thing' is an event occuring every three days at 11am
for (let n = 0; n < 10; n++) {
let t = new Date(midnightToday.getTime() + n * 3 * 86400 * 1000);
t.setHours(11);
summary = '11-oclock thing (n=' + n + ')';
this._fakeEvents.push(new CalendarEvent(t, summary, false));
}
// 'Weekly Meeting' is an event occuring every seven days at 1:45pm (two days displaced)
for (let n = 0; n < 5; n++) {
let t = new Date(midnightToday.getTime() + (n * 7 + 2) * 86400 * 1000);
t.setHours(13);
t.setMinutes(45);
summary = 'Weekly Meeting (n=' + n + ')';
this._fakeEvents.push(new CalendarEvent(t, summary, false));
}
// 'Fun All Day' is an all-day event occuring every fortnight (three days displayed)
for (let n = 0; n < 10; n++) {
let t = new Date(midnightToday.getTime() + (n * 14 + 3) * 86400 * 1000);
summary = 'Fun All Day (n=' + n + ')';
this._fakeEvents.push(new CalendarEvent(t, summary, true));
}
// 'Get Married' is an event that actually reflects reality (Dec 4, 2010) :-)
this._fakeEvents.push(new CalendarEvent(new Date(2010, 11, 4, 16, 0), 'Get Married', false));
// ditto for 'NE Patriots vs NY Jets'
this._fakeEvents.push(new CalendarEvent(new Date(2010, 11, 6, 20, 30), 'NE Patriots vs NY Jets', false));
// An event for tomorrow @6:30pm that is added/removed every five
// seconds (to check that the ::changed signal works)
let transientEventDate = new Date(midnightToday.getTime() + 86400 * 1000);
transientEventDate.setHours(18);
transientEventDate.setMinutes(30);
transientEventDate.setSeconds(0);
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
this._includeTransientEvent = false;
this._transientEvent = new CalendarEvent(transientEventDate, 'A Transient Event', false);
this._transientEventCounter = 1;
},
_updateTransientEvent: function() {
this._includeTransientEvent = !this._includeTransientEvent;
this._transientEventCounter = this._transientEventCounter + 1;
this._transientEvent.summary = 'A Transient Event (' + this._transientEventCounter + ')';
this.emit('changed');
Mainloop.timeout_add(5000, Lang.bind(this, this._updateTransientEvent));
},
requestRange: function(begin, end) {
},
getEvents: function(begin, end) {
let result = [];
//log('begin:' + begin);
//log('end: ' + end);
for(let n = 0; n < this._fakeEvents.length; n++) {
let event = this._fakeEvents[n];
if (event.date >= begin && event.date <= end) {
result.push(event);
}
//log('when:' + event.date + ' summary:' + event.summary);
}
if (this._includeTransientEvent && this._transientEvent.date >= begin && this._transientEvent.date <= end)
result.push(this._transientEvent);
result.sort(function(event1, event2) {
return event1.date.getTime() - event2.date.getTime();
});
return result;
},
hasEvents: function(day) {
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let events = this.getEvents(dayBegin, dayEnd);
if (events.length == 0)
return false;
return true;
}
};
Signals.addSignalMethods(FakeEventSource.prototype);
// Calendar:
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
function Calendar(eventSource) {
this._init(eventSource);
}
Calendar.prototype = {
_init: function(eventSource) {
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, this._update));
// FIXME: This is actually the fallback method for GTK+ for the week start; // FIXME: This is actually the fallback method for GTK+ for the week start;
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably // GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
// should add a C function so we can do the full handling. // should add a C function so we can do the full handling.
@ -71,6 +377,7 @@ Calendar.prototype = {
} }
// Find the ordering for month/year in the calendar heading // Find the ordering for month/year in the calendar heading
this._headerFormatWithoutYear = '%B';
switch (Gettext_gtk30.gettext('calendar:MY')) { switch (Gettext_gtk30.gettext('calendar:MY')) {
case 'calendar:MY': case 'calendar:MY':
this._headerFormat = '%B %Y'; this._headerFormat = '%B %Y';
@ -85,7 +392,7 @@ Calendar.prototype = {
} }
// Start off with the current date // Start off with the current date
this.date = new Date(); this._selectedDate = new Date();
this.actor = new St.Table({ homogeneous: false, this.actor = new St.Table({ homogeneous: false,
style_class: 'calendar', style_class: 'calendar',
@ -100,9 +407,10 @@ Calendar.prototype = {
// Sets the calendar to show a specific date // Sets the calendar to show a specific date
setDate: function(date) { setDate: function(date) {
if (!_sameDay(date, this.date)) { if (!_sameDay(date, this._selectedDate)) {
this.date = date; this._selectedDate = date;
this._update(); this._update();
this.emit('selected-date-changed', new Date(this._selectedDate));
} }
}, },
@ -116,45 +424,36 @@ Calendar.prototype = {
{ row: 0, col: 0, col_span: offsetCols + 7 }); { row: 0, col: 0, col_span: offsetCols + 7 });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange)); this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange));
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' }); let back = new St.Button({ style_class: 'calendar-change-month-back' });
this._topBox.add(back); this._topBox.add(back);
back.connect('clicked', Lang.bind(this, this._prevMonth)); back.connect('clicked', Lang.bind(this, this._onPrevMonthButtonClicked));
this._dateLabel = new St.Label(); this._monthLabel = new St.Label({style_class: 'calendar-month-label'});
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE }); this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' }); let forward = new St.Button({ style_class: 'calendar-change-month-forward' });
this._topBox.add(forward); this._topBox.add(forward);
forward.connect('clicked', Lang.bind(this, this._nextMonth)); forward.connect('clicked', Lang.bind(this, this._onNextMonthButtonClicked));
// Add weekday labels...
//
// We need to figure out the abbreviated localized names for the days of the week; // We need to figure out the abbreviated localized names for the days of the week;
// we do this by just getting the next 7 days starting from right now and then putting // we do this by just getting the next 7 days starting from right now and then putting
// them in the right cell in the table. It doesn't matter if we add them in order // them in the right cell in the table. It doesn't matter if we add them in order
let iter = new Date(this.date); let iter = new Date(this._selectedDate);
iter.setSeconds(0); // Leap second protection. Hah! iter.setSeconds(0); // Leap second protection. Hah!
iter.setHours(12); iter.setHours(12);
if (this._useWeekdate) {
this._weekdateHeader = new St.Label();
this.actor.add(this._weekdateHeader,
{ row: 1,
col: 0,
x_fill: false, x_align: St.Align.MIDDLE });
this._setWeekdateHeaderWidth();
} else {
this._weekdateHeader = null;
}
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }), // Could use iter.toLocaleFormat('%a') but that normally gives three characters
// and we want, ideally, a single character for e.g. S M T W T F S
let customDayAbbrev = _getCalendarDayAbbreviation(iter.getDay());
let label = new St.Label({ style_class: 'calendar-day-base calendar-day-heading',
text: customDayAbbrev });
this.actor.add(label,
{ row: 1, { row: 1,
col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: St.Align.END }); x_fill: false, x_align: St.Align.MIDDLE });
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
} }
@ -178,33 +477,57 @@ Calendar.prototype = {
switch (event.get_scroll_direction()) { switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP: case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT: case Clutter.ScrollDirection.LEFT:
this._prevMonth(); this._onPrevMonthButtonClicked();
break; break;
case Clutter.ScrollDirection.DOWN: case Clutter.ScrollDirection.DOWN:
case Clutter.ScrollDirection.RIGHT: case Clutter.ScrollDirection.RIGHT:
this._nextMonth(); this._onNextMonthButtonClicked();
break; break;
} }
}, },
_prevMonth: function() { _onPrevMonthButtonClicked: function() {
if (this.date.getMonth() == 0) { let newDate = new Date(this._selectedDate);
this.date.setMonth(11); let oldMonth = newDate.getMonth();
this.date.setFullYear(this.date.getFullYear() - 1); if (oldMonth == 0) {
} else { newDate.setMonth(11);
this.date.setMonth(this.date.getMonth() - 1); newDate.setFullYear(newDate.getFullYear() - 1);
if (newDate.getMonth() != 11) {
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
newDate = new Date(newDate.getFullYear() - 1, 11, day);
}
} }
this._update(); else {
newDate.setMonth(oldMonth - 1);
if (newDate.getMonth() != oldMonth - 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
newDate = new Date(newDate.getFullYear(), oldMonth - 1, day);
}
}
this.setDate(newDate);
}, },
_nextMonth: function() { _onNextMonthButtonClicked: function() {
if (this.date.getMonth() == 11) { let newDate = new Date(this._selectedDate);
this.date.setMonth(0); let oldMonth = newDate.getMonth();
this.date.setFullYear(this.date.getFullYear() + 1); if (oldMonth == 11) {
} else { newDate.setMonth(0);
this.date.setMonth(this.date.getMonth() + 1); newDate.setFullYear(newDate.getFullYear() + 1);
if (newDate.getMonth() != 0) {
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
newDate = new Date(newDate.getFullYear() + 1, 0, day);
}
} }
this._update(); else {
newDate.setMonth(oldMonth + 1);
if (newDate.getMonth() != oldMonth + 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
newDate = new Date(newDate.getFullYear(), oldMonth + 1, day);
}
}
this.setDate(newDate);
}, },
_onSettingsChange: function() { _onSettingsChange: function() {
@ -214,7 +537,12 @@ Calendar.prototype = {
}, },
_update: function() { _update: function() {
this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat); let now = new Date();
if (_sameYear(this._selectedDate, now))
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormatWithoutYear);
else
this._monthLabel.text = this._selectedDate.toLocaleFormat(this._headerFormat);
// Remove everything but the topBox and the weekday labels // Remove everything but the topBox and the weekday labels
let children = this.actor.get_children(); let children = this.actor.get_children();
@ -222,45 +550,215 @@ Calendar.prototype = {
children[i].destroy(); children[i].destroy();
// Start at the beginning of the week before the start of the month // Start at the beginning of the week before the start of the month
let iter = new Date(this.date); let beginDate = new Date(this._selectedDate);
iter.setDate(1); beginDate.setDate(1);
iter.setSeconds(0); beginDate.setSeconds(0);
iter.setHours(12); beginDate.setHours(12);
let daysToWeekStart = (7 + iter.getDay() - this._weekStart) % 7; let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
iter.setTime(iter.getTime() - daysToWeekStart * MSECS_IN_DAY); beginDate.setTime(beginDate.getTime() - daysToWeekStart * MSECS_IN_DAY);
let now = new Date();
let iter = new Date(beginDate);
let row = 2; let row = 2;
while (true) { while (true) {
let label = new St.Label({ text: iter.getDate().toString() }); let button = new St.Button({ label: iter.getDate().toString() });
if (_sameDay(now, iter))
label.style_class = 'calendar-day calendar-today'; let iterStr = iter.toUTCString();
else if (iter.getMonth() != this.date.getMonth()) button.connect('clicked', Lang.bind(this, function() {
label.style_class = 'calendar-day calendar-other-month-day'; let newlySelectedDate = new Date(iterStr);
this.setDate(newlySelectedDate);
}));
let hasEvents = this._eventSource.hasEvents(iter);
let styleClass = 'calendar-day-base calendar-day';
if (_isWorkDay(iter))
styleClass += ' calendar-work-day'
else else
label.style_class = 'calendar-day'; styleClass += ' calendar-nonwork-day'
// Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2)
styleClass = 'calendar-day-top ' + styleClass;
if (iter.getDay() == this._weekStart)
styleClass = 'calendar-day-left ' + styleClass;
if (_sameDay(now, iter))
styleClass += ' calendar-today';
else if (iter.getMonth() != this._selectedDate.getMonth())
styleClass += ' calendar-other-month-day';
if (_sameDay(this._selectedDate, iter))
button.add_style_pseudo_class('active');
if (hasEvents)
styleClass += ' calendar-day-with-events'
button.style_class = styleClass;
let offsetCols = this._useWeekdate ? 1 : 0; let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.add(label, this.actor.add(button,
{ row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7, { row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7 });
x_fill: false, x_align: St.Align.END });
if (this._useWeekdate && iter.getDay() == 4) { if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(), let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
style_class: 'calendar-day calendar-calendarweek'}); style_class: 'calendar-day-base calendar-week-number'});
this.actor.add(label, this.actor.add(label,
{ row: row, col: 0, { row: row, col: 0, y_align: St.Align.MIDDLE });
x_fill: false, x_align: St.Align.MIDDLE });
} }
iter.setTime(iter.getTime() + MSECS_IN_DAY); iter.setTime(iter.getTime() + MSECS_IN_DAY);
if (iter.getDay() == this._weekStart) { if (iter.getDay() == this._weekStart) {
// We stop on the first "first day of the week" after the month we are displaying // We stop on the first "first day of the week" after the month we are displaying
if (iter.getMonth() > this.date.getMonth() || iter.getYear() > this.date.getYear()) if (iter.getMonth() > this._selectedDate.getMonth() || iter.getYear() > this._selectedDate.getYear())
break; break;
row++; row++;
} }
} }
// Signal to the event source that we are interested in events
// only from this date range
this._eventSource.requestRange(beginDate, iter);
}
};
Signals.addSignalMethods(Calendar.prototype);
function EventsList(eventSource) {
this._init(eventSource);
}
EventsList.prototype = {
_init: function(eventSource) {
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
this._date = new Date();
this._eventSource = eventSource;
this._eventSource.connect('changed', Lang.bind(this, this._update));
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._desktopSettings.connect('changed', Lang.bind(this, this._update));
let weekStartString = Gettext_gtk30.gettext('calendar:week_start:0');
if (weekStartString.indexOf('calendar:week_start:') == 0) {
this._weekStart = parseInt(weekStartString.substring(20));
}
if (isNaN(this._weekStart) ||
this._weekStart < 0 ||
this._weekStart > 6) {
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
this._weekStart = 0;
}
this._update();
},
_addEvent: function(dayNameBox, timeBox, eventTitleBox, includeDayName, day, time, desc) {
if (includeDayName) {
dayNameBox.add(new St.Label( { style_class: 'events-day-dayname',
text: day } ),
{ x_fill: true } );
}
timeBox.add(new St.Label( { style_class: 'events-day-time',
text: time} ),
{ x_fill: true } );
eventTitleBox.add(new St.Label( { style_class: 'events-day-task',
text: desc} ));
},
_addPeriod: function(header, begin, end, includeDayName, showNothingScheduled) {
let events = this._eventSource.getEvents(begin, end);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);;
if (events.length == 0 && !showNothingScheduled)
return;
let vbox = new St.BoxLayout( {vertical: true} );
this.actor.add(vbox);
vbox.add(new St.Label({ style_class: 'events-day-header', text: header }));
let box = new St.BoxLayout({style_class: 'events-header-hbox'});
let dayNameBox = new St.BoxLayout({ vertical: true, style_class: 'events-day-name-box' });
let timeBox = new St.BoxLayout({ vertical: true, style_class: 'events-time-box' });
let eventTitleBox = new St.BoxLayout({ vertical: true, style_class: 'events-event-box' });
box.add(dayNameBox, {x_fill: false});
box.add(timeBox, {x_fill: false});
box.add(eventTitleBox, {expand: true});
vbox.add(box);
for (let n = 0; n < events.length; n++) {
let event = events[n];
let dayString = _getEventDayAbbreviation(event.date.getDay());
let timeString = _formatEventTime(event, clockFormat);
let summaryString = event.summary;
this._addEvent(dayNameBox, timeBox, eventTitleBox, includeDayName, dayString, timeString, summaryString);
}
if (events.length == 0 && showNothingScheduled) {
let now = new Date();
/* Translators: Text to show if there are no events */
let nothingEvent = new CalendarEvent(now, _("Nothing Scheduled"), true);
let timeString = _formatEventTime(nothingEvent, clockFormat);
this._addEvent(dayNameBox, timeBox, eventTitleBox, false, "", timeString, nothingEvent.summary);
}
},
_showOtherDay: function(day) {
this.actor.destroy_children();
let dayBegin = _getBeginningOfDay(day);
let dayEnd = _getEndOfDay(day);
let dayString;
let now = new Date();
if (_sameYear(day, now))
dayString = day.toLocaleFormat('%A, %B %d');
else
dayString = day.toLocaleFormat('%A, %B %d, %Y');
this._addPeriod(dayString, dayBegin, dayEnd, false, true);
},
_showToday: function() {
this.actor.destroy_children();
let now = new Date();
let dayBegin = _getBeginningOfDay(now);
let dayEnd = _getEndOfDay(now);
this._addPeriod(_("Today"), dayBegin, dayEnd, false, true);
let tomorrowBegin = new Date(dayBegin.getTime() + 86400 * 1000);
let tomorrowEnd = new Date(dayEnd.getTime() + 86400 * 1000);
this._addPeriod(_("Tomorrow"), tomorrowBegin, tomorrowEnd, false, true);
if (dayEnd.getDay() <= 4 + this._weekStart) {
/* If now is within the first 5 days we show "This week" and
* include events up until and including Saturday/Sunday
* (depending on whether a week starts on Sunday/Monday).
*/
let thisWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let thisWeekEnd = new Date(dayEnd.getTime() + (6 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
this._addPeriod(_("This week"), thisWeekBegin, thisWeekEnd, true, false);
} else {
/* otherwise it's one of the two last days of the week ... show
* "Next week" and include events up until and including *next*
* Saturday/Sunday
*/
let nextWeekBegin = new Date(dayBegin.getTime() + 2 * 86400 * 1000);
let nextWeekEnd = new Date(dayEnd.getTime() + (13 + this._weekStart - dayEnd.getDay()) * 86400 * 1000);
this._addPeriod(_("Next week"), nextWeekBegin, nextWeekEnd, true, false);
}
},
// Sets the event list to show events from a specific date
setDate: function(date) {
if (!_sameDay(date, this._date)) {
this._date = date;
this._update();
}
},
_update: function() {
let today = new Date();
if (_sameDay (this._date, today)) {
this._showToday();
} else {
this._showOtherDay(this._date);
}
} }
}; };

View File

@ -54,7 +54,7 @@ RemoveFavoriteIcon.prototype = {
if (source instanceof AppDisplay.AppWellIcon) { if (source instanceof AppDisplay.AppWellIcon) {
let appSystem = Shell.AppSystem.get_default(); let appSystem = Shell.AppSystem.get_default();
app = appSystem.get_app(source.getId()); app = appSystem.get_app(source.getId());
} else if (source instanceof Workspace.WindowClone) { } else if (source.metaWindow) {
let tracker = Shell.WindowTracker.get_default(); let tracker = Shell.WindowTracker.get_default();
app = tracker.get_window_app(source.metaWindow); app = tracker.get_window_app(source.metaWindow);
} }
@ -78,8 +78,6 @@ function Dash() {
Dash.prototype = { Dash.prototype = {
_init : function() { _init : function() {
this._menus = [];
this._menuDisplays = [];
this._maxHeight = -1; this._maxHeight = -1;
this._iconSize = 48; this._iconSize = 48;
@ -150,7 +148,7 @@ Dash.prototype = {
let app = null; let app = null;
if (dragEvent.source instanceof AppDisplay.AppWellIcon) if (dragEvent.source instanceof AppDisplay.AppWellIcon)
app = this._appSystem.get_app(dragEvent.source.getId()); app = this._appSystem.get_app(dragEvent.source.getId());
else if (dragEvent.source instanceof Workspace.WindowClone) else if (dragEvent.source.metaWindow)
app = this._tracker.get_window_app(dragEvent.source.metaWindow); app = this._tracker.get_window_app(dragEvent.source.metaWindow);
else else
return DND.DragMotionResult.CONTINUE; return DND.DragMotionResult.CONTINUE;
@ -193,7 +191,8 @@ Dash.prototype = {
}, },
_addApp: function(app) { _addApp: function(app) {
let display = new AppDisplay.AppWellIcon(app); let display = new AppDisplay.AppWellIcon(app,
{ setSizeManually: true });
display._draggable.connect('drag-begin', display._draggable.connect('drag-begin',
Lang.bind(this, function() { Lang.bind(this, function() {
display.actor.opacity = 50; display.actor.opacity = 50;
@ -207,7 +206,7 @@ Dash.prototype = {
_redisplay: function () { _redisplay: function () {
this._box.hide(); this._box.hide();
this._box.remove_all(); this._box.destroy_children();
let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
@ -266,14 +265,18 @@ Dash.prototype = {
let app = null; let app = null;
if (source instanceof AppDisplay.AppWellIcon) if (source instanceof AppDisplay.AppWellIcon)
app = this._appSystem.get_app(source.getId()); app = this._appSystem.get_app(source.getId());
else if (source instanceof Workspace.WindowClone) else if (source.metaWindow)
app = this._tracker.get_window_app(source.metaWindow); app = this._tracker.get_window_app(source.metaWindow);
// Don't allow favoriting of transient apps // Don't allow favoriting of transient apps
if (app == null || app.is_transient()) if (app == null || app.is_transient())
return DND.DragMotionResult.NO_DROP; return DND.DragMotionResult.NO_DROP;
let numFavorites = AppFavorites.getAppFavorites().getFavorites().length; let favorites = AppFavorites.getAppFavorites().getFavorites();
let numFavorites = favorites.length;
let favPos = favorites.indexOf(app);
let numChildren = this._box.get_children().length; let numChildren = this._box.get_children().length;
let boxHeight = this._box.height; let boxHeight = this._box.height;
@ -291,15 +294,16 @@ Dash.prototype = {
this._dragPlaceholderPos = pos; this._dragPlaceholderPos = pos;
if (this._dragPlaceholder) if (this._dragPlaceholder)
this._dragPlaceholder.destroy(); this._dragPlaceholder.destroy();
// Don't allow positioning before or after self
if (favPos != -1 && (pos == favPos || pos == favPos + 1))
return DND.DragMotionResult.CONTINUE;
this._dragPlaceholder = new St.Bin({ style_class: 'dash-placeholder' }); this._dragPlaceholder = new St.Bin({ style_class: 'dash-placeholder' });
this._box.insert_actor(this._dragPlaceholder, pos); this._box.insert_actor(this._dragPlaceholder, pos);
} }
let id = app.get_id(); let srcIsFavorite = (favPos != -1);
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
let srcIsFavorite = (id in favorites);
if (srcIsFavorite) if (srcIsFavorite)
return DND.DragMotionResult.MOVE_DROP; return DND.DragMotionResult.MOVE_DROP;
@ -312,7 +316,7 @@ Dash.prototype = {
let app = null; let app = null;
if (source instanceof AppDisplay.AppWellIcon) { if (source instanceof AppDisplay.AppWellIcon) {
app = this._appSystem.get_app(source.getId()); app = this._appSystem.get_app(source.getId());
} else if (source instanceof Workspace.WindowClone) { } else if (source.metaWindow) {
app = this._tracker.get_window_app(source.metaWindow); app = this._tracker.get_window_app(source.metaWindow);
} }

212
js/ui/dateMenu.js Normal file
View File

@ -0,0 +1,212 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Util = imports.misc.util;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar;
// in org.gnome.desktop.interface
const CLOCK_FORMAT_KEY = 'clock-format';
// in org.gnome.shell.clock
const CLOCK_SHOW_DATE_KEY = 'show-date';
const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
function _onVertSepRepaint (area)
{
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let stippleColor = new Clutter.Color();
let stippleWidth = themeNode.get_length('-stipple-width');
let x = Math.floor(width/2) + 0.5;
themeNode.lookup_color('-stipple-color', false, stippleColor);
cr.moveTo(x, 0);
cr.lineTo(x, height);
Clutter.cairo_set_source_color(cr, stippleColor);
cr.setDash([1, 3], 1); // Hard-code for now
cr.setLineWidth(stippleWidth);
cr.stroke();
};
function DateMenuButton() {
this._init();
}
DateMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
let item;
let hbox;
let vbox;
//this._eventSource = new Calendar.EmptyEventSource();
//this._eventSource = new Calendar.FakeEventSource();
this._eventSource = new Calendar.EvolutionEventSource();
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this._clock = new St.Label();
this.actor.set_child(this._clock);
hbox = new St.BoxLayout({name: 'calendarArea'});
this.menu.addActor(hbox);
// Fill up the first column
vbox = new St.BoxLayout({vertical: true});
hbox.add(vbox);
// Date
this._date = new St.Label();
this._date.style_class = 'datemenu-date-label';
vbox.add(this._date);
this._eventList = new Calendar.EventsList(this._eventSource);
// Calendar
this._calendar = new Calendar.Calendar(this._eventSource);
this._calendar.connect('selected-date-changed',
Lang.bind(this, function(calendar, date) {
this._eventList.setDate(date);
}));
vbox.add(this._calendar.actor);
item = new PopupMenu.PopupSeparatorMenuItem();
item.setColumnWidths(1);
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
item = new PopupMenu.PopupMenuItem(_("Date and Time Settings"));
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
vbox.add(item.actor);
// Add vertical separator
item = new St.DrawingArea({ style_class: 'calendar-vertical-separator',
pseudo_class: 'highlighted' });
item.connect('repaint', Lang.bind(this, _onVertSepRepaint));
hbox.add(item);
// Fill up the second column
vbox = new St.BoxLayout({vertical: true});
hbox.add(vbox);
// Event list
vbox.add(this._eventList.actor);
item = new PopupMenu.PopupMenuItem(_("Open Calendar"));
item.connect('activate', Lang.bind(this, this._onOpenCalendarActivate));
vbox.add(item.actor, {y_align: St.Align.END, expand: true, y_fill: false});
// Whenever the menu is opened, select today
this.menu.connect('open-state-changed', Lang.bind(this, function(menu, isOpen) {
if (isOpen) {
let now = new Date();
this._calendar.setDate(now);
// No need to update this._eventList as ::selected-date-changed
// signal will fire
}
}));
// Done with hbox for calendar and event list
// Track changes to clock settings
this._desktopSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
this._desktopSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
this._clockSettings.connect('changed', Lang.bind(this, this._updateClockAndDate));
// Start the clock
this._updateClockAndDate();
},
_updateClockAndDate: function() {
let format = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
let clockFormat;
let dateFormat;
switch (format) {
case '24h':
if (showDate)
/* Translators: This is the time format with date used
in 24-hour mode. */
clockFormat = showSeconds ? _("%a %b %e, %R:%S")
: _("%a %b %e, %R");
else
/* Translators: This is the time format without date used
in 24-hour mode. */
clockFormat = showSeconds ? _("%a %R:%S")
: _("%a %R");
break;
case '12h':
default:
if (showDate)
/* Translators: This is a time format with date used
for AM/PM. */
clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
: _("%a %b %e, %l:%M %p");
else
/* Translators: This is a time format without date used
for AM/PM. */
clockFormat = showSeconds ? _("%a %l:%M:%S %p")
: _("%a %l:%M %p");
break;
}
let displayDate = new Date();
let msecRemaining;
if (showSeconds) {
msecRemaining = 1000 - displayDate.getMilliseconds();
if (msecRemaining < 50) {
displayDate.setSeconds(displayDate.getSeconds() + 1);
msecRemaining += 1000;
}
} else {
msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
displayDate.getMilliseconds());
if (msecRemaining < 500) {
displayDate.setMinutes(displayDate.getMinutes() + 1);
msecRemaining += 60000;
}
}
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
/* Translators: This is the date format to use when the calendar popup is
* shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
*/
dateFormat = _("%A %B %e, %Y");
this._date.set_text(displayDate.toLocaleFormat(dateFormat));
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClockAndDate));
return false;
},
_onPreferencesActivate: function() {
this.menu.close();
Util.spawnDesktop('gnome-datetime-panel');
},
_onOpenCalendarActivate: function() {
this.menu.close();
// TODO: pass '-c calendar' (to force the calendar at startup)
// TODO: pass the selected day
Util.spawnDesktop('evolution');
},
};

View File

@ -101,6 +101,12 @@ _Draggable.prototype = {
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet. this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting). this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
// During the drag, we eat enter/leave events so that actors don't prelight or show
// tooltips. But we remember the relevant events (first leave, last enter) so we can
// fix up the hover state after the drag ends.
this._firstLeaveEvent = null;
this._lastEnterEvent = null;
this._eventsGrabbed = false; this._eventsGrabbed = false;
}, },
@ -198,6 +204,11 @@ _Draggable.prototype = {
this._cancelDrag(event.get_time()); this._cancelDrag(event.get_time());
return true; return true;
} }
} else if (event.type() == Clutter.EventType.LEAVE) {
if (this._firstLeaveEvent == null)
this._firstLeaveEvent = event;
} else if (event.type() == Clutter.EventType.ENTER) {
this._lastEnterEvent = event;
} }
return false; return false;
@ -485,7 +496,7 @@ _Draggable.prototype = {
if (this._actorDestroyed) { if (this._actorDestroyed) {
global.unset_cursor(); global.unset_cursor();
if (!this._buttonDown) if (!this._buttonDown)
this._ungrabEvents(); this._dragComplete();
this.emit('drag-end', eventTime, false); this.emit('drag-end', eventTime, false);
return; return;
} }
@ -542,12 +553,41 @@ _Draggable.prototype = {
this._dragComplete(); this._dragComplete();
}, },
// Actor is an actor we might have entered or left during the drag; call
// st_widget_sync_hover on all StWidget ancestors
_syncHover: function(actor) {
// If the actor was reparented from its original location and
// destroyed, then start syncing hover at the original parent
if (actor == this._dragActor && this._actorDestroyed)
actor = this._dragOrigParent;
while (actor) {
let parent = actor.get_parent();
if (actor instanceof St.Widget)
actor.sync_hover();
actor = parent;
}
},
_dragComplete: function() { _dragComplete: function() {
Shell.util_set_hidden_from_pick(this._dragActor, false); if (!this._actorDestroyed)
Shell.util_set_hidden_from_pick(this._dragActor, false);
this._ungrabEvents();
if (this._firstLeaveEvent) {
this._syncHover(this._firstLeaveEvent.get_source());
this._firstLeaveEvent = null;
}
if (this._lastEnterEvent) {
this._syncHover(this._lastEnterEvent.get_source());
this._lastEnterEvent = null;
}
this._dragActor = undefined; this._dragActor = undefined;
currentDraggable = null; currentDraggable = null;
this._ungrabEvents();
} }
}; };

View File

@ -1,487 +1,12 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- 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 Signals = imports.signals;
const St = imports.gi.St;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const DocInfo = imports.misc.docInfo; const DocInfo = imports.misc.docInfo;
const DND = imports.ui.dnd; const Params = imports.misc.params;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Search = imports.ui.search; const Search = imports.ui.search;
const MAX_DASH_DOCS = 50;
const DASH_DOCS_ICON_SIZE = 16;
const DEFAULT_SPACING = 4;
/* This class represents a single display item containing information about a document.
* We take the current number of seconds in the constructor to avoid looking up the current
* time for every item when they are created in a batch.
*
* docInfo - DocInfo object containing information about the document
* currentSeconds - current number of seconds since the epoch
*/
function DocDisplayItem(docInfo, currentSecs) {
this._init(docInfo, currentSecs);
}
DocDisplayItem.prototype = {
__proto__: GenericDisplay.GenericDisplayItem.prototype,
_init : function(docInfo, currentSecs) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
this._docInfo = docInfo;
this._setItemInfo(docInfo.name, '');
this._timeoutTime = -1;
this._resetTimeDisplay(currentSecs);
},
//// Public methods ////
getUpdateTimeoutTime: function() {
return this._timeoutTime;
},
// Update any relative-time based displays for this item.
redisplay: function(currentSecs) {
this._resetTimeDisplay(currentSecs);
},
//// Public method overrides ////
// Opens a document represented by this display item.
launch : function() {
this._docInfo.launch();
},
//// Protected method overrides ////
// Returns an icon for the item.
_createIcon : function() {
return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
},
// Returns a preview icon for the item.
_createPreviewIcon : function() {
return this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE);
},
// Creates and returns a large preview icon, but only if this._docInfo is an image file
// and we were able to generate a pixbuf from it successfully.
_createLargePreviewIcon : function() {
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf('image/') != 0)
return null;
try {
return St.TextureCache.get_default().load_uri_sync(St.TextureCachePolicy.NONE,
this._docInfo.uri, -1, -1);
} catch (e) {
// An exception will be raised when the image format isn't know
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
* only ignore GDK_PIXBUF_ERROR_UNKNOWN_TYPE. */
return null;
}
},
//// Drag and Drop ////
shellWorkspaceLaunch: function() {
this.launch();
},
//// Private Methods ////
// Updates the last visited time displayed in the description text for the item.
_resetTimeDisplay: function(currentSecs) {
let lastSecs = this._docInfo.timestamp;
let timeDelta = currentSecs - lastSecs;
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
this._timeoutTime = currentSecs + nextUpdate;
this._setDescriptionText(text);
}
};
/* This class represents a display containing a collection of document items.
* The documents are sorted by how recently they were last visited.
*/
function DocDisplay() {
this._init();
}
DocDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function() {
GenericDisplay.GenericDisplay.prototype._init.call(this);
// We keep a single timeout callback for updating last visited times
// for all the items in the display. This avoids creating individual
// callbacks for each item in the display. So proper time updates
// for individual items and item details depend on the item being
// associated with one of the displays.
this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
this._docManager = DocInfo.getDocManager();
this._docsStale = true;
this._docManager.connect('changed', Lang.bind(this, function(mgr, userData) {
this._docsStale = true;
// Changes in local recent files should not happen when we are in the Overview mode,
// but redisplaying right away is cool when we use Zephyr.
// Also, we might be displaying remote documents, like Google Docs, in the future
// which might be edited by someone else.
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
}));
this.connect('destroy', Lang.bind(this, function (o) {
if (this._updateTimeoutId > 0)
Mainloop.source_remove(this._updateTimeoutId);
}));
},
//// Protected method overrides ////
// Gets the list of recent items from the recent items manager.
_refreshCache : function() {
if (!this._docsStale)
return true;
this._allItems = {};
Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
this._docsStale = false;
return false;
},
// Sets the list of the displayed items based on how recently they were last visited.
_setDefaultList : function() {
// It seems to be an implementation detail of the Mozilla JavaScript that object
// properties are returned during the iteration in the same order in which they were
// defined, but it is not a guarantee according to this
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Statements/for...in
// While this._allItems associative array seems to always be ordered by last added,
// as the results of this._recentManager.get_items() based on which it is constructed are,
// we should do the sorting manually because we want the order to be based on last visited.
//
// This function is called each time the search string is set back to '' or we display
// the Overview, so we are doing the sorting over the same items multiple times if the list
// of recent items didn't change. We could store an additional array of doc ids and sort
// them once when they are returned by this._recentManager.get_items() to avoid having to do
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
// to introduce an additional class variable.
this._matchedItems = {};
this._matchedItemKeys = [];
let docIdsToRemove = [];
for (docId in this._allItems) {
this._matchedItems[docId] = 1;
this._matchedItemKeys.push(docId);
}
for (docId in docIdsToRemove) {
delete this._allItems[docId];
}
this._matchedItemKeys.sort(Lang.bind(this, this._compareItems));
},
// Compares items associated with the item ids based on how recently the items
// were last visited.
// Returns an integer value indicating the result of the comparison.
_compareItems : function(itemIdA, itemIdB) {
let docA = this._allItems[itemIdA];
let docB = this._allItems[itemIdB];
return docB.timestamp - docA.timestamp;
},
// Checks if the item info can be a match for the search string by checking
// the name of the document. Item info is expected to be GtkRecentInfo.
// Returns a boolean flag indicating if itemInfo is a match.
_isInfoMatching : function(itemInfo, search) {
if (!itemInfo.exists())
return false;
if (search == null || search == '')
return true;
let name = itemInfo.name.toLowerCase();
if (name.indexOf(search) >= 0)
return true;
// TODO: we can also check doc URIs, so that
// if you search for a directory name, we display recent files from it
return false;
},
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
_createDisplayItem: function(itemInfo) {
let currentSecs = new Date().getTime() / 1000;
let docDisplayItem = new DocDisplayItem(itemInfo, currentSecs);
this._updateTimeoutCallback(docDisplayItem, currentSecs);
return docDisplayItem;
},
//// Private Methods ////
// A callback function that redisplays the items, updating their descriptions,
// and sets up a new timeout callback.
_docTimeout: function () {
let currentSecs = new Date().getTime() / 1000;
this._updateTimeoutId = 0;
this._updateTimeoutTargetTime = -1;
for (let docId in this._displayedItems) {
let docDisplayItem = this._displayedItems[docId];
docDisplayItem.redisplay(currentSecs);
this._updateTimeoutCallback(docDisplayItem, currentSecs);
}
return false;
},
// Updates the timeout callback if the timeout time for the docDisplayItem
// is earlier than the target time for the current timeout callback.
_updateTimeoutCallback: function (docDisplayItem, currentSecs) {
let timeoutTime = docDisplayItem.getUpdateTimeoutTime();
if (this._updateTimeoutTargetTime < 0 || timeoutTime < this._updateTimeoutTargetTime) {
if (this._updateTimeoutId > 0)
Mainloop.source_remove(this._updateTimeoutId);
this._updateTimeoutId = Mainloop.timeout_add_seconds(timeoutTime - currentSecs, Lang.bind(this, this._docTimeout));
this._updateTimeoutTargetTime = timeoutTime;
}
}
};
Signals.addSignalMethods(DocDisplay.prototype);
function DashDocDisplayItem(docInfo) {
this._init(docInfo);
}
DashDocDisplayItem.prototype = {
_init: function(docInfo) {
this._info = docInfo;
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
this.actor = new St.Clickable({ style_class: 'recent-docs-item',
reactive: true,
x_align: St.Align.START });
let box = new St.BoxLayout({ style_class: 'recent-docs-item-box' });
this.actor.set_child(box);
box.add(this._icon);
let text = new St.Label({ text: docInfo.name });
box.add(text);
this.actor.connect('clicked', Lang.bind(this, function () {
docInfo.launch();
Main.overview.hide();
}));
this.actor._delegate = this;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
},
getUri: function() {
return this._info.uri;
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
this.dragActor = this._info.createIcon(DASH_DOCS_ICON_SIZE);
return this.dragActor;
},
//// Drag and drop functions ////
shellWorkspaceLaunch: function () {
this._info.launch();
}
};
/**
* Class used to display two column recent documents in the dash
*/
function DashDocDisplay() {
this._init();
}
DashDocDisplay.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._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
this._actorsByUri = {};
this._docManager = DocInfo.getDocManager();
this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
this._pendingDocsChange = true;
this._checkDocExistence = false;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let children = actor.get_children();
// We use two columns maximum. Just take the min and natural size of the
// first two items, even though strictly speaking it's not correct; we'd
// need to calculate how many items we could fit for the height, then
// take the biggest preferred width for each column.
// In practice the dash gets a fixed width anyways.
// If we have one child, add its minimum and natural size
if (children.length > 0) {
let [minSize, naturalSize] = children[0].get_preferred_width(forHeight);
alloc.min_size += minSize;
alloc.natural_size += naturalSize;
}
// If we have two, add its size, plus DEFAULT_SPACING
if (children.length > 1) {
let [minSize, naturalSize] = children[1].get_preferred_width(forHeight);
alloc.min_size += DEFAULT_SPACING + minSize;
alloc.natural_size += DEFAULT_SPACING + naturalSize;
}
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let children = actor.get_children();
// 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);
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();
let x = 0;
let y = 0;
let columnIndex = 0;
let i = 0;
// Loop over the children, going vertically down first. When we run
// out of vertical space (our y variable is bigger than box.y2), switch
// to the second column.
while (i < children.length) {
let child = children[i];
if (y + this._itemHeight > box.y2) {
// Is this the second column, or we're in
// the first column and can't even fit one
// item? In that case, break.
if (columnIndex == 1 || i == 0) {
break;
}
// Set x to the halfway point.
columnIndex += 1;
x = x + this._itemWidth + DEFAULT_SPACING;
// And y is back to the top.
y = 0;
// Retry this same item, now that we're in the second column.
// By looping back to the top here, we re-test the size
// again for the second column.
continue;
}
let childBox = new Clutter.ActorBox();
childBox.x1 = x;
childBox.y1 = y;
childBox.x2 = childBox.x1 + this._itemWidth;
childBox.y2 = y + this._itemHeight;
y = childBox.y2 + DEFAULT_SPACING;
child.allocate(childBox, flags);
this.actor.set_skip_paint(child, false);
i++;
}
if (this._checkDocExistence) {
// Now we know how many docs we are displaying, queue a check to see if any of them
// have been deleted. If they are deleted, then we'll get a 'changed' signal; since
// we'll now be displaying items we weren't previously, we'll check again to see
// if they were deleted, and so forth and so on.
// TODO: We should change this to ask for as many as we can fit in the given space:
// https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
this._docManager.queueExistenceCheck(i);
this._checkDocExistence = false;
}
for (; i < children.length; i++)
this.actor.set_skip_paint(children[i], true);
},
_onDocsChanged: function() {
this._checkDocExistence = true;
Main.queueDeferredWork(this._workId);
},
_redisplay: function() {
// Should be kept alive by the _actorsByUri
this.actor.remove_all();
let docs = this._docManager.getTimestampOrderedInfos();
for (let i = 0; i < docs.length && i < MAX_DASH_DOCS; i++) {
let doc = docs[i];
let display = this._actorsByUri[doc.uri];
if (display) {
this.actor.add_actor(display.actor);
} else {
let display = new DashDocDisplayItem(doc);
this.actor.add_actor(display.actor);
this._actorsByUri[doc.uri] = display;
}
}
// Any unparented actors must have been deleted
for (let uri in this._actorsByUri) {
let display = this._actorsByUri[uri];
if (display.actor.get_parent() == null) {
display.actor.destroy();
delete this._actorsByUri[uri];
}
}
this.emit('changed');
}
};
Signals.addSignalMethods(DashDocDisplay.prototype);
function DocSearchProvider() { function DocSearchProvider() {
this._init(); this._init();
@ -504,9 +29,12 @@ DocSearchProvider.prototype = {
'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)}; 'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)};
}, },
activateResult: function(id) { activateResult: function(id, params) {
params = Params.parse(params, { workspace: null,
timestamp: null });
let docInfo = this._docManager.lookupByUri(id); let docInfo = this._docManager.lookupByUri(id);
docInfo.launch(); docInfo.launch(params.workspace ? params.workspace.index() : -1);
}, },
getInitialResultSet: function(terms) { getInitialResultSet: function(terms) {

504
js/ui/endSessionDialog.js Normal file
View File

@ -0,0 +1,504 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
* Copyright 2010 Red Hat, Inc
*
* This program is free software; 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, or (at your option)
* any later version.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
const DBus = imports.dbus;
const Lang = imports.lang;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Clutter = imports.gi.Clutter;
const Gdm = imports.gi.Gdm;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
let _endSessionDialog = null;
const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = {
name: 'org.gnome.SessionManager.EndSessionDialog',
methods: [{ name: 'Open',
inSignature: 'uuuao',
outSignature: ''
}
],
signals: [{ name: 'Canceled',
outSignature: '',
}],
properties: []
};
const logoutDialogContent = {
subjectWithUser: _("Log Out %s"),
subject: _("Log Out"),
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
endDescription: _("Logging out of the system."),
confirmButtonText: _("Log Out"),
iconStyleClass: 'end-session-dialog-logout-icon'
};
const shutdownDialogContent = {
subject: _("Shut Down"),
inhibitedDescription: _("Click Shut Down to quit these applications and shut down the system."),
uninhibitedDescription: _("The system will shut down automatically in %d seconds."),
endDescription: _("Shutting down the system."),
confirmButtonText: _("Shut Down"),
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
const restartDialogContent = {
subject: _("Restart"),
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: _("The system will restart automatically in %d seconds."),
endDescription: _("Restarting the system."),
confirmButtonText: _("Restart"),
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
const DialogContent = {
0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */: logoutDialogContent,
1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */: shutdownDialogContent,
2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */: restartDialogContent
};
function findAppFromInhibitor(inhibitor) {
let desktopFile = inhibitor.app_id;
if (!GLib.str_has_suffix(desktopFile, '.desktop'))
desktopFile += '.desktop';
let candidateDesktopFiles = [];
candidateDesktopFiles.push(desktopFile);
candidateDesktopFiles.push('gnome-' + desktopFile);
let appSystem = Shell.AppSystem.get_default();
let app = null;
for (let i = 0; i < candidateDesktopFiles.length; i++) {
try {
app = appSystem.get_app(candidateDesktopFiles[i]);
if (app)
break;
} catch(e) {
// ignore errors
}
}
return app;
}
function ListItem(app, reason) {
this._init(app, reason);
}
ListItem.prototype = {
_init: function(app, reason) {
this._app = app;
this._reason = reason;
if (this._reason == null)
this._reason = '';
let layout = new St.BoxLayout({ vertical: false});
this.actor = new St.Clickable({ style_class: 'end-session-dialog-app-list-item',
can_focus: true,
child: layout,
reactive: true,
x_align: St.Align.START,
x_fill: true });
this._icon = this._app.create_icon_texture(_ITEM_ICON_SIZE);
let iconBin = new St.Bin({ style_class: 'end-session-dialog-app-list-item-icon',
child: this._icon });
layout.add(iconBin);
let textLayout = new St.BoxLayout({ style_class: 'end-session-dialog-app-list-item-text-box',
vertical: true });
layout.add(textLayout);
this._nameLabel = new St.Label({ text: this._app.get_name(),
style_class: 'end-session-dialog-app-list-item-name' });
textLayout.add(this._nameLabel,
{ expand: false,
x_fill: true });
this._descriptionLabel = new St.Label({ text: this._reason,
style_class: 'end-session-dialog-app-list-item-description' });
textLayout.add(this._descriptionLabel,
{ expand: true,
x_fill: true });
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
_onClicked: function() {
this.emit('activate');
this._app.activate(-1);
}
};
Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds
// until the last 10 seconds, then it shows updates every
// second. This function takes a given time and returns
// what we should show to the user for that time.
function _roundSecondsToInterval(totalSeconds, secondsLeft, interval) {
let time;
time = Math.ceil(secondsLeft);
// Final count down is in decrements of 1
if (time <= interval)
return time;
// Round up higher than last displayable time interval
time += interval - 1;
// Then round down to that time interval
if (time > totalSeconds)
time = Math.ceil(totalSeconds);
else
time -= time % interval;
return time;
}
function _setLabelText(label, text) {
if (text) {
label.set_text(text);
label.show();
} else {
label.set_text('');
label.hide();
}
}
function EndSessionDialog() {
if (_endSessionDialog == null) {
this._init();
DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
this);
_endSessionDialog = this;
}
return _endSessionDialog;
}
function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
let dialog = new EndSessionDialog();
}
EndSessionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function() {
ModalDialog.ModalDialog.prototype._init.call(this);
this._user = Gdm.UserManager.ref_default().get_user(GLib.get_user_name());
this._secondsLeft = 0;
this._totalSecondsToStayOpen = 0;
this._inhibitors = [];
this.connect('destroy',
Lang.bind(this, this._onDestroy));
this.connect('opened',
Lang.bind(this, this._onOpened));
this._userLoadedId = this._user.connect('notify::is_loaded',
Lang.bind(this, this._updateContent));
this._userChangedId = this._user.connect('changed',
Lang.bind(this, this._updateContent));
let mainContentLayout = new St.BoxLayout({ vertical: false });
this.contentLayout.add(mainContentLayout,
{ x_fill: true,
y_fill: false });
this._iconBin = new St.Bin();
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
let messageLayout = new St.BoxLayout({ vertical: true });
mainContentLayout.add(messageLayout,
{ y_align: St.Align.START });
this._subjectLabel = new St.Label({ style_class: 'end-session-dialog-subject' });
messageLayout.add(this._subjectLabel,
{ y_fill: false,
y_align: St.Align.START });
this._descriptionLabel = new St.Label({ style_class: 'end-session-dialog-description' });
this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add(this._descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
let scrollView = new St.ScrollView({ style_class: 'end-session-dialog-app-list'});
scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC);
this.contentLayout.add(scrollView,
{ x_fill: true,
y_fill: true });
this._applicationList = new St.BoxLayout({ vertical: true });
scrollView.add_actor(this._applicationList,
{ x_fill: true,
y_fill: true,
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
},
_onDestroy: function() {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
},
_setIconFromFile: function(iconFile, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
this._iconBin.child = null;
if (iconFile) {
this._iconBin.show();
this._iconBin.set_style('background-image: url("' + iconFile + '");');
} else {
this._iconBin.hide();
}
},
_setIconFromName: function(iconName, styleClass) {
if (styleClass)
this._iconBin.set_style_class_name(styleClass);
this._iconBin.set_style(null);
if (iconName != null) {
let textureCache = St.TextureCache.get_default();
let icon = textureCache.load_icon_name(this._iconBin.get_theme_node(),
iconName,
St.IconType.SYMBOLIC,
_DIALOG_ICON_SIZE);
this._iconBin.child = icon;
this._iconBin.show();
} else {
this._iconBin.child = null;
this._iconBin.hide();
}
},
_updateContent: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
let dialogContent = DialogContent[this._type];
let subject = dialogContent.subject;
let description;
if (this._user.is_loaded && !dialogContent.iconName) {
let iconFile = this._user.get_icon_file();
this._setIconFromFile(iconFile, dialogContent.iconStyleClass);
} else if (dialogContent.iconName) {
this._setIconFromName(dialogContent.iconName,
dialogContent.iconStyleClass);
}
if (this._inhibitors.length > 0) {
this._stopTimer();
description = dialogContent.inhibitedDescription;
} else if (this._secondsLeft > 0 && this._inhibitors.length == 0) {
let displayTime = _roundSecondsToInterval(this._totalSecondsToStayOpen,
this._secondsLeft,
10);
if (this._user.is_loaded) {
let realName = this._user.get_real_name();
if (realName != null) {
if (dialogContent.subjectWithUser)
subject = dialogContent.subjectWithUser.format(realName);
if (dialogContent.uninhibitedDescriptionWithUser)
description = dialogContent.uninhibitedDescriptionWithUser.format(realName, displayTime);
else
description = dialogContent.uninhibitedDescription.format(displayTime);
}
}
if (!description)
description = dialogContent.uninhibitedDescription.format(displayTime);
} else {
description = dialogContent.endDescription;
}
_setLabelText(this._subjectLabel, subject);
_setLabelText(this._descriptionLabel, description);
},
_updateButtons: function() {
if (this.state != ModalDialog.State.OPENING &&
this.state != ModalDialog.State.OPENED)
return;
let dialogContent = DialogContent[this._type];
let confirmButtonText = _("Confirm");
if (dialogContent.confirmButtonText)
confirmButtonText = dialogContent.confirmButtonText;
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this.cancel),
key: Clutter.Escape
},
{ label: confirmButtonText,
action: Lang.bind(this, this._confirm)
}]);
},
cancel: function() {
this._stopTimer();
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Canceled', '', []);
this.close(global.get_current_time());
},
_confirm: function() {
this._fadeOutDialog();
this._stopTimer();
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Confirmed', '', []);
},
_onOpened: function() {
if (this._inhibitors.length == 0)
this._startTimer();
},
_startTimer: function() {
this._secondsLeft = this._totalSecondsToStayOpen;
Tweener.addTween(this,
{ _secondsLeft: 0,
time: this._secondsLeft,
transition: 'linear',
onUpdate: Lang.bind(this, this._updateContent),
onComplete: Lang.bind(this, this._confirm),
});
},
_stopTimer: function() {
Tweener.removeTweens(this);
this._secondsLeft = 0;
},
_onInhibitorLoaded: function(inhibitor) {
if (this._inhibitors.indexOf(inhibitor) < 0) {
// Stale inhibitor
return;
}
let app = findAppFromInhibitor(inhibitor);
if (app) {
let item = new ListItem(app, inhibitor.reason);
item.connect('activate',
Lang.bind(this, function() {
this.close(global.get_current_time());
}));
this._applicationList.add(item.actor, { x_fill: true });
this._stopTimer();
} else {
// inhibiting app is a service, not an application
this._inhibitors.splice(this._inhibitors.indexOf(inhibitor), 1);
}
this._updateContent();
},
OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._inhibitors = [];
this._applicationList.destroy_children();
this._type = type;
if (!(this._type in DialogContent))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
inhibitor.connect('is-loaded',
Lang.bind(this, function() {
this._onInhibitorLoaded(inhibitor);
}));
this._inhibitors.push(inhibitor);
}
if (!this.open(timestamp))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
"Cannot grab pointer and keyboard");
this._updateButtons();
this._updateContent();
let signalId = this.connect('opened',
Lang.bind(this, function() {
callback();
this.disconnect(signalId);
}));
}
};
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);

View File

@ -88,8 +88,6 @@ function init() {
_blockMethod('Clutter.Event.get_state', 'Shell.get_event_state', _blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.'); 'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
_blockMethod('Gdk.Display.get_device_state', 'global.get_pointer',
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
_blockMethod('Gdk.Window.get_device_position', 'global.get_pointer', _blockMethod('Gdk.Window.get_device_position', 'global.get_pointer',
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.'); 'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');

View File

@ -4,6 +4,8 @@ const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const St = imports.gi.St; const St = imports.gi.St;
const Config = imports.misc.config;
const ExtensionState = { const ExtensionState = {
ENABLED: 1, ENABLED: 1,
DISABLED: 2, DISABLED: 2,
@ -25,6 +27,36 @@ var disabledExtensions;
// GFile for user extensions // GFile for user extensions
var userExtensionsDir = null; var userExtensionsDir = null;
/**
* versionCheck:
* @required: an array of versions we're compatible with
* @current: the version we have
*
* Check if a component is compatible for an extension.
* @required is an array, and at least one version must match.
* @current must be in the format <major>.<minor>.<point>.<micro>
* <micro> is always ignored
* <point> is ignored if <minor> is even (so you can target the
* whole stable release)
* <minor> and <major> must match
* Each target version must be at least <major> and <minor>
*/
function versionCheck(required, current) {
let currentArray = current.split('.');
let major = currentArray[0];
let minor = currentArray[1];
let point = currentArray[2];
for (let i = 0; i < required.length; i++) {
let requiredArray = required[i].split('.');
if (requiredArray[0] == major &&
requiredArray[1] == minor &&
(requiredArray[2] == point ||
(requiredArray[2] == undefined && parseInt(minor) % 2 == 0)))
return true;
}
return false;
}
function loadExtension(dir, enabled, type) { function loadExtension(dir, enabled, type) {
let info; let info;
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": '; let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
@ -43,8 +75,8 @@ function loadExtension(dir, enabled, type) {
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e); global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
return; return;
} }
let requiredProperties = ['uuid', 'name', 'description']; let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties; i++) { for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i]; let prop = requiredProperties[i];
if (!meta[prop]) { if (!meta[prop]) {
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json'); global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
@ -68,6 +100,12 @@ function loadExtension(dir, enabled, type) {
return; return;
} }
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
global.logError(baseErrorString + 'extension is not compatible with current GNOME Shell and/or GJS version');
return;
}
extensionMeta[meta.uuid] = meta; extensionMeta[meta.uuid] = meta;
extensionMeta[meta.uuid].type = type; extensionMeta[meta.uuid].type = type;
extensionMeta[meta.uuid].path = dir.get_path(); extensionMeta[meta.uuid].path = dir.get_path();

View File

@ -1,693 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const RedisplayFlags = { NONE: 0,
FULL: 1 << 1,
SUBSEARCH: 1 << 2,
IMMEDIATE: 1 << 3 };
// Used by subclasses
const ITEM_DISPLAY_ICON_SIZE = 48;
const PREVIEW_ICON_SIZE = 96;
/* This is a virtual class that represents a single display item containing
* a name, a description, and an icon. It allows selecting an item and represents
* it by highlighting it with a different background color than the default.
*/
function GenericDisplayItem() {
this._init();
}
GenericDisplayItem.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ style_class: 'generic-display-item',
reactive: true });
this.actor._delegate = this;
this.actor.connect('button-release-event',
Lang.bind(this,
function() {
// Activates the item by launching it
this.emit('activate');
return true;
}));
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
this._iconBin = new St.Bin();
this.actor.add(this._iconBin);
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
vertical: true });
this.actor.add(this._infoText, { expand: true, y_fill: false });
this._name = null;
this._description = null;
this._icon = null;
this._initialLoadComplete = false;
// An array of details description actors that we create over time for the item.
// It is used for updating the description text inside the details actor when
// the description text for the item is updated.
this._detailsDescriptions = [];
},
//// Draggable object interface ////
// Returns a cloned texture of the item's icon to represent the item as it
// is being dragged.
getDragActor: function(stageX, stageY) {
return this._createIcon();
},
// Returns the item icon, a separate copy of which is used to
// represent the item as it is being dragged. This is used to
// determine a snap-back location for the drag icon if it does
// not get accepted by any drop target.
getDragActorSource: function() {
return this._icon;
},
//// Public methods ////
// Highlights the item by setting a different background color than the default
// if isSelected is true, removes the highlighting otherwise.
markSelected: function(isSelected) {
if (isSelected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
},
/*
* Returns an actor containing item details. In the future details can have more information than what
* the preview pop-up has and be item-type specific.
*/
createDetailsActor: function() {
let details = new St.BoxLayout({ style_class: 'generic-display-container',
vertical: true });
let mainDetails = new St.BoxLayout({ style_class: 'generic-display-container' });
// Inner box with name and description
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
vertical: true });
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
text: this._name.text });
textDetails.add(detailsName);
let detailsDescription = new St.Label({ text: this._description.text });
textDetails.add(detailsDescription);
this._detailsDescriptions.push(detailsDescription);
mainDetails.add(textDetails, { expand: true });
let previewIcon = this._createPreviewIcon();
let largePreviewIcon = this._createLargePreviewIcon();
if (previewIcon != null && largePreviewIcon == null) {
mainDetails.insert_actor(previewIcon, 0);
}
details.add(mainDetails);
if (largePreviewIcon != null) {
details.add(largePreviewIcon);
}
return details;
},
// Destroys the item.
destroy: function() {
this.actor.destroy();
},
//// Pure virtual public methods ////
// Performes an action associated with launching this item, such as opening a file or an application.
launch: function() {
throw new Error('Not implemented');
},
//// Protected methods ////
/*
* Creates the graphical elements for the item based on the item information.
*
* nameText - name of the item
* descriptionText - short description of the item
*/
_setItemInfo: function(nameText, descriptionText) {
if (this._name != null) {
// this also removes this._name from the parent container,
// so we don't need to call this.actor.remove_actor(this._name) directly
this._name.destroy();
this._name = null;
}
if (this._description != null) {
this._description.destroy();
this._description = null;
}
if (this._icon != null) {
// though we get the icon from elsewhere, we assume its ownership here,
// and therefore should be responsible for distroying it
this._icon.destroy();
this._icon = null;
}
this._icon = this._createIcon();
this._iconBin.set_child(this._icon);
this._name = new St.Label({ style_class: 'generic-display-item-name',
text: nameText });
this._infoText.add(this._name);
this._description = new St.Label({ style_class: 'generic-display-item-description',
text: descriptionText ? descriptionText : '' });
this._infoText.add(this._description);
},
// Sets the description text for the item, including the description text
// in the details actors that have been created for the item.
_setDescriptionText: function(text) {
this._description.text = text;
for (let i = 0; i < this._detailsDescriptions.length; i++) {
let detailsDescription = this._detailsDescriptions[i];
if (detailsDescription != null) {
detailsDescription.text = text;
}
}
},
//// Virtual protected methods ////
// Creates and returns a large preview icon, but only if we have a detailed image.
_createLargePreviewIcon : function() {
return null;
},
//// Pure virtual protected methods ////
// Returns an icon for the item.
_createIcon: function() {
throw new Error('Not implemented');
},
// Returns a preview icon for the item.
_createPreviewIcon: function() {
throw new Error('Not implemented');
}
//// Private methods ////
};
Signals.addSignalMethods(GenericDisplayItem.prototype);
/* This is a virtual class that represents a display containing a collection of items
* that can be filtered with a search string.
*/
function GenericDisplay() {
this._init();
}
GenericDisplay.prototype = {
_init : function() {
this._search = '';
this._expanded = false;
this.actor = new St.ScrollView({ x_fill: true,
y_fill: false,
vshadows: true });
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
vertical: true });
this.actor.add_actor(this._list);
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._pendingRedisplay = RedisplayFlags.NONE;
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
// map<itemId, Object> where Object represents the item info
this._allItems = {};
// set<itemId>
this._matchedItems = {};
// sorted array of items matched by search
this._matchedItemKeys = [];
// map<itemId, GenericDisplayItem>
this._displayedItems = {};
this._openDetailIndex = -1;
this._selectedIndex = -1;
},
//// Public methods ////
// Sets the search string and displays the matching items.
setSearch: function(text) {
let lowertext = text.toLowerCase();
if (lowertext == this._search) {
return;
}
let flags = RedisplayFlags.IMMEDIATE;
if (this._search != '') {
// Because we combine search terms with OR, we have to be sure that no new term
// was introduced before deciding that the new search results will be a subset of
// the existing search results.
if (lowertext.indexOf(this._search) == 0 &&
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
flags |= RedisplayFlags.SUBSEARCH;
}
}
this._search = lowertext;
this._redisplay(flags);
},
// Launches the item that is currently selected, closing the Overview
activateSelected: function() {
if (this._selectedIndex != -1) {
let selected = this._findDisplayedByIndex(this._selectedIndex);
selected.launch();
this.unsetSelected();
Main.overview.hide();
}
},
// Moves the selection one up. If the selection was already on the top item, it's moved
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
// around to the bottom.
selectUp: function() {
let count = this._getVisibleCount();
let selectedUp = true;
let prev = this._selectedIndex - 1;
if (this._selectedIndex <= 0) {
prev = count - 1;
selectedUp = false;
}
this._selectIndex(prev);
return selectedUp;
},
// Moves the selection one down. If the selection was already on the bottom item, it's moved
// to the top one. Returns true if the selection actually moved down, false if it wrapped
// around to the top.
selectDown: function() {
let count = this._getVisibleCount();
let selectedDown = true;
let next = this._selectedIndex + 1;
if (this._selectedIndex == count - 1) {
next = 0;
selectedDown = false;
}
this._selectIndex(next);
return selectedDown;
},
// Selects the first item among the displayed items.
selectFirstItem: function() {
if (this.hasItems())
this._selectIndex(0);
},
// Selects the last item among the displayed items.
selectLastItem: function() {
let count = this._getVisibleCount();
if (this.hasItems())
this._selectIndex(count - 1);
},
// Returns true if the display has some item selected.
hasSelected: function() {
return this._selectedIndex != -1;
},
// Removes selection if some display item is selected.
unsetSelected: function() {
this._selectIndex(-1);
},
// Returns true if the display has any displayed items.
hasItems: function() {
// TODO: figure out why this._list.displayedCount is returning a
// positive number when this._mathedItems.length is 0
// This can be triggered if a search string is entered for which there are no matches.
// log('this._mathedItems.length: ' + this._matchedItems.length + ' this._list.displayedCount ' + this._list.displayedCount);
return this._matchedItemKeys.length > 0;
},
getMatchedItemsCount: function() {
return this._matchedItemKeys.length;
},
// Load the initial state
load: function() {
this._redisplay(RedisplayFlags.FULL);
},
// Should be called when the display is closed
resetState: function() {
this._filterReset();
this._openDetailIndex = -1;
this.actor.get_vscroll_bar().get_adjustment().value = 0;
},
// Returns an actor which acts as a sidebar; this is used for
// the applications category view
getNavigationArea: function () {
return null;
},
createDetailsForIndex: function(index) {
let item = this._findDisplayedByIndex(index);
return item.createDetailsActor();
},
//// Protected methods ////
_recreateDisplayItems: function() {
this._removeAllDisplayItems();
this._setDefaultList();
for (let itemId in this._allItems) {
this._addDisplayItem(itemId);
}
},
// Creates a display item based on the information associated with itemId
// and adds it to the list of displayed items, but does not yet display it.
_addDisplayItem : function(itemId) {
if (this._displayedItems.hasOwnProperty(itemId)) {
log('Tried adding a display item for ' + itemId + ', but an item with this item id is already among displayed items.');
return;
}
let itemInfo = this._allItems[itemId];
let displayItem = this._createDisplayItem(itemInfo);
displayItem.connect('activate',
Lang.bind(this,
function() {
// update the selection
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
this.activateSelected();
}));
displayItem.connect('show-details',
Lang.bind(this,
function() {
let index = this._list.get_children().indexOf(displayItem.actor);
/* Close the details pane if already open */
if (index == this._openDetailIndex) {
this._openDetailIndex = -1;
this.emit('show-details', -1);
} else {
this._openDetailIndex = index;
this.emit('show-details', index);
}
}));
this._displayedItems[itemId] = displayItem;
},
// Removes an item identifed by the itemId from the displayed items.
_removeDisplayItem: function(itemId) {
let children = this._list.get_children();
let count = children.length;
let displayItem = this._displayedItems[itemId];
let displayItemIndex = children.indexOf(displayItem.actor);
if (this.hasSelected() && count == 1) {
this.unsetSelected();
} else if (this.hasSelected() && displayItemIndex < this._selectedIndex) {
this.selectUp();
}
displayItem.destroy();
delete this._displayedItems[itemId];
},
// Removes all displayed items.
_removeAllDisplayItems: function() {
this.unsetSelected();
for (itemId in this._displayedItems)
this._removeDisplayItem(itemId);
},
// Return true if there's an active search or other constraint
// on the list
_filterActive: function() {
return this._search != '';
},
// Called when we are resetting state
_filterReset: function() {
this.unsetSelected();
},
_compareSearchMatch: function(a, b) {
let countA = this._matchedItems[a];
let countB = this._matchedItems[b];
if (countA > countB)
return -1;
else if (countA < countB)
return 1;
else
return this._compareItems(a, b);
},
_setMatches: function(matches) {
this._matchedItems = matches;
this._matchedItemKeys = [];
for (let itemId in this._matchedItems) {
this._matchedItemKeys.push(itemId);
}
this._matchedItemKeys.sort(Lang.bind(this, this._compareSearchMatch));
},
/**
* _redisplaySubSearch:
* A somewhat more optimized function called when we know
* that we're going to be displaying a subset of the items
* we already had, in the same order. In that case, we can
* just hide the actors that shouldn't be shown.
*/
_redisplaySubSearch: function() {
let matches = this._getSearchMatchedItems(true);
// Just hide all from the old set,
// we'll show the ones we want below
for (let itemId in this._displayedItems) {
let item = this._displayedItems[itemId];
item.actor.hide();
}
this._setMatches(matches);
for (let itemId in matches) {
let item = this._displayedItems[itemId];
item.actor.show();
}
this._list.queue_relayout();
},
_redisplayReordering: function() {
if (!this._filterActive()) {
this._setDefaultList();
} else {
this._setMatches(this._getSearchMatchedItems(false));
}
this._list.remove_all();
for (let i = 0; i < this._matchedItemKeys.length; i++) {
let itemId = this._matchedItemKeys[i];
let item = this._displayedItems[itemId];
item.actor.show();
this._list.add_actor(item.actor);
}
},
/*
* Updates the displayed items, applying the search string if one exists.
* @flags: Flags controlling redisplay behavior as follows:
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
* one, which implies we only need to re-search through previous results.
* FULL - Indicates that we need recreate all displayed items.
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
* if you want to get the number of matched items and show/hide a section based on
* that number.
*/
_redisplay: function(flags) {
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
if (!immediate && !this.actor.mapped) {
this._pendingRedisplay |= flags;
return;
}
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
let fullReload = (flags & RedisplayFlags.FULL) != 0;
let hadSelected = this.hasSelected();
this.unsetSelected();
if (!this._initialLoadComplete)
fullReload = true;
if (!this._refreshCache())
fullReload = true;
if (fullReload) {
this._recreateDisplayItems();
this._initialLoadComplete = true;
}
if (isSubSearch) {
this._redisplaySubSearch();
} else {
this._redisplayReordering();
}
if (hadSelected) {
this._selectedIndex = -1;
this.selectFirstItem();
}
this.emit('redisplayed');
},
//// Pure virtual protected methods ////
// Performs the steps needed to have the latest information about the items.
// Implementation should return %true if we are up to date, and %false
// if a full reload occurred.
_refreshCache: function() {
throw new Error('Not implemented');
},
// Sets the list of the displayed items based on the default sorting order.
// The default sorting order is specific to each implementing class.
_setDefaultList: function() {
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.
_compareItems: function(itemIdA, itemIdB) {
throw new Error('Not implemented');
},
// Checks if the item info can be a match for the search string.
// Returns a boolean flag indicating if that's the case.
_isInfoMatching: function(itemInfo, search) {
throw new Error('Not implemented');
},
// Creates a display item based on itemInfo.
_createDisplayItem: function(itemInfo) {
throw new Error('Not implemented');
},
//// Private methods ////
_getItemSearchScore: function(itemId, terms) {
let item = this._allItems[itemId];
let score = 0;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
if (this._isInfoMatching(item, term)) {
score++;
}
}
return score;
},
_getSearchMatchedItems: function(isSubSearch) {
// Break the search up into terms, and search for each
// individual term. Keep track of the number of terms
// each item matched.
let terms = this._search.split(/\s+/);
let matchScores = {};
if (isSubSearch) {
for (let i = 0; i < this._matchedItemKeys.length; i++) {
let itemId = this._matchedItemKeys[i];
let score = this._getItemSearchScore(itemId, terms);
if (score > 0)
matchScores[itemId] = score;
}
} else {
for (let itemId in this._displayedItems) {
let score = this._getItemSearchScore(itemId, terms);
if (score > 0)
matchScores[itemId] = score;
}
}
return matchScores;
},
// Returns a display item based on its index in the ordering of the
// display children.
_findDisplayedByIndex: function(index) {
let actor = this._list.get_children()[index];
return this._findDisplayedByActor(actor);
},
// Returns a display item based on the actor that represents it in
// the display.
_findDisplayedByActor: function(actor) {
for (itemId in this._displayedItems) {
let item = this._displayedItems[itemId];
if (item.actor == actor) {
return item;
}
}
return null;
},
// Selects (e.g. highlights) a display item at the provided index,
// updates this.selectedItemDetails actor, and emits 'selected' signal.
_selectIndex: function(index) {
// Cleanup from the previous item
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}
this._selectedIndex = index;
if (index < 0)
return;
// Mark the new item as selected and create its details pane
let item = this._findDisplayedByIndex(index);
item.markSelected(true);
this.emit('selected');
},
_getVisibleCount: function() {
return this._list.get_n_children();
},
_onMappedNotify: function () {
let mapped = this.actor.mapped;
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
this._redisplay(this._pendingRedisplay);
this._pendingRedisplay = RedisplayFlags.NONE;
}
};
Signals.addSignalMethods(GenericDisplay.prototype);

View File

@ -398,6 +398,9 @@ Inspector.prototype = {
}, },
_allocate: function(actor, box, flags) { _allocate: function(actor, box, flags) {
if (!this._eventHandler)
return;
let primary = global.get_primary_monitor(); let primary = global.get_primary_monitor();
let [minWidth, minHeight, natWidth, natHeight] = let [minWidth, minHeight, natWidth, natHeight] =
@ -415,6 +418,7 @@ Inspector.prototype = {
Clutter.ungrab_pointer(this._eventHandler); Clutter.ungrab_pointer(this._eventHandler);
Clutter.ungrab_keyboard(this._eventHandler); Clutter.ungrab_keyboard(this._eventHandler);
this._eventHandler.destroy(); this._eventHandler.destroy();
this._eventHandler = null;
this.emit('closed'); this.emit('closed');
}, },

View File

@ -22,6 +22,7 @@ const _ = Gettext.gettext;
const Chrome = imports.ui.chrome; const Chrome = imports.ui.chrome;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const EndSessionDialog = imports.ui.endSessionDialog;
const Environment = imports.ui.environment; const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem; const ExtensionSystem = imports.ui.extensionSystem;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
@ -37,7 +38,9 @@ const ShellDBus = imports.ui.shellDBus;
const TelepathyClient = imports.ui.telepathyClient; const TelepathyClient = imports.ui.telepathyClient;
const WindowManager = imports.ui.windowManager; const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier; const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler;
const StatusIconDispatcher = imports.ui.statusIconDispatcher; const StatusIconDispatcher = imports.ui.statusIconDispatcher;
const Util = imports.misc.util;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff); DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
@ -60,9 +63,12 @@ let modalCount = 0;
let modalActorFocusStack = []; let modalActorFocusStack = [];
let uiGroup = null; let uiGroup = null;
let magnifier = null; let magnifier = null;
let xdndHandler = null;
let statusIconDispatcher = null; let statusIconDispatcher = null;
let _errorLogStack = []; let _errorLogStack = [];
let _startDate; let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
let background = null; let background = null;
@ -107,10 +113,8 @@ function start() {
global.stage.color = DEFAULT_BACKGROUND_COLOR; global.stage.color = DEFAULT_BACKGROUND_COLOR;
global.stage.no_clear_hint = true; global.stage.no_clear_hint = true;
let themeContext = St.ThemeContext.get_for_stage (global.stage); _defaultCssStylesheet = global.datadir + '/theme/gnome-shell.css';
let stylesheetPath = global.datadir + '/theme/gnome-shell.css'; loadTheme();
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
themeContext.set_theme (theme);
let shellwm = global.window_manager; let shellwm = global.window_manager;
shellwm.takeover_keybinding('panel_main_menu'); shellwm.takeover_keybinding('panel_main_menu');
@ -129,6 +133,7 @@ function start() {
global.stage.add_actor(uiGroup); global.stage.add_actor(uiGroup);
placesManager = new PlaceDisplay.PlacesManager(); placesManager = new PlaceDisplay.PlacesManager();
xdndHandler = new XdndHandler.XdndHandler();
overview = new Overview.Overview(); overview = new Overview.Overview();
chrome = new Chrome.Chrome(); chrome = new Chrome.Chrome();
magnifier = new Magnifier.Magnifier(); magnifier = new Magnifier.Magnifier();
@ -170,6 +175,12 @@ function start() {
} }
}); });
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
// Provide the bus object for gnome-session to
// initiate logouts.
EndSessionDialog.init();
global.gdk_screen.connect('monitors-changed', _relayout); global.gdk_screen.connect('monitors-changed', _relayout);
ExtensionSystem.init(); ExtensionSystem.init();
@ -188,14 +199,144 @@ function start() {
_log('info', 'loaded at ' + _startDate); _log('info', 'loaded at ' + _startDate);
log('GNOME Shell started at ' + _startDate); log('GNOME Shell started at ' + _startDate);
Mainloop.idle_add(_removeUnusedWorkspaces);
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE"); let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) { if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT"); let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';'); let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput); Scripting.runPerfScript(module, perfOutput);
} }
global.screen.connect('notify::n-workspaces', _nWorkspacesChanged);
Mainloop.idle_add(_nWorkspacesChanged);
}
let _workspaces = [];
let _checkWorkspacesId = 0;
function _checkWorkspaces() {
let i;
let emptyWorkspaces = [];
for (i = 0; i < _workspaces.length; i++)
emptyWorkspaces[i] = true;
let windows = global.get_window_actors();
for (i = 0; i < windows.length; i++) {
let win = windows[i];
if (win.get_meta_window().is_on_all_workspaces())
continue;
let workspaceIndex = win.get_workspace();
emptyWorkspaces[workspaceIndex] = false;
}
// If we don't have an empty workspace at the end, add one
if (!emptyWorkspaces[emptyWorkspaces.length -1]) {
global.screen.append_new_workspace(false, global.get_current_time());
emptyWorkspaces.push(false);
}
// Delete other empty workspaces; do it from the end to avoid index changes
for (i = emptyWorkspaces.length - 2; i >= 0; i--) {
if (emptyWorkspaces[i])
global.screen.remove_workspace(_workspaces[i], global.get_current_time());
}
_checkWorkspacesId = 0;
return false;
}
function _queueCheckWorkspaces() {
if (_checkWorkspacesId == 0)
_checkWorkspacesId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, _checkWorkspaces);
}
function _nWorkspacesChanged() {
let oldNumWorkspaces = _workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
if (oldNumWorkspaces == newNumWorkspaces)
return false;
let lostWorkspaces = [];
if (newNumWorkspaces > oldNumWorkspaces) {
let w;
// Assume workspaces are only added at the end
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++)
_workspaces[w] = global.screen.get_workspace_by_index(w);
for (w = oldNumWorkspaces; w < newNumWorkspaces; w++) {
let workspace = _workspaces[w];
workspace._windowAddedId = workspace.connect('window-added', _queueCheckWorkspaces);
workspace._windowRemovedId = workspace.connect('window-removed', _queueCheckWorkspaces);
}
} else {
// Assume workspaces are only removed sequentially
// (e.g. 2,3,4 - not 2,4,7)
let removedIndex;
let removedNum = oldNumWorkspaces - newNumWorkspaces;
for (let w = 0; w < oldNumWorkspaces; w++) {
let workspace = global.screen.get_workspace_by_index(w);
if (_workspaces[w] != workspace) {
removedIndex = w;
break;
}
}
let lostWorkspaces = _workspaces.splice(removedIndex, removedNum);
lostWorkspaces.forEach(function(workspace) {
workspace.disconnect(workspace._windowAddedId);
workspace.disconnect(workspace._windowRemovedId);
});
}
_queueCheckWorkspaces();
return false;
}
/**
* getThemeStylesheet:
*
* Get the theme CSS file that the shell will load
*
* Returns: A file path that contains the theme CSS,
* null if using the default
*/
function getThemeStylesheet()
{
return _cssStylesheet;
}
/**
* setThemeStylesheet:
* @cssStylesheet: A file path that contains the theme CSS,
* set it to null to use the default
*
* Set the theme CSS file that the shell will load
*/
function setThemeStylesheet(cssStylesheet)
{
_cssStylesheet = cssStylesheet;
}
/**
* loadTheme:
*
* Reloads the theme CSS file
*/
function loadTheme() {
let themeContext = St.ThemeContext.get_for_stage (global.stage);
let cssStylesheet = _defaultCssStylesheet;
if (_cssStylesheet != null)
cssStylesheet = _cssStylesheet;
let theme = new St.Theme ({ application_stylesheet: cssStylesheet });
themeContext.set_theme (theme);
} }
/** /**
@ -247,38 +388,8 @@ function _relayout() {
// To avoid updating the position and size of the workspaces // To avoid updating the position and size of the workspaces
// in the overview, we just hide the overview. The positions // in the overview, we just hide the overview. The positions
// will be updated when it is next shown. We do the same for // will be updated when it is next shown.
// the calendar popdown.
overview.hide(); overview.hide();
panel.hideCalendar();
}
// metacity-clutter currently uses the same prefs as plain metacity,
// which probably means we'll be starting out with multiple workspaces;
// remove any unused ones. (We do this from an idle handler, because
// global.get_window_actors() still returns NULL at the point when start()
// is called.)
function _removeUnusedWorkspaces() {
let windows = global.get_window_actors();
let maxWorkspace = 0;
for (let i = 0; i < windows.length; i++) {
let win = windows[i];
if (!win.get_meta_window().is_on_all_workspaces() &&
win.get_workspace() > maxWorkspace) {
maxWorkspace = win.get_workspace();
}
}
let screen = global.screen;
if (screen.n_workspaces > maxWorkspace) {
for (let w = screen.n_workspaces - 1; w > maxWorkspace; w--) {
let workspace = screen.get_workspace_by_index(w);
screen.remove_workspace(workspace, 0);
}
}
return false;
} }
// This function encapsulates hacks to make certain global keybindings // This function encapsulates hacks to make certain global keybindings
@ -286,65 +397,64 @@ function _removeUnusedWorkspaces() {
// are disabled with a global grab. (When there is a global grab, then // are disabled with a global grab. (When there is a global grab, then
// all key events will be delivered to the stage, so ::captured-event // all key events will be delivered to the stage, so ::captured-event
// on the stage can be used for global keybindings.) // on the stage can be used for global keybindings.)
//
// We expect to need to conditionally enable just a few keybindings
// depending on circumstance; the main hackiness here is that we are
// assuming that keybindings have their default values; really we
// should be asking Mutter to resolve the key into an action and then
// base our handling based on the action.
function _globalKeyPressHandler(actor, event) { function _globalKeyPressHandler(actor, event) {
if (modalCount == 0) if (modalCount == 0)
return false; return false;
if (event.type() != Clutter.EventType.KEY_RELEASE) if (event.type() != Clutter.EventType.KEY_PRESS)
return false; return false;
let symbol = event.get_key_symbol(); let symbol = event.get_key_symbol();
let keyCode = event.get_key_code(); let keyCode = event.get_key_code();
let modifierState = Shell.get_event_state(event); let modifierState = Shell.get_event_state(event);
// Check the overview key first, this isn't a Meta.KeyBindingAction yet
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
// The super key is the default for triggering the overview, and should
// get us out of the overview when we are already in it.
if (overview.visible)
overview.hide();
let display = global.screen.get_display();
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = display.get_keybinding_action(keyCode, modifierState);
// The screenshot action should always be available (even if a
// modal dialog is present)
if (action == Meta.KeyBindingAction.COMMAND_SCREENSHOT) {
let gconf = GConf.Client.get_default();
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
if (command != null && command != '')
Util.spawnCommandLine(command);
return true; return true;
} }
// Whitelist some of the Metacity actions // Other bindings are only available when the overview is up and
let display = global.screen.get_display(); // no modal dialog is present.
let activeWorkspaceIndex = global.screen.get_active_workspace_index(); if (!overview.visible || modalCount > 1)
return false;
// This isn't a Meta.KeyBindingAction yet
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
overview.hide();
return true;
}
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = display.get_keybinding_action(keyCode, modifierState);
switch (action) { switch (action) {
case Meta.KeyBindingAction.COMMAND_SCREENSHOT:
let gconf = GConf.Client.get_default();
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
if (command != null && command != '') {
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
p.run();
}
return true;
case Meta.KeyBindingAction.WORKSPACE_LEFT: case Meta.KeyBindingAction.WORKSPACE_LEFT:
wm.actionMoveWorkspaceLeft(); wm.actionMoveWorkspaceLeft();
return true; return true;
case Meta.KeyBindingAction.WORKSPACE_RIGHT: case Meta.KeyBindingAction.WORKSPACE_RIGHT:
wm.actionMoveWorkspaceRight(); wm.actionMoveWorkspaceRight();
return true; return true;
case Meta.KeyBindingAction.WORKSPACE_UP:
wm.actionMoveWorkspaceUp();
return true;
case Meta.KeyBindingAction.WORKSPACE_DOWN:
wm.actionMoveWorkspaceDown();
return true;
case Meta.KeyBindingAction.PANEL_RUN_DIALOG: case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
case Meta.KeyBindingAction.COMMAND_2: case Meta.KeyBindingAction.COMMAND_2:
getRunDialog().open(); getRunDialog().open();
return true; return true;
case Meta.KeyBindingAction.PANEL_MAIN_MENU:
overview.hide();
return true;
case Meta.KeyBindingAction.SWITCH_PANELS: case Meta.KeyBindingAction.SWITCH_PANELS:
// Only intercept this when we're in the overview, and don't ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK);
// intercept it if something beyond that (like, say, the return true;
// ctrl-alt-tab popup!) is visible
if (overview.visible && modalCount == 1) {
ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK);
return true;
}
} }
return false; return false;
@ -363,6 +473,7 @@ function _findModal(actor) {
/** /**
* pushModal: * pushModal:
* @actor: #ClutterActor which will be given keyboard focus * @actor: #ClutterActor which will be given keyboard focus
* @timestamp: optional timestamp
* *
* Ensure we are in a mode where all keyboard and mouse input goes to * Ensure we are in a mode where all keyboard and mouse input goes to
* the stage, and focus @actor. Multiple calls to this function act in * the stage, and focus @actor. Multiple calls to this function act in
@ -373,11 +484,19 @@ function _findModal(actor) {
* modal stack returns to this actor, reset the focus to the actor * modal stack returns to this actor, reset the focus to the actor
* which was focused at the time pushModal() was invoked. * which was focused at the time pushModal() was invoked.
* *
* @timestamp is optionally used to associate the call with a specific user
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
*
* Returns: true iff we successfully acquired a grab or already had one * Returns: true iff we successfully acquired a grab or already had one
*/ */
function pushModal(actor) { function pushModal(actor, timestamp) {
if (timestamp == undefined)
timestamp = global.get_current_time();
if (modalCount == 0) { if (modalCount == 0) {
if (!global.begin_modal(global.get_current_time())) { if (!global.begin_modal(timestamp)) {
log('pushModal: invocation of begin_modal failed'); log('pushModal: invocation of begin_modal failed');
return false; return false;
} }
@ -408,12 +527,21 @@ function pushModal(actor) {
/** /**
* popModal: * popModal:
* @actor: #ClutterActor passed to original invocation of pushModal(). * @actor: #ClutterActor passed to original invocation of pushModal().
* @timestamp: optional timestamp
* *
* Reverse the effect of pushModal(). If this invocation is undoing * Reverse the effect of pushModal(). If this invocation is undoing
* the topmost invocation, then the focus will be restored to the * the topmost invocation, then the focus will be restored to the
* previous focus at the time when pushModal() was invoked. * previous focus at the time when pushModal() was invoked.
*
* @timestamp is optionally used to associate the call with a specific user
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
*/ */
function popModal(actor) { function popModal(actor, timestamp) {
if (timestamp == undefined)
timestamp = global.get_current_time();
modalCount -= 1; modalCount -= 1;
let focusIndex = _findModal(actor); let focusIndex = _findModal(actor);
if (focusIndex >= 0) { if (focusIndex >= 0) {
@ -432,7 +560,7 @@ function popModal(actor) {
return; return;
global.stage.set_key_focus(null); global.stage.set_key_focus(null);
global.end_modal(global.get_current_time()); global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL); global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
} }

View File

@ -16,7 +16,10 @@ const Tweener = imports.ui.tweener;
const Main = imports.ui.main; const Main = imports.ui.main;
const BoxPointer = imports.ui.boxpointer; const BoxPointer = imports.ui.boxpointer;
const Params = imports.misc.params; const Params = imports.misc.params;
const Utils = imports.misc.utils; const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const ANIMATION_TIME = 0.2; const ANIMATION_TIME = 0.2;
const NOTIFICATION_TIMEOUT = 4; const NOTIFICATION_TIMEOUT = 4;
@ -38,6 +41,28 @@ const State = {
HIDING: 3 HIDING: 3
}; };
// These reasons are useful when we destroy the notifications received through
// the notification daemon. We use EXPIRED for transient notifications that the
// user did not interact with, DISMISSED for all other notifications that were
// destroyed as a result of a user action, and SOURCE_CLOSED for the notifications
// that were requested to be destroyed by the associated source.
const NotificationDestroyedReason = {
EXPIRED: 1,
DISMISSED: 2,
SOURCE_CLOSED: 3
};
// Message tray has its custom Urgency enumeration. LOW, NORMAL and CRITICAL
// urgency values map to the corresponding values for the notifications received
// through the notification daemon. HIGH urgency value is used for chats received
// through the Telepathy client.
const Urgency = {
LOW: 0,
NORMAL: 1,
HIGH: 2,
CRITICAL: 3
}
function _fixMarkup(text, allowMarkup) { function _fixMarkup(text, allowMarkup) {
if (allowMarkup) { if (allowMarkup) {
// Support &amp;, &quot;, &apos;, &lt; and &gt;, escape all other // Support &amp;, &quot;, &apos;, &lt; and &gt;, escape all other
@ -92,8 +117,7 @@ URLHighlighter.prototype = {
return true; return true;
} catch (e) { } catch (e) {
// TODO: remove this after gnome 3 release // TODO: remove this after gnome 3 release
let p = new Shell.Process({ 'args' : ['gvfs-open', url] }); Util.spawn(['gvfs-open', url]);
p.run();
return true; return true;
} }
} }
@ -124,13 +148,13 @@ URLHighlighter.prototype = {
this.actor.clutter_text.set_markup(text); this.actor.clutter_text.set_markup(text);
/* clutter_text.text contain text without markup */ /* clutter_text.text contain text without markup */
this._urls = Utils.findUrls(this.actor.clutter_text.text); this._urls = Util.findUrls(this.actor.clutter_text.text);
this._highlightUrls(); this._highlightUrls();
}, },
_highlightUrls: function() { _highlightUrls: function() {
// text here contain markup // text here contain markup
let urls = Utils.findUrls(this._text); let urls = Util.findUrls(this._text);
let markup = ''; let markup = '';
let pos = 0; let pos = 0;
for (let i = 0; i < urls.length; i++) { for (let i = 0; i < urls.length; i++) {
@ -225,11 +249,12 @@ function Notification(source, title, banner, params) {
Notification.prototype = { Notification.prototype = {
_init: function(source, title, banner, params) { _init: function(source, title, banner, params) {
this.source = source; this.source = source;
this.urgent = false; this.urgency = Urgency.NORMAL;
this.resident = false; this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name // 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
this.isTransient = false; this.isTransient = false;
this.expanded = false; this.expanded = false;
this._destroyed = false;
this._useActionIcons = false; this._useActionIcons = false;
this._customContent = false; this._customContent = false;
this._bannerBodyText = null; this._bannerBodyText = null;
@ -237,6 +262,7 @@ Notification.prototype = {
this._titleFitsInBannerMode = true; this._titleFitsInBannerMode = true;
this._spacing = 0; this._spacing = 0;
this._buttonFocusManager = null;
this._hasFocus = false; this._hasFocus = false;
this._lockTrayOnFocusGrab = false; this._lockTrayOnFocusGrab = false;
// We use this._prevFocusedWindow and this._prevKeyFocusActor to return the // We use this._prevFocusedWindow and this._prevKeyFocusActor to return the
@ -250,7 +276,11 @@ Notification.prototype = {
this._capturedEventId = 0; this._capturedEventId = 0;
this._keyPressId = 0; this._keyPressId = 0;
source.connect('destroy', Lang.bind(this, this.destroy)); source.connect('destroy', Lang.bind(this,
// Avoid passing 'source' as an argument to this.destroy()
function () {
this.destroy();
}));
this.actor = new St.Table({ name: 'notification', this.actor = new St.Table({ name: 'notification',
reactive: true }); reactive: true });
@ -373,7 +403,7 @@ Notification.prototype = {
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview', this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
vscrollbar_policy: Gtk.PolicyType.AUTOMATIC, vscrollbar_policy: Gtk.PolicyType.AUTOMATIC,
hscrollbar_policy: Gtk.PolicyType.NEVER, hscrollbar_policy: Gtk.PolicyType.NEVER,
vshadows: true }); vfade: true });
this.actor.add(this._scrollArea, { row: 1, this.actor.add(this._scrollArea, { row: 1,
col: 1 }); col: 1 });
this._contentArea = new St.BoxLayout({ name: 'notification-body', this._contentArea = new St.BoxLayout({ name: 'notification-body',
@ -475,7 +505,7 @@ Notification.prototype = {
this._buttonBox = box; this._buttonBox = box;
} }
let button = new St.Button(); let button = new St.Button({ can_focus: true });
if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(id)) { if (this._useActionIcons && Gtk.IconTheme.get_default().has_icon(id)) {
button.add_style_class_name('notification-icon-button'); button.add_style_class_name('notification-icon-button');
@ -485,13 +515,20 @@ Notification.prototype = {
button.label = label; button.label = label;
} }
if (!this._buttonFocusManager)
this._buttonFocusManager = St.FocusManager.get_for_stage(global.stage);
if (this._buttonBox.get_children().length > 0)
this._buttonFocusManager.remove_group(this._buttonBox);
this._buttonBox.add(button); this._buttonBox.add(button);
this._buttonFocusManager.add_group(this._buttonBox);
button.connect('clicked', Lang.bind(this, this._onActionInvoked, id)); button.connect('clicked', Lang.bind(this, this._onActionInvoked, id));
this._updated(); this._updated();
}, },
setUrgent: function(urgent) { setUrgency: function(urgency) {
this.urgent = urgent; this.urgency = urgency;
}, },
setResident: function(resident) { setResident: function(resident) {
@ -636,6 +673,10 @@ Notification.prototype = {
this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged)); this._focusActorChangedId = global.stage.connect('notify::key-focus', Lang.bind(this, this._focusActorChanged));
this._hasFocus = true; this._hasFocus = true;
if (this._buttonFocusManager)
this._buttonBox.get_children()[0].grab_key_focus();
if (lockTray) if (lockTray)
Main.messageTray.lock(); Main.messageTray.lock();
}, },
@ -693,15 +734,6 @@ Notification.prototype = {
this.destroy(); this.destroy();
}, },
_onKeyPress: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.Escape) {
Main.messageTray.escapeTray();
return true;
}
return false;
},
ungrabFocus: function() { ungrabFocus: function() {
if (!this._hasFocus) if (!this._hasFocus)
return; return;
@ -751,8 +783,13 @@ Notification.prototype = {
} }
}, },
destroy: function() { destroy: function(reason) {
this.emit('destroy'); if (this._destroyed)
return;
this._destroyed = true;
if (!reason)
reason = NotificationDestroyedReason.DISMISSED;
this.emit('destroy', reason);
} }
}; };
Signals.addSignalMethods(Notification.prototype); Signals.addSignalMethods(Notification.prototype);
@ -769,6 +806,7 @@ Source.prototype = {
this._iconBin = new St.Bin({ width: this.ICON_SIZE, this._iconBin = new St.Bin({ width: this.ICON_SIZE,
height: this.ICON_SIZE }); height: this.ICON_SIZE });
this.isTransient = false; this.isTransient = false;
this.isChat = false;
}, },
setTransient: function(isTransient) { setTransient: function(isTransient) {
@ -905,7 +943,7 @@ MessageTray.prototype = {
this._notification = null; this._notification = null;
this._notificationClickedId = 0; this._notificationClickedId = 0;
this._summaryBin = new St.Bin({ anchor_gravity: Clutter.Gravity.NORTH_EAST }); this._summaryBin = new St.Bin({ x_align: St.Align.END });
this.actor.add_actor(this._summaryBin); this.actor.add_actor(this._summaryBin);
this._summary = new St.BoxLayout({ name: 'summary-mode', this._summary = new St.BoxLayout({ name: 'summary-mode',
reactive: true, reactive: true,
@ -988,6 +1026,7 @@ MessageTray.prototype = {
// added to the summary without a notification being shown. // added to the summary without a notification being shown.
this._newSummaryItems = []; this._newSummaryItems = [];
this._longestSummaryItem = null; this._longestSummaryItem = null;
this._chatSummaryItemsCount = 0;
}, },
_setSizePosition: function() { _setSizePosition: function() {
@ -997,9 +1036,8 @@ MessageTray.prototype = {
this.actor.width = primary.width; this.actor.width = primary.width;
this._notificationBin.x = 0; this._notificationBin.x = 0;
this._notificationBin.width = primary.width; this._notificationBin.width = primary.width;
this._summaryBin.x = 0;
// These work because of their anchor_gravity this._summaryBin.width = primary.width;
this._summaryBin.x = primary.width;
}, },
contains: function(source) { contains: function(source) {
@ -1022,7 +1060,12 @@ MessageTray.prototype = {
let summaryItem = new SummaryItem(source); let summaryItem = new SummaryItem(source);
this._summary.insert_actor(summaryItem.actor, 0); if (source.isChat) {
this._summary.insert_actor(summaryItem.actor, 0);
this._chatSummaryItemsCount++;
} else {
this._summary.insert_actor(summaryItem.actor, this._chatSummaryItemsCount);
}
let titleWidth = summaryItem.getTitleNaturalWidth(); let titleWidth = summaryItem.getTitleNaturalWidth();
if (titleWidth > this._summaryItemTitleWidth) { if (titleWidth > this._summaryItemTitleWidth) {
@ -1087,6 +1130,10 @@ MessageTray.prototype = {
this._newSummaryItems.splice(newSummaryItemsIndex, 1); this._newSummaryItems.splice(newSummaryItemsIndex, 1);
this._summaryItems.splice(index, 1); this._summaryItems.splice(index, 1);
if (source.isChat)
this._chatSummaryItemsCount--;
if (this._longestSummaryItem.source == source) { if (this._longestSummaryItem.source == source) {
let newTitleWidth = 0; let newTitleWidth = 0;
this._longestSummaryItem = null; this._longestSummaryItem = null;
@ -1166,13 +1213,11 @@ MessageTray.prototype = {
} else if (this._notificationQueue.indexOf(notification) < 0) { } else if (this._notificationQueue.indexOf(notification) < 0) {
notification.connect('destroy', notification.connect('destroy',
Lang.bind(this, this.removeNotification)); Lang.bind(this, this.removeNotification));
this._notificationQueue.push(notification);
if (notification.urgent) this._notificationQueue.sort(function(notification1, notification2) {
this._notificationQueue.unshift(notification); return (notification2.urgency - notification1.urgency);
else });
this._notificationQueue.push(notification);
} }
this._updateState(); this._updateState();
}, },
@ -1371,7 +1416,7 @@ MessageTray.prototype = {
let notificationsPending = this._notificationQueue.length > 0; let notificationsPending = this._notificationQueue.length > 0;
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved; let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
let notificationExpanded = this._notificationBin.y < 0; let notificationExpanded = this._notificationBin.y < 0;
let notificationExpired = (this._notificationTimeoutId == 0 && !this._pointerInTray && !this._locked) || this._notificationRemoved; let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked) || this._notificationRemoved;
if (this._notificationState == State.HIDDEN) { if (this._notificationState == State.HIDDEN) {
if (notificationsPending) if (notificationsPending)
@ -1499,27 +1544,45 @@ MessageTray.prototype = {
_updateShowingNotification: function() { _updateShowingNotification: function() {
Tweener.removeTweens(this._notificationBin); Tweener.removeTweens(this._notificationBin);
this._tween(this._notificationBin, '_notificationState', State.SHOWN,
{ y: 0,
opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showNotificationCompleted,
onCompleteScope: this
});
// We auto-expand urgent notifications. // We auto-expand notifications with CRITICAL urgency.
// We call _expandNotification() again on the notifications that // We use Tweener.removeTweens() to remove a tween that was hiding the notification we are
// are expanded in case they were in the process of hiding and need // updating, in case that notification was in the process of being hidden. However,
// to re-expand. // Tweener.removeTweens() would also remove a tween that was updating the position of the
if (this._notification.urgent || this._notification.expanded) // notification we are updating, in case that notification was already expanded and its height
// This will overwrite the y tween, but leave the opacity // changed. Therefore we need to call this._expandNotification() for expanded notifications
// tween, and so the onComplete will remain as well. // to make sure their position is updated.
if (this._notification.urgency == Urgency.CRITICAL || this._notification.expanded)
this._expandNotification(true); this._expandNotification(true);
// We tween all notifications to full opacity. This ensures that both new notifications and
// notifications that might have been in the process of hiding get full opacity.
//
// We tween any notification showing in the banner mode to banner height (this._notificationBin.y = 0).
// This ensures that both new notifications and notifications in the banner mode that might
// have been in the process of hiding are shown with the banner height.
//
// We use this._showNotificationCompleted() onComplete callback to extend the time the updated
// notification is being shown.
//
// We don't set the y parameter for the tween for expanded notifications because
// this._expandNotification() will result in getting this._notificationBin.y set to the appropriate
// fully expanded value.
let tweenParams = { opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showNotificationCompleted,
onCompleteScope: this
};
if (!this._notification.expanded)
tweenParams.y = 0;
this._tween(this._notificationBin, '_notificationState', State.SHOWN, tweenParams);
}, },
_showNotificationCompleted: function() { _showNotificationCompleted: function() {
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000); if (this._notification.urgency != Urgency.CRITICAL)
this._updateNotificationTimeout(NOTIFICATION_TIMEOUT * 1000);
}, },
_updateNotificationTimeout: function(timeout) { _updateNotificationTimeout: function(timeout) {
@ -1577,7 +1640,7 @@ MessageTray.prototype = {
let notification = this._notification; let notification = this._notification;
this._notification = null; this._notification = null;
if (notification.isTransient) if (notification.isTransient)
notification.destroy(); notification.destroy(NotificationDestroyedReason.EXPIRED);
}, },
_expandNotification: function(autoExpanding) { _expandNotification: function(autoExpanding) {
@ -1604,7 +1667,7 @@ MessageTray.prototype = {
}, },
// We use this function to grab focus when the user moves the pointer // We use this function to grab focus when the user moves the pointer
// to an urgent notification that was already auto-expanded. // to a notification with CRITICAL urgency that was already auto-expanded.
_ensureNotificationFocused: function() { _ensureNotificationFocused: function() {
this._notification.grabFocus(false); this._notification.grabFocus(false);
}, },
@ -1727,10 +1790,34 @@ MessageTray.prototype = {
let summaryNotification = this._summaryNotification; let summaryNotification = this._summaryNotification;
this._summaryNotification = null; this._summaryNotification = null;
if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide) if (summaryNotification.isTransient && !this._reNotifyWithSummaryNotificationAfterHide)
summaryNotification.destroy(); summaryNotification.destroy(NotificationDestroyedReason.EXPIRED);
if (this._reNotifyWithSummaryNotificationAfterHide) { if (this._reNotifyWithSummaryNotificationAfterHide) {
this._onNotify(summaryNotification.source, summaryNotification); this._onNotify(summaryNotification.source, summaryNotification);
this._reNotifyWithSummaryNotificationAfterHide = false; this._reNotifyWithSummaryNotificationAfterHide = false;
} }
} }
}; };
function SystemNotificationSource() {
this._init();
}
SystemNotificationSource.prototype = {
__proto__: Source.prototype,
_init: function() {
Source.prototype._init.call(this, _("System Information"));
this._setSummaryIcon(this.createNotificationIcon());
},
createNotificationIcon: function() {
return new St.Icon({ icon_name: 'dialog-information',
icon_type: St.IconType.SYMBOLIC,
icon_size: this.ICON_SIZE });
},
_notificationClicked: function() {
this.destroy();
}
};

235
js/ui/modalDialog.js Normal file
View File

@ -0,0 +1,235 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Params = imports.misc.params;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const OPEN_AND_CLOSE_TIME = 0.1;
const FADE_OUT_DIALOG_TIME = 1.0;
const State = {
OPENED: 0,
CLOSED: 1,
OPENING: 2,
CLOSING: 3,
FADED_OUT: 4
};
function ModalDialog() {
this._init();
}
ModalDialog.prototype = {
_init: function(params) {
params = Params.parse(params, { styleClass: null });
this.state = State.CLOSED;
this._group = new St.Group({ visible: false,
x: 0,
y: 0 });
Main.uiGroup.add_actor(this._group);
global.focus_manager.add_group(this._group);
this._initialKeyFocus = this._group;
this._group.connect('destroy', Lang.bind(this, this._onGroupDestroy));
this._actionKeys = {};
this._group.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this._lightbox = new Lightbox.Lightbox(this._group,
{ inhibitEvents: true });
this._backgroundBin = new St.Bin();
this._group.add_actor(this._backgroundBin);
this._lightbox.highlight(this._backgroundBin);
this._dialogLayout = new St.BoxLayout({ style_class: 'modal-dialog',
vertical: true });
if (params.styleClass != null) {
this._dialogLayout.add_style_class_name(params.styleClass);
}
this._backgroundBin.child = this._dialogLayout;
this.contentLayout = new St.BoxLayout({ vertical: true });
this._dialogLayout.add(this.contentLayout,
{ x_fill: true,
y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this._buttonLayout = new St.BoxLayout({ opacity: 220,
vertical: false });
this._dialogLayout.add(this._buttonLayout,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
},
setButtons: function(buttons) {
this._buttonLayout.destroy_children();
this._actionKeys = {};
let i = 0;
for (let index in buttons) {
let buttonInfo = buttons[index];
let label = buttonInfo['label'];
let action = buttonInfo['action'];
let key = buttonInfo['key'];
let button = new St.Button({ style_class: 'modal-dialog-button',
reactive: true,
can_focus: true,
label: label });
let x_alignment;
if (buttons.length == 1)
x_alignment = St.Align.END;
else if (i == 0)
x_alignment = St.Align.START;
else if (i == buttons.length - 1)
x_alignment = St.Align.END;
else
x_alignment = St.Align.MIDDLE;
this._initialKeyFocus = button;
this._buttonLayout.add(button,
{ expand: true,
x_fill: false,
y_fill: false,
x_align: x_alignment,
y_align: St.Align.MIDDLE });
button.connect('clicked', action);
if (key)
this._actionKeys[key] = action;
i++;
}
},
_onKeyPressEvent: function(object, keyPressEvent) {
let symbol = keyPressEvent.get_key_symbol();
let action = this._actionKeys[symbol];
if (action)
action();
},
_onGroupDestroy: function() {
this.emit('destroy');
},
_fadeOpen: function() {
let monitor = global.get_focus_monitor();
this._backgroundBin.set_position(monitor.x, monitor.y);
this._backgroundBin.set_size(monitor.width, monitor.height);
this.state = State.OPENING;
this._dialogLayout.opacity = 255;
this._lightbox.show();
this._group.opacity = 0;
this._group.show();
Tweener.addTween(this._group,
{ opacity: 255,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this._initialKeyFocus.grab_key_focus();
this.state = State.OPENED;
this.emit('opened');
}),
});
},
open: function(timestamp) {
if (this.state == State.OPENED || this.state == State.OPENING)
return true;
if (!Main.pushModal(this._group, timestamp))
return false;
global.stage.set_key_focus(this._group);
this._fadeOpen();
return true;
},
close: function(timestamp) {
if (this.state == State.CLOSED || this.state == State.CLOSING)
return;
let needsPopModal;
if (this.state == State.OPENED || this.state == State.OPENING)
needsPopModal = true;
else
needsPopModal = false;
this.state = State.CLOSING;
Tweener.addTween(this._group,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.state = State.CLOSED;
this._group.hide();
if (needsPopModal)
Main.popModal(this._group, timestamp);
})
});
},
// This method is like close, but fades the dialog out much slower,
// and leaves the lightbox in place. Once in the faded out state,
// the dialog can be brought back by an open call, or the lightbox
// can be dismissed by a close call.
//
// The main point of this method is to give some indication to the user
// that the dialog reponse has been acknowledged but will take a few
// moments before being processed.
// e.g., if a user clicked "Log Out" then the dialog should go away
// imediately, but the lightbox should remain until the logout is
// complete.
_fadeOutDialog: function(timestamp) {
if (this.state == State.CLOSED || this.state == State.CLOSING)
return;
if (this.state == State.FADED_OUT)
return;
Tweener.addTween(this._dialogLayout,
{ opacity: 0,
time: FADE_OUT_DIALOG_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.state = State.FADED_OUT;
Main.popModal(this._group, timestamp);
})
});
}
};
Signals.addSignalMethods(ModalDialog.prototype);

View File

@ -9,9 +9,11 @@ const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const Config = imports.misc.config;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params; const Params = imports.misc.params;
const Util = imports.misc.util;
let nextNotificationId = 1; let nextNotificationId = 1;
@ -126,17 +128,8 @@ NotificationDaemon.prototype = {
log('Failed to acquire org.freedesktop.Notifications'); log('Failed to acquire org.freedesktop.Notifications');
else { else {
log('Failed to acquire org.freedesktop.Notifications; trying again'); log('Failed to acquire org.freedesktop.Notifications; trying again');
Util.killall('notification-daemon');
// kill the notification-daemon. pkill is more portable Util.killall('notify-osd');
// 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();
} }
}, },
@ -153,9 +146,9 @@ NotificationDaemon.prototype = {
return new St.Icon({ icon_name: icon, return new St.Icon({ icon_name: icon,
icon_type: St.IconType.FULLCOLOR, icon_type: St.IconType.FULLCOLOR,
icon_size: size }); icon_size: size });
} else if (hints.icon_data) { } else if (hints['image-data']) {
let [width, height, rowStride, hasAlpha, let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints.icon_data; bitsPerSample, nChannels, data] = hints['image-data'];
return textureCache.load_from_raw(data, data.length, hasAlpha, return textureCache.load_from_raw(data, data.length, hasAlpha,
width, height, rowStride, size); width, height, rowStride, size);
} else { } else {
@ -245,6 +238,15 @@ NotificationDaemon.prototype = {
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true); hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
// Be compatible with the various hints for image data
// 'image-data' is the latest name of this hint, introduced in 1.2
if (!hints['image-data']) {
if (hints['image_data'])
hints['image-data'] = hints['image_data']; // version 1.1 of the spec
else if (hints['icon_data'])
hints['image-data'] = hints['icon_data']; // previous versions of the spec
}
let ndata = { appName: appName, let ndata = { appName: appName,
icon: icon, icon: icon,
summary: summary, summary: summary,
@ -320,13 +322,22 @@ NotificationDaemon.prototype = {
{ icon: iconActor, { icon: iconActor,
bannerMarkup: true }); bannerMarkup: true });
ndata.notification = notification; ndata.notification = notification;
notification.connect('clicked', Lang.bind(this,
function(n) {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
}));
notification.connect('destroy', Lang.bind(this, notification.connect('destroy', Lang.bind(this,
function(n) { function(n, reason) {
delete this._notifications[id]; delete this._notifications[id];
let notificationClosedReason;
switch (reason) {
case MessageTray.NotificationDestroyedReason.EXPIRED:
notificationClosedReason = NotificationClosedReason.EXPIRED;
break;
case MessageTray.NotificationDestroyedReason.DISMISSED:
notificationClosedReason = NotificationClosedReason.DISMISSED;
break;
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
break;
}
this._emitNotificationClosed(id, notificationClosedReason);
})); }));
notification.connect('action-invoked', Lang.bind(this, notification.connect('action-invoked', Lang.bind(this,
function(n, actionId) { function(n, actionId) {
@ -343,8 +354,17 @@ NotificationDaemon.prototype = {
for (let i = 0; i < actions.length - 1; i += 2) for (let i = 0; i < actions.length - 1; i += 2)
notification.addButton(actions[i], actions[i + 1]); notification.addButton(actions[i], actions[i + 1]);
} }
switch (hints.urgency) {
notification.setUrgent(hints.urgency == Urgency.CRITICAL); case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
break;
case Urgency.NORMAL:
notification.setUrgency(MessageTray.Urgency.NORMAL);
break;
case Urgency.CRITICAL:
notification.setUrgency(MessageTray.Urgency.CRITICAL);
break;
}
notification.setResident(hints.resident == true); notification.setResident(hints.resident == true);
// 'transient' is a reserved keyword in JS, so we have to retrieve the value // 'transient' is a reserved keyword in JS, so we have to retrieve the value
// of the 'transient' hint with hints['transient'] rather than hints.transient // of the 'transient' hint with hints['transient'] rather than hints.transient
@ -358,10 +378,9 @@ NotificationDaemon.prototype = {
let ndata = this._notifications[id]; let ndata = this._notifications[id];
if (ndata) { if (ndata) {
if (ndata.notification) if (ndata.notification)
ndata.notification.destroy(); ndata.notification.destroy(MessageTray.NotificationDestroyedReason.SOURCE_CLOSED);
delete this._notifications[id]; delete this._notifications[id];
} }
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
}, },
GetCapabilities: function() { GetCapabilities: function() {
@ -381,10 +400,10 @@ NotificationDaemon.prototype = {
GetServerInformation: function() { GetServerInformation: function() {
return [ return [
'GNOME Shell', Config.PACKAGE_NAME,
'GNOME', 'GNOME',
'0.1', // FIXME, get this from somewhere Config.PACKAGE_VERSION,
'1.0' '1.2'
]; ];
}, },
@ -467,8 +486,8 @@ Source.prototype = {
return; return;
// Only override the icon if we were previously using // Only override the icon if we were previously using
// notification-based icons (ie, not a trayicon) // notification-based icons (ie, not a trayicon) or if it was unset before
if (this.useNotificationIcon) { if (!this._isTrayIcon) {
this.useNotificationIcon = false; this.useNotificationIcon = false;
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE)); this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
} }

View File

@ -1,18 +1,21 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const Lang = imports.lang; const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const Gdk = imports.gi.Gdk;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const Dash = imports.ui.dash; const Dash = imports.ui.dash;
const DND = imports.ui.dnd;
const DocDisplay = imports.ui.docDisplay; const DocDisplay = imports.ui.docDisplay;
const GenericDisplay = imports.ui.genericDisplay;
const Lightbox = imports.ui.lightbox; const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main; const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
@ -28,30 +31,19 @@ const ANIMATION_TIME = 0.25;
// We split the screen vertically between the dash and the view selector. // We split the screen vertically between the dash and the view selector.
const DASH_SPLIT_FRACTION = 0.1; const DASH_SPLIT_FRACTION = 0.1;
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
function Source() { const SwipeScrollDirection = {
this._init(); NONE: 0,
} HORIZONTAL: 1,
VERTICAL: 2
};
Source.prototype = { const SwipeScrollResult = {
__proto__: MessageTray.Source.prototype, CANCEL: 0,
SWIPE: 1,
_init: function() { CLICK: 2
MessageTray.Source.prototype._init.call(this, };
"System Information");
this._setSummaryIcon(this.createNotificationIcon());
},
createNotificationIcon: function() {
return new St.Icon({ icon_name: 'dialog-information',
icon_type: St.IconType.SYMBOLIC,
icon_size: this.ICON_SIZE });
},
_notificationClicked: function() {
this.destroy();
}
}
function ShellInfo() { function ShellInfo() {
this._init(); this._init();
@ -74,7 +66,7 @@ ShellInfo.prototype = {
setMessage: function(text, undoCallback, undoLabel) { setMessage: function(text, undoCallback, undoLabel) {
if (this._source == null) { if (this._source == null) {
this._source = new Source(); this._source = new MessageTray.SystemNotificationSource();
this._source.connect('destroy', Lang.bind(this, this._source.connect('destroy', Lang.bind(this,
function() { function() {
this._source = null; this._source = null;
@ -119,7 +111,8 @@ Overview.prototype = {
this._spacing = 0; this._spacing = 0;
this._group = new St.Group({ name: 'overview' }); this._group = new St.Group({ name: 'overview',
reactive: true });
this._group._delegate = this; this._group._delegate = this;
this._group.connect('style-changed', this._group.connect('style-changed',
Lang.bind(this, function() { Lang.bind(this, function() {
@ -131,11 +124,19 @@ Overview.prototype = {
} }
})); }));
this._scrollDirection = SwipeScrollDirection.NONE;
this._scrollAdjustment = null;
this._capturedEventId = 0;
this._buttonPressId = 0;
this.shellInfo = new ShellInfo(); this.shellInfo = new ShellInfo();
this._workspacesDisplay = null; this._workspacesDisplay = null;
this.visible = false; this.visible = false; // animating to overview, in overview, animating out
this._shown = false; // show() and not hide()
this._shownTemporarily = false; // showTemporarily() and not hideTemporarily()
this._modal = false; // have a modal grab
this.animationInProgress = false; this.animationInProgress = false;
this._hideInProgress = false; this._hideInProgress = false;
@ -172,11 +173,236 @@ Overview.prototype = {
this._dash.actor.add_constraint(this.viewSelector.constrainY); this._dash.actor.add_constraint(this.viewSelector.constrainY);
this._dash.actor.add_constraint(this.viewSelector.constrainHeight); this._dash.actor.add_constraint(this.viewSelector.constrainHeight);
this._coverPane.lower_bottom(); this._coverPane.hide();
// XDND
this._dragMonitor = {
dragMotion: Lang.bind(this, this._onDragMotion)
};
Main.xdndHandler.connect('drag-begin', Lang.bind(this, this._onDragBegin));
Main.xdndHandler.connect('drag-end', Lang.bind(this, this._onDragEnd));
this._windowSwitchTimeoutId = 0;
this._windowSwitchTimestamp = 0;
this._lastActiveWorkspaceIndex = -1;
this._lastHoveredWindow = null;
this._needsFakePointerEvent = false;
this.workspaces = null; this.workspaces = null;
}, },
_onDragBegin: function() {
DND.addDragMonitor(this._dragMonitor);
// Remember the workspace we started from
this._lastActiveWorkspaceIndex = global.screen.get_active_workspace_index();
},
_onDragEnd: function(time) {
// In case the drag was canceled while in the overview
// we have to go back to where we started and hide
// the overview
if (this._shownTemporarily) {
global.screen.get_workspace_by_index(this._lastActiveWorkspaceIndex).activate(time);
this.hideTemporarily();
}
this._lastHoveredWindow = null;
DND.removeMonitor(this._dragMonitor);
},
_fakePointerEvent: function() {
let display = Gdk.Display.get_default();
let deviceManager = display.get_device_manager();
let pointer = deviceManager.get_client_pointer();
let [screen, pointerX, pointerY] = pointer.get_position();
pointer.warp(screen, pointerX, pointerY);
},
_onDragMotion: function(dragEvent) {
let targetIsWindow = dragEvent.targetActor &&
dragEvent.targetActor._delegate &&
dragEvent.targetActor._delegate.metaWindow;
if (targetIsWindow &&
dragEvent.targetActor._delegate.metaWindow == this._lastHoveredWindow)
return DND.DragMotionResult.CONTINUE;
this._lastHoveredWindow = null;
if (this._windowSwitchTimeoutId != 0) {
Mainloop.source_remove(this._windowSwitchTimeoutId);
this._windowSwitchTimeoutId = 0;
this._needsFakePointerEvent = false;
}
if (targetIsWindow) {
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimestamp = global.get_current_time();
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
Lang.bind(this, function() {
this._needsFakePointerEvent = true;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
this._windowSwitchTimestamp);
this.hideTemporarily();
this._lastHoveredWindow = null;
}));
}
return DND.DragMotionResult.CONTINUE;
},
setScrollAdjustment: function(adjustment, direction) {
this._scrollAdjustment = adjustment;
if (this._scrollAdjustment == null)
this._scrollDirection = SwipeScrollDirection.NONE;
else
this._scrollDirection = direction;
},
_onButtonPress: function(actor, event) {
if (this._scrollDirection == SwipeScrollDirection.NONE)
return;
let [stageX, stageY] = event.get_coords();
this._dragStartX = this._dragX = stageX;
this._dragStartY = this._dragY = stageY;
this._dragStartValue = this._scrollAdjustment.value;
this._lastMotionTime = -1; // used to track "stopping" while swipe-scrolling
this._capturedEventId = global.stage.connect('captured-event',
Lang.bind(this, this._onCapturedEvent));
this.emit('swipe-scroll-begin');
},
_onCapturedEvent: function(actor, event) {
let stageX, stageY;
let threshold = Gtk.Settings.get_default().gtk_dnd_drag_threshold;
switch(event.type()) {
case Clutter.EventType.BUTTON_RELEASE:
[stageX, stageY] = event.get_coords();
// default to snapping back to the original value
let newValue = this._dragStartValue;
let minValue = this._scrollAdjustment.lower;
let maxValue = this._scrollAdjustment.upper - this._scrollAdjustment.page_size;
let direction;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
direction = stageX > this._dragStartX ? -1 : 1;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
direction *= -1;
} else {
direction = stageY > this._dragStartY ? -1 : 1;
}
// We default to scroll a full page size; both the first
// and the last page may be smaller though, so we need to
// adjust difference in those cases.
let difference = direction * this._scrollAdjustment.page_size;
if (this._dragStartValue + difference > maxValue)
difference = maxValue - this._dragStartValue;
else if (this._dragStartValue + difference < minValue)
difference = minValue - this._dragStartValue;
// If the user has moved more than half the scroll
// difference, we want to "settle" to the new value
// even if the user stops dragging rather "throws" by
// releasing during the drag.
let distance = this._dragStartValue - this._scrollAdjustment.value;
let noStop = Math.abs(distance / difference) > 0.5;
// We detect if the user is stopped by comparing the
// timestamp of the button release with the timestamp of
// the last motion. Experimentally, a difference of 0 or 1
// millisecond indicates that the mouse is in motion, a
// larger difference indicates that the mouse is stopped.
if ((this._lastMotionTime > 0 &&
this._lastMotionTime > event.get_time() - 2) ||
noStop) {
if (this._dragStartValue + difference >= minValue &&
this._dragStartValue + difference <= maxValue)
newValue += difference;
}
let result;
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold) {
// no motion? It's a click!
result = SwipeScrollResult.CLICK;
this.emit('swipe-scroll-end', result);
} else {
if (newValue == this._dragStartValue)
result = SwipeScrollResult.CANCEL;
else
result = SwipeScrollResult.SWIPE;
// The event capture handler is disconnected
// while scrolling to the final position, so
// to avoid undesired prelights we raise
// the cover pane.
this._coverPane.raise_top();
this._coverPane.show();
Tweener.addTween(this._scrollAdjustment,
{ value: newValue,
time: ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete: function() {
this._coverPane.hide();
this.emit('swipe-scroll-end',
result);
}
});
}
global.stage.disconnect(this._capturedEventId);
this._capturedEventId = 0;
return result != SwipeScrollResult.CLICK;
case Clutter.EventType.MOTION:
[stageX, stageY] = event.get_coords();
let dx = this._dragX - stageX;
let dy = this._dragY - stageY;
let primary = global.get_primary_monitor();
this._dragX = stageX;
this._dragY = stageY;
this._lastMotionTime = event.get_time();
// See if the user has moved the mouse enough to trigger
// a drag
if (Math.abs(stageX - this._dragStartX) < threshold &&
Math.abs(stageY - this._dragStartY) < threshold)
return true;
if (this._scrollDirection == SwipeScrollDirection.HORIZONTAL) {
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
this._scrollAdjustment.value -= (dx / primary.width) * this._scrollAdjustment.page_size;
else
this._scrollAdjustment.value += (dx / primary.width) * this._scrollAdjustment.page_size;
} else {
this._scrollAdjustment.value += (dy / primary.height) * this._scrollAdjustment.page_size;
}
return true;
// Block enter/leave events to avoid prelights
// during swipe-scroll
case Clutter.EventType.ENTER:
case Clutter.EventType.LEAVE:
return true;
}
return false;
},
_getDesktopClone: function() { _getDesktopClone: function() {
let windows = global.get_window_actors().filter(function(w) { let windows = global.get_window_actors().filter(function(w) {
return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP; return w.meta_window.get_window_type() == Meta.WindowType.DESKTOP;
@ -267,11 +493,26 @@ Overview.prototype = {
return [this.workspaces.actor.x, this.workspaces.actor.y]; return [this.workspaces.actor.x, this.workspaces.actor.y];
}, },
// show:
//
// Animates the overview visible and grabs mouse and keyboard input
show : function() { show : function() {
if (this.visible) if (this._shown)
return; return;
// Do this manually instead of using _syncInputMode, to handle failure
if (!Main.pushModal(this.viewSelector.actor)) if (!Main.pushModal(this.viewSelector.actor))
return; return;
this._modal = true;
this._animateVisible();
this._shown = true;
this._buttonPressId = this._group.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
},
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
this.visible = true; this.visible = true;
this.animationInProgress = true; this.animationInProgress = true;
@ -334,11 +575,110 @@ Overview.prototype = {
}); });
this._coverPane.raise_top(); this._coverPane.raise_top();
this._coverPane.show();
this.emit('showing'); this.emit('showing');
}, },
// showTemporarily:
//
// Animates the overview visible without grabbing mouse and keyboard input;
// if show() has already been called, this has no immediate effect, but
// will result in the overview not being hidden until hideTemporarily() is
// called.
showTemporarily: function() {
if (this._shownTemporarily)
return;
this._syncInputMode();
this._animateVisible();
this._shownTemporarily = true;
},
// hide:
//
// Reverses the effect of show()
hide: function() { hide: function() {
if (!this.visible || this._hideInProgress) if (!this._shown)
return;
if (!this._shownTemporarily)
this._animateNotVisible();
this._shown = false;
this._syncInputMode();
if (this._buttonPressId > 0)
this._group.disconnect(this._buttonPressId);
this._buttonPressId = 0;
},
// hideTemporarily:
//
// Reverses the effect of showTemporarily()
hideTemporarily: function() {
if (!this._shownTemporarily)
return;
if (!this._shown)
this._animateNotVisible();
this._shownTemporarily = false;
this._syncInputMode();
},
toggle: function() {
if (this._shown)
this.hide();
else
this.show();
},
/**
* getWorkspacesForWindow:
* @metaWindow: A #MetaWindow
*
* Returns the Workspaces object associated with the given window.
* This method is not be accessible if the overview is not open
* and will return %null.
*/
getWorkspacesForWindow: function(metaWindow) {
return this.workspaces;
},
//// Private methods ////
_syncInputMode: function() {
// We delay input mode changes during animation so that when removing the
// overview we don't have a problem with the release of a press/release
// going to an application.
if (this.animationInProgress)
return;
if (this._shown) {
if (!this._modal) {
if (Main.pushModal(this._dash.actor))
this._modal = true;
else
this.hide();
}
} else if (this._shownTemporarily) {
if (this._modal) {
Main.popModal(this._dash.actor);
this._modal = false;
}
global.stage_input_mode = Shell.StageInputMode.FULLSCREEN;
} else {
if (this._modal) {
Main.popModal(this._dash.actor);
this._modal = false;
}
else if (global.stage_input_mode == Shell.StageInputMode.FULLSCREEN)
global.stage_input_mode = Shell.StageInputMode.NORMAL;
}
},
_animateNotVisible: function() {
if (!this.visible || this.animationInProgress)
return; return;
this.animationInProgress = true; this.animationInProgress = true;
@ -379,39 +719,21 @@ Overview.prototype = {
}); });
this._coverPane.raise_top(); this._coverPane.raise_top();
this._coverPane.show();
this.emit('hiding'); this.emit('hiding');
}, },
toggle: function() {
if (this.visible)
this.hide();
else
this.show();
},
/**
* getWorkspacesForWindow:
* @metaWindow: A #MetaWindow
*
* Returns the Workspaces object associated with the given window.
* This method is not be accessible if the overview is not open
* and will return %null.
*/
getWorkspacesForWindow: function(metaWindow) {
return this.workspaces;
},
//// Private methods ////
_showDone: function() { _showDone: function() {
if (this._hideInProgress)
return;
this.animationInProgress = false; this.animationInProgress = false;
this._desktopFade.hide(); this._desktopFade.hide();
this._coverPane.lower_bottom(); this._coverPane.hide();
this.emit('shown'); this.emit('shown');
// Handle any calls to hide* while we were showing
if (!this._shown && !this._shownTemporarily)
this._animateNotVisible();
this._syncInputMode();
}, },
_hideDone: function() { _hideDone: function() {
@ -432,10 +754,20 @@ Overview.prototype = {
this.animationInProgress = false; this.animationInProgress = false;
this._hideInProgress = false; this._hideInProgress = false;
this._coverPane.lower_bottom(); this._coverPane.hide();
Main.popModal(this.viewSelector.actor);
this.emit('hidden'); this.emit('hidden');
// Handle any calls to show* while we were hiding
if (this._shown || this._shownTemporarily)
this._animateVisible();
this._syncInputMode();
// Fake a pointer event if requested
if (this._needsFakePointerEvent) {
this._fakePointerEvent();
this._needsFakePointerEvent = false;
}
} }
}; };
Signals.addSignalMethods(Overview.prototype); Signals.addSignalMethods(Overview.prototype);

View File

@ -17,6 +17,7 @@ const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const StatusMenu = imports.ui.statusMenu; const StatusMenu = imports.ui.statusMenu;
const DateMenu = imports.ui.dateMenu;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@ -26,6 +27,8 @@ const PANEL_ICON_SIZE = 24;
const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5; const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
const ANIMATED_ICON_UPDATE_TIMEOUT = 100; const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const SPINNER_UPDATE_TIMEOUT = 130; const SPINNER_UPDATE_TIMEOUT = 130;
const SPINNER_SPEED = 0.02; const SPINNER_SPEED = 0.02;
@ -34,14 +37,17 @@ const STANDARD_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'blue
const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = { const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator, 'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator, 'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator 'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator
}; };
if (Config.HAVE_BLUETOOTH) if (Config.HAVE_BLUETOOTH)
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator; STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
const CLOCK_FORMAT_KEY = 'format'; // in org.gnome.desktop.interface
const CLOCK_CUSTOM_FORMAT_KEY = 'custom-format'; const CLOCK_FORMAT_KEY = 'clock-format';
// in org.gnome.shell.clock
const CLOCK_SHOW_DATE_KEY = 'show-date'; const CLOCK_SHOW_DATE_KEY = 'show-date';
const CLOCK_SHOW_SECONDS_KEY = 'show-seconds'; const CLOCK_SHOW_SECONDS_KEY = 'show-seconds';
@ -487,147 +493,6 @@ AppMenuButton.prototype = {
Signals.addSignalMethods(AppMenuButton.prototype); Signals.addSignalMethods(AppMenuButton.prototype);
function ClockButton() {
this._init();
}
ClockButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this.menu.addAction(_("Preferences"), Lang.bind(this, this._onPrefs));
this._clock = new St.Label();
this.actor.set_child(this._clock);
this._calendarPopup = null;
this._clockSettings = new Gio.Settings({ schema: 'org.gnome.shell.clock' });
this._clockSettings.connect('changed', Lang.bind(this, this._updateClock));
// Start the clock
this._updateClock();
},
_onButtonPress: function(actor, event) {
let button = event.get_button();
let menuShowing = this.menu.isOpen;
let calendarShowing = this._calendarPopup && this._calendarPopup.isOpen;
if (menuShowing || (button == 3 && !calendarShowing))
this.menu.toggle();
else
this._toggleCalendar();
return true;
},
closeCalendar: function() {
if (!this._calendarPopup || !this._calendarPopup.isOpen)
return;
this._calendarPopup.hide();
this.actor.remove_style_pseudo_class('pressed');
},
openCalendar: function() {
this._calendarPopup.show();
this.actor.add_style_pseudo_class('pressed');
},
_onPrefs: function() {
let args = ['gnome-shell-clock-preferences'];
let p = new Shell.Process({ args: args });
p.run();
},
_toggleCalendar: function() {
if (this._calendarPopup == null) {
this._calendarPopup = new CalendarPopup();
this._calendarPopup.actor.hide();
}
if (this.menu.isOpen && !this._calendarPopup.isOpen) {
this.menu.close();
return;
}
if (!this._calendarPopup.isOpen)
this.openCalendar();
else
this.closeCalendar();
},
_updateClock: function() {
let format = this._clockSettings.get_string(CLOCK_FORMAT_KEY);
let showDate = this._clockSettings.get_boolean(CLOCK_SHOW_DATE_KEY);
let showSeconds = this._clockSettings.get_boolean(CLOCK_SHOW_SECONDS_KEY);
let clockFormat;
switch (format) {
case 'unix':
// force updates every second
showSeconds = true;
clockFormat = '%s';
break;
case 'custom':
// force updates every second
showSeconds = true;
clockFormat = this._clockSettings.get_string(CLOCK_CUSTOM_FORMAT_KEY);
break;
case '24-hour':
if (showDate)
/* Translators: This is the time format with date used
in 24-hour mode. */
clockFormat = showSeconds ? _("%a %b %e, %R:%S")
: _("%a %b %e, %R");
else
/* Translators: This is the time format without date used
in 24-hour mode. */
clockFormat = showSeconds ? _("%a %R:%S")
: _("%a %R");
break;
case '12-hour':
default:
if (showDate)
/* Translators: This is a time format with date used
for AM/PM. */
clockFormat = showSeconds ? _("%a %b %e, %l:%M:%S %p")
: _("%a %b %e, %l:%M %p");
else
/* Translators: This is a time format without date used
for AM/PM. */
clockFormat = showSeconds ? _("%a %l:%M:%S %p")
: _("%a %l:%M %p");
break;
}
let displayDate = new Date();
let msecRemaining;
if (showSeconds) {
msecRemaining = 1000 - displayDate.getMilliseconds();
if (msecRemaining < 50) {
displayDate.setSeconds(displayDate.getSeconds() + 1);
msecRemaining += 1000;
}
} else {
msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
displayDate.getMilliseconds());
if (msecRemaining < 500) {
displayDate.setMinutes(displayDate.getMinutes() + 1);
msecRemaining += 60000;
}
}
this._clock.set_text(displayDate.toLocaleFormat(clockFormat));
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClock));
return false;
}
};
function Panel() { function Panel() {
this._init(); this._init();
} }
@ -752,7 +617,20 @@ Panel.prototype = {
reactive: true, reactive: true,
can_focus: true }); can_focus: true });
this.button.set_child(label); this.button.set_child(label);
this.button._delegate = this.button;
this.button._xdndTimeOut = 0;
this.button.handleDragOver = Lang.bind(this,
function(source, actor, x, y, time) {
if (source == Main.xdndHandler) {
if (this.button._xdndTimeOut != 0)
Mainloop.source_remove(this.button._xdndTimeOut);
this.button._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT,
Lang.bind(this,
function() {
this._xdndShowOverview(actor);
}));
}
});
this._leftBox.add(this.button); this._leftBox.add(this.button);
// We use this flag to mark the case where the user has entered the // We use this flag to mark the case where the user has entered the
@ -790,6 +668,18 @@ Panel.prototype = {
this._hotCorner.connect('leave-event', this._hotCorner.connect('leave-event',
Lang.bind(this, this._onHotCornerLeft)); Lang.bind(this, this._onHotCornerLeft));
this._hotCorner._delegate = this._hotCorner;
this._hotCorner.handleDragOver = Lang.bind(this,
function(source, actor, x, y, time) {
if (source == Main.xdndHandler) {
if(!Main.overview.visible && !Main.overview.animationInProgress) {
this.rippleAnimation();
Main.overview.showTemporarily();
Main.overview.beginItemDrag(actor);
}
}
});
this._boxContainer.add_actor(this._hotCornerEnvirons); this._boxContainer.add_actor(this._hotCornerEnvirons);
this._boxContainer.add_actor(this._hotCorner); this._boxContainer.add_actor(this._hotCorner);
@ -799,26 +689,21 @@ Panel.prototype = {
this._menus.addMenu(appMenuButton.menu); this._menus.addMenu(appMenuButton.menu);
/* center */ /* center */
this._dateMenu = new DateMenu.DateMenuButton();
this._clockButton = new ClockButton(); this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._centerBox.add(this._clockButton.actor, { y_fill: true }); this._menus.addMenu(this._dateMenu.menu);
let clockMenuManager = new PopupMenu.PopupMenuManager(this);
clockMenuManager.addMenu(this._clockButton.menu);
/* right */ /* right */
// System status applets live in statusBox, while legacy tray icons // System status applets live in statusBox, while legacy tray icons
// live in trayBox // live in trayBox
// The trayBox is hidden when there are no tray icons. // The trayBox is hidden when there are no tray icons.
let statusBox = new St.BoxLayout({ name: 'statusTray' }); this._trayBox = new St.BoxLayout({ name: 'legacyTray' });
let trayBox = new St.BoxLayout({ name: 'legacyTray' }); this._statusBox = new St.BoxLayout({ name: 'statusTray' });
this._trayBox = trayBox;
this._statusBox = statusBox;
trayBox.hide(); this._trayBox.hide();
this._rightBox.add(trayBox); this._rightBox.add(this._trayBox);
this._rightBox.add(statusBox); this._rightBox.add(this._statusBox);
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded)); Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved)); Main.statusIconDispatcher.connect('status-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
@ -848,6 +733,25 @@ Panel.prototype = {
Main.chrome.addActor(this.actor, { visibleInOverview: true }); Main.chrome.addActor(this.actor, { visibleInOverview: true });
}, },
_xdndShowOverview: function (actor) {
let [x, y, mask] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
if (pickedActor != this.button) {
Mainloop.source_remove(this.button._xdndTimeOut);
this.button._xdndTimeOut = 0;
return;
}
if(!Main.overview.visible && !Main.overview.animationInProgress) {
Main.overview.showTemporarily();
Main.overview.beginItemDrag(actor);
}
Mainloop.source_remove(this.button._xdndTimeOut);
this.button._xdndTimeOut = 0;
},
startStatusArea: function() { startStatusArea: function() {
for (let i = 0; i < STANDARD_TRAY_ICON_ORDER.length; i++) { for (let i = 0; i < STANDARD_TRAY_ICON_ORDER.length; i++) {
let role = STANDARD_TRAY_ICON_ORDER[i]; let role = STANDARD_TRAY_ICON_ORDER[i];
@ -866,10 +770,6 @@ Panel.prototype = {
this._rightBox.add(this._statusmenu.actor); this._rightBox.add(this._statusmenu.actor);
}, },
hideCalendar: function() {
this._clockButton.closeCalendar();
},
startupAnimation: function() { startupAnimation: function() {
this.actor.y = -this.actor.height; this.actor.y = -this.actor.height;
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
@ -942,6 +842,17 @@ Panel.prototype = {
Main.uiGroup.add_actor(ripple); Main.uiGroup.add_actor(ripple);
}, },
rippleAnimation: function() {
// 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);
},
_onHotCornerEntered : function() { _onHotCornerEntered : function() {
if (this._menus.grabbed) if (this._menus.grabbed)
return false; return false;
@ -950,14 +861,7 @@ Panel.prototype = {
if (!Main.overview.animationInProgress) { if (!Main.overview.animationInProgress) {
this._hotCornerActivationTime = Date.now() / 1000; this._hotCornerActivationTime = Date.now() / 1000;
// Show three concentric ripples expanding outwards; the exact this.rippleAnimation();
// 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(); Main.overview.toggle();
} }
} }
@ -1004,6 +908,9 @@ function CalendarPopup() {
CalendarPopup.prototype = { CalendarPopup.prototype = {
_init: function() { _init: function() {
let panelActor = Main.panel.actor; let panelActor = Main.panel.actor;
let alignConstraint = new Clutter.AlignConstraint({ source: panelActor,
align_axis: Clutter.AlignAxis.X_AXIS,
factor: 0.5 });
this.actor = new St.Bin({ name: 'calendarPopup' }); this.actor = new St.Bin({ name: 'calendarPopup' });
@ -1015,7 +922,7 @@ CalendarPopup.prototype = {
Main.chrome.addActor(this.actor, { visibleInOverview: true, Main.chrome.addActor(this.actor, { visibleInOverview: true,
affectsStruts: false }); affectsStruts: false });
this.actor.y = (panelActor.y + panelActor.height - this.actor.height); this.actor.y = (panelActor.y + panelActor.height - this.actor.height);
this.calendar.actor.connect('notify::width', Lang.bind(this, this._centerPopup)); this.actor.add_constraint(alignConstraint);
}, },
show: function() { show: function() {
@ -1028,7 +935,6 @@ CalendarPopup.prototype = {
// Reset the calendar to today's date // Reset the calendar to today's date
this.calendar.setDate(new Date()); this.calendar.setDate(new Date());
this._centerPopup();
this.actor.lower(panelActor); this.actor.lower(panelActor);
this.actor.show(); this.actor.show();
Tweener.addTween(this.actor, Tweener.addTween(this.actor,
@ -1052,10 +958,5 @@ CalendarPopup.prototype = {
onComplete: function() { this.actor.hide(); }, onComplete: function() { this.actor.hide(); },
onCompleteScope: this onCompleteScope: this
}); });
},
_centerPopup: function() {
let panelActor = Main.panel.actor;
this.actor.x = Math.round(panelActor.x + (panelActor.width - this.actor.width) / 2);
} }
}; };

View File

@ -1,6 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const GConf = imports.gi.GConf;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell; const Shell = imports.gi.Shell;
@ -13,12 +12,9 @@ const _ = Gettext.gettext;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params;
const Search = imports.ui.search; const Search = imports.ui.search;
const Util = imports.misc.util;
const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences';
const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir';
const PLACES_ICON_SIZE = 16;
/** /**
* Represents a place object, which is most normally a bookmark entry, * Represents a place object, which is most normally a bookmark entry,
@ -63,6 +59,21 @@ PlaceInfo.prototype = {
} }
}; };
// Helper function to translate launch parameters into a GAppLaunchContext
function _makeLaunchContext(params)
{
params = Params.parse(params, { workspace: null,
timestamp: null });
let launchContext = global.create_app_launch_context();
if (params.workspace != null)
launchContext.set_desktop(params.workspace.index());
if (params.timestamp != null)
launchContext.set_timestamp(params.timestamp);
return launchContext;
}
function PlaceDeviceInfo(mount) { function PlaceDeviceInfo(mount) {
this._init(mount); this._init(mount);
} }
@ -82,9 +93,9 @@ PlaceDeviceInfo.prototype = {
return St.TextureCache.get_default().load_gicon(null, icon, size); return St.TextureCache.get_default().load_gicon(null, icon, size);
}, },
launch: function() { launch: function(param) {
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(), Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
global.create_app_launch_context()); _makeLaunchContex(params));
}, },
isRemovable: function() { isRemovable: function() {
@ -116,20 +127,15 @@ PlaceDeviceInfo.prototype = {
} }
}; };
function PlacesManager() { function PlacesManager() {
this._init(); this._init();
} }
PlacesManager.prototype = { PlacesManager.prototype = {
_init: function() { _init: function() {
let gconf = GConf.Client.get_default();
gconf.add_dir(NAUTILUS_PREFS_DIR, GConf.ClientPreloadType.PRELOAD_NONE);
this._defaultPlaces = []; this._defaultPlaces = [];
this._mounts = []; this._mounts = [];
this._bookmarks = []; this._bookmarks = [];
this._isDesktopHome = gconf.get_bool(DESKTOP_IS_HOME_KEY);
let homeFile = Gio.file_new_for_path (GLib.get_home_dir()); let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
let homeUri = homeFile.get_uri(); let homeUri = homeFile.get_uri();
@ -139,8 +145,8 @@ PlacesManager.prototype = {
function(size) { function(size) {
return St.TextureCache.get_default().load_gicon(null, homeIcon, size); return St.TextureCache.get_default().load_gicon(null, homeIcon, size);
}, },
function() { function(params) {
Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context()); Gio.app_info_launch_default_for_uri(homeUri, _makeLaunchContext(params));
}); });
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
@ -152,8 +158,8 @@ PlacesManager.prototype = {
function(size) { function(size) {
return St.TextureCache.get_default().load_gicon(null, desktopIcon, size); return St.TextureCache.get_default().load_gicon(null, desktopIcon, size);
}, },
function() { function(params) {
Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context()); Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params));
}); });
this._connect = new PlaceInfo('special:connect', _("Connect to..."), this._connect = new PlaceInfo('special:connect', _("Connect to..."),
@ -162,8 +168,12 @@ PlacesManager.prototype = {
icon_type: St.IconType.FULLCOLOR, icon_type: St.IconType.FULLCOLOR,
icon_size: size }); icon_size: size });
}, },
function () { function (params) {
new Shell.Process({ args: ['nautilus-connect-server'] }).run(); // BUG: nautilus-connect-server doesn't have a desktop file, so we can'
// launch it with the workspace from params. It's probably pretty rare
// and odd to drag this place onto a workspace in any case
Util.spawn(['nautilus-connect-server']);
}); });
let networkApp = null; let networkApp = null;
@ -182,16 +192,17 @@ PlacesManager.prototype = {
function(size) { function(size) {
return networkApp.create_icon_texture(size); return networkApp.create_icon_texture(size);
}, },
function () { function (params) {
networkApp.launch(); params = Params.parse(params, { workspace: null,
timestamp: 0 });
networkApp.launch_full(params.timestamp, [],
params.workspace ? params.workspace.index() : -1);
}); });
} }
this._defaultPlaces.push(this._home); this._defaultPlaces.push(this._home);
this._defaultPlaces.push(this._desktopMenu);
this._desktopMenuIndex = this._defaultPlaces.length;
if (!this._isDesktopHome)
this._defaultPlaces.push(this._desktopMenu);
if (this._network) if (this._network)
this._defaultPlaces.push(this._network); this._defaultPlaces.push(this._network);
@ -229,9 +240,6 @@ PlacesManager.prototype = {
})); }));
this._reloadBookmarks(); this._reloadBookmarks();
gconf.notify_add(DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
}, },
_updateDevices: function() { _updateDevices: function() {
@ -329,8 +337,8 @@ PlacesManager.prototype = {
function(size) { function(size) {
return St.TextureCache.get_default().load_gicon(null, icon, size); return St.TextureCache.get_default().load_gicon(null, icon, size);
}, },
function() { function(params) {
Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context()); Gio.app_info_launch_default_for_uri(bookmark, _makeLaunchContext(params));
}); });
this._bookmarks.push(item); this._bookmarks.push(item);
} }
@ -340,21 +348,6 @@ PlacesManager.prototype = {
this.emit('places-updated'); this.emit('places-updated');
}, },
_updateDesktopMenuVisibility: function() {
let gconf = GConf.Client.get_default();
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
if (this._isDesktopHome)
this._removeById(this._defaultPlaces, 'special:desktop');
else
this._defaultPlaces.splice(this._desktopMenuIndex, 0,
this._desktopMenu);
/* See comment in _updateDevices for explanation why there are two signals. */
this.emit('defaults-updated');
this.emit('places-updated');
},
_addMount: function(mount) { _addMount: function(mount) {
let devItem = new PlaceDeviceInfo(mount); let devItem = new PlaceDeviceInfo(mount);
this._mounts.push(devItem); this._mounts.push(devItem);
@ -402,150 +395,8 @@ PlacesManager.prototype = {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1); sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
} }
}; };
Signals.addSignalMethods(PlacesManager.prototype); Signals.addSignalMethods(PlacesManager.prototype);
/**
* An entry in the places menu.
* @info The corresponding PlaceInfo to populate this entry.
*/
function DashPlaceDisplayItem(info) {
this._init(info);
}
DashPlaceDisplayItem.prototype = {
_init: function(info) {
this.name = info.name;
this._info = info;
this._icon = info.iconFactory(PLACES_ICON_SIZE);
this.actor = new St.Clickable({ style_class: 'places-item',
reactive: true,
x_align: St.Align.START,
x_fill: true });
let box = new St.BoxLayout({ style_class: 'places-item-box' });
this.actor.set_child(box);
let bin = new St.Bin({ child: this._icon });
box.add(bin);
let text = new St.Label({ text: info.name });
box.add(text, { expand: true, x_fill: true });
if (info.isRemovable()) {
let removeIcon = new St.Icon({ icon_name: 'media-eject',
icon_type: St.IconType.FULLCOLOR,
icon_size: PLACES_ICON_SIZE });
let removeIconBox = new St.Clickable({ child: removeIcon,
reactive: true });
box.add(removeIconBox);
removeIconBox.connect('clicked',
Lang.bind(this, function() {
this._info.remove();
}));
}
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor._delegate = this;
this._draggable = DND.makeDraggable(this.actor);
this._draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
this._draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
},
_onClicked: function(b) {
this._info.launch();
Main.overview.hide();
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
return this._info.iconFactory(PLACES_ICON_SIZE);
},
//// Drag and drop methods ////
shellWorkspaceLaunch: function() {
this._info.launch();
}
};
function DashPlaceDisplay() {
this._init();
}
DashPlaceDisplay.prototype = {
_init: function() {
// Places is divided semi-arbitrarily into left and right; a grid would
// look better in that there would be an even number of items left+right,
// but it seems like we want some sort of differentiation between actions
// like "Connect to server..." and regular folders
this.actor = new St.Table({ style_class: 'places-section',
homogeneous: true });
this._defaultsList = [];
this._bookmarksList = [];
this._mountsList = [];
Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults));
Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks));
Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts));
this._updateDefaults();
this._updateMounts();
this._updateBookmarks();
},
_updateDefaults: function() {
for (let i = 0; i < this._defaultsList.length; i++)
this._defaultsList[i].destroy();
this._defaultsList = [];
let places = Main.placesManager.getDefaultPlaces();
for (let i = 0; i < places.length; i++) {
this._defaultsList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._defaultsList[i], {row: i, col: 0});
}
this._updateMounts();
},
_updateMounts: function() {
for (let i = 0; i < this._mountsList.length; i++)
this._mountsList[i].destroy();
this._mountsList = [];
let places = Main.placesManager.getMounts();
for (let i = 0; i < places.length; i++) {
this._mountsList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._mountsList[i], {row: this._defaultsList.length + i, col: 0});
}
},
_updateBookmarks: function() {
for (let i = 0; i < this._bookmarksList.length; i++)
this._bookmarksList[i].destroy();
this._bookmarksList = [];
let places = Main.placesManager.getBookmarks();
for (let i = 0; i < places.length; i ++) {
this._bookmarksList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._bookmarksList[i], {row: i, col: 1});
}
}
};
Signals.addSignalMethods(DashPlaceDisplay.prototype);
function PlaceSearchProvider() { function PlaceSearchProvider() {
this._init(); this._init();
@ -567,9 +418,9 @@ PlaceSearchProvider.prototype = {
'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) }; 'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) };
}, },
activateResult: function(id) { activateResult: function(id, params) {
let placeInfo = Main.placesManager.lookupPlaceById(id); let placeInfo = Main.placesManager.lookupPlaceById(id);
placeInfo.launch(); placeInfo.launch(params);
}, },
_compareResultMeta: function (idA, idB) { _compareResultMeta: function (idA, idB) {

View File

@ -631,15 +631,22 @@ PopupMenuBase.prototype = {
}, },
addMenuItem: function(menuItem, position) { addMenuItem: function(menuItem, position) {
if (position == undefined) let before_item = null;
if (position == undefined) {
this.box.add(menuItem.actor); this.box.add(menuItem.actor);
else } else {
this.box.insert_actor(menuItem.actor, position); let items = this.getMenuItems();
if (position < items.length) {
before_item = items[position].actor;
this.box.insert_before(menuItem.actor, before_item);
} else
this.box.add(menuItem.actor);
}
if (menuItem instanceof PopupSubMenuMenuItem) { if (menuItem instanceof PopupSubMenuMenuItem) {
if (position == undefined) if (before_item == null)
this.box.add(menuItem.menu.actor); this.box.add(menuItem.menu.actor);
else else
this.box.insert_actor(menuItem.menu.actor, position + 1); this.box.insert_before(menuItem.menu.actor, before_item);
menuItem._subMenuActivateId = menuItem.menu.connect('activate', Lang.bind(this, function() { menuItem._subMenuActivateId = menuItem.menu.connect('activate', Lang.bind(this, function() {
this.emit('activate'); this.emit('activate');
this.close(true); this.close(true);
@ -1187,6 +1194,18 @@ PopupMenuManager.prototype = {
return -1; return -1;
}, },
_nextMenu: function(pos, direction) {
for (let i = 1; i < this._menus.length; i++) {
let candidate = mod(pos + i * direction, this._menus.length);
let menu = this._menus[candidate].menu;
if (!menu.sourceActor || menu.sourceActor.visible)
return menu;
}
// no menu is found? this should not happen
// anyway stay on current menu
return this._menus[pos];
},
_onEventCapture: function(actor, event) { _onEventCapture: function(actor, event) {
if (!this.grabbed) if (!this.grabbed)
return false; return false;
@ -1225,7 +1244,7 @@ PopupMenuManager.prototype = {
if (symbol == Clutter.Left || symbol == Clutter.Right) { if (symbol == Clutter.Left || symbol == Clutter.Right) {
let direction = symbol == Clutter.Right ? 1 : -1; let direction = symbol == Clutter.Right ? 1 : -1;
let pos = this._findMenu(this._activeMenu); let pos = this._findMenu(this._activeMenu);
let next = this._menus[mod(pos + direction, this._menus.length)].menu; let next = this._nextMenu(pos, direction);
if (next != this._activeMenu) { if (next != this._activeMenu) {
this._changeMenu(next); this._changeMenu(next);
next.activateFirst(); next.activateFirst();

View File

@ -11,16 +11,18 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const Lightbox = imports.ui.lightbox; const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main; const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
const MAX_FILE_DELETED_BEFORE_INVALID = 10; const MAX_FILE_DELETED_BEFORE_INVALID = 10;
const HISTORY_KEY = 'command-history'; const HISTORY_KEY = 'command-history';
const HISTORY_LIMIT = 512; const HISTORY_LIMIT = 512;
const DIALOG_FADE_TIME = 0.1; const DIALOG_GROW_TIME = 0.1;
function CommandCompleter() { function CommandCompleter() {
this._init(); this._init();
@ -62,25 +64,6 @@ CommandCompleter.prototype = {
this._update(0); this._update(0);
}, },
_onGetEnumerateComplete : function(obj, res) {
this._enumerator = obj.enumerate_children_finish(res);
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
},
_onNextFileComplete : function(obj, res) {
let files = obj.next_files_finish(res);
for (let i = 0; i < files.length; i++) {
this._childs[this._i].push(files[i].get_name());
}
if (files.length) {
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
} else {
this._enumerator.close(null);
this._enumerator = null;
this._update(this._i + 1);
}
},
update : function() { update : function() {
if (this._valid) if (this._valid)
return; return;
@ -100,7 +83,12 @@ CommandCompleter.prototype = {
} }
let file = Gio.file_new_for_path(this._paths[i]); let file = Gio.file_new_for_path(this._paths[i]);
this._childs[this._i] = []; this._childs[this._i] = [];
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onGetEnumerateComplete)); FileUtils.listDirAsync(file, Lang.bind(this, function (files) {
for (let i = 0; i < files.length; i++) {
this._childs[this._i].push(files[i].get_name());
}
this._update(this._i + 1);
}));
}, },
_onChanged : function(m, f, of, type) { _onChanged : function(m, f, of, type) {
@ -175,8 +163,9 @@ function RunDialog() {
} }
RunDialog.prototype = { RunDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init : function() { _init : function() {
this._isOpen = false; ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
global.settings.connect('changed::development-tools', Lang.bind(this, function () { global.settings.connect('changed::development-tools', Lang.bind(this, function () {
this._enableInternalCommands = global.settings.get_boolean('development-tools'); this._enableInternalCommands = global.settings.get_boolean('development-tools');
@ -207,52 +196,45 @@ RunDialog.prototype = {
'debugexit': Lang.bind(this, function() { 'debugexit': Lang.bind(this, function() {
Meta.exit(Meta.ExitCode.ERROR); Meta.exit(Meta.ExitCode.ERROR);
}),
// rt is short for "reload theme"
'rt': Lang.bind(this, function() {
Main.loadTheme();
}) })
}; };
// All actors are inside _group. We create it initially
// hidden then show it in show()
this._group = new Clutter.Group({ visible: false,
x: 0, y: 0 });
Main.uiGroup.add_actor(this._group);
this._lightbox = new Lightbox.Lightbox(this._group,
{ inhibitEvents: true });
this._box = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._group.add_actor(this._box);
this._lightbox.highlight(this._box);
let dialogBox = new St.BoxLayout({ style_class: 'run-dialog', vertical: true });
this._box.set_child(dialogBox);
let label = new St.Label({ style_class: 'run-dialog-label', let label = new St.Label({ style_class: 'run-dialog-label',
text: _("Please enter a command:") }); text: _("Please enter a command:") });
dialogBox.add(label, { expand: true, y_fill: false }); this.contentLayout.add(label, { y_align: St.Align.START });
let entry = new St.Entry({ style_class: 'run-dialog-entry' }); let entry = new St.Entry({ style_class: 'run-dialog-entry' });
this._entryText = entry.clutter_text; this._entryText = entry.clutter_text;
dialogBox.add(entry, { expand: true }); this.contentLayout.add(entry, { y_align: St.Align.START });
this.connect('opened',
Lang.bind(this, function() {
this._entryText.grab_key_focus();
}));
this._errorBox = new St.BoxLayout(); this._errorBox = new St.BoxLayout({ style_class: 'run-dialog-error-box' });
dialogBox.add(this._errorBox, { expand: true }); this.contentLayout.add(this._errorBox, { expand: true });
let errorIcon = new St.Button({ style_class: 'run-dialog-error-icon' }); let errorIcon = new St.Icon({ icon_name: 'dialog-error', icon_size: 24, style_class: 'run-dialog-error-icon' });
this._errorBox.add(errorIcon); this._errorBox.add(errorIcon, { y_align: St.Align.MIDDLE });
this._commandError = false; this._commandError = false;
this._errorMessage = new St.Label({ style_class: 'run-dialog-error-label' }); this._errorMessage = new St.Label({ style_class: 'run-dialog-error-label' });
this._errorMessage.clutter_text.line_wrap = true; this._errorMessage.clutter_text.line_wrap = true;
this._errorBox.add(this._errorMessage, { expand: true }); this._errorBox.add(this._errorMessage, { expand: true,
y_align: St.Align.MIDDLE,
y_fill: false });
this._errorBox.hide(); this._errorBox.hide();
@ -275,10 +257,10 @@ RunDialog.prototype = {
else else
this._run(o.get_text(), false); this._run(o.get_text(), false);
if (!this._commandError) if (!this._commandError)
this.close(); this.close(global.get_current_time());
} }
if (symbol == Clutter.Escape) { if (symbol == Clutter.Escape) {
this.close(); this.close(global.get_current_time());
return true; return true;
} }
if (symbol == Clutter.slash) { if (symbol == Clutter.slash) {
@ -349,9 +331,7 @@ RunDialog.prototype = {
try { try {
if (inTerminal) if (inTerminal)
command = 'gnome-terminal -x ' + input; command = 'gnome-terminal -x ' + input;
let [ok, len, args] = GLib.shell_parse_argv(command); Util.trySpawnCommandLine(command);
let p = new Shell.Process({ 'args' : args });
p.run();
} catch (e) { } catch (e) {
// Mmmh, that failed - see if @input matches an existing file // Mmmh, that failed - see if @input matches an existing file
let path = null; let path = null;
@ -369,16 +349,24 @@ RunDialog.prototype = {
global.create_app_launch_context()); global.create_app_launch_context());
} else { } else {
this._commandError = true; this._commandError = true;
// The exception contains an error string like:
// Error invoking Shell.run: Failed to execute child
// process "foo" (No such file or directory)
// We are only interested in the actual error, so parse
//that out.
let m = /.+\((.+)\)/.exec(e);
let errorStr = _("Execution of '%s' failed:").format(command) + '\n' + m[1];
this._errorMessage.set_text(errorStr);
this._errorBox.show(); this._errorMessage.set_text(e.message);
if (!this._errorBox.visible) {
let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
let parentActor = this._errorBox.get_parent();
Tweener.addTween(parentActor,
{ height: parentActor.height + errorBoxNaturalHeight,
time: DIALOG_GROW_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
parentActor.set_height(-1);
this._errorBox.show();
})
});
}
} }
} }
} }
@ -400,53 +388,14 @@ RunDialog.prototype = {
this._entryText.set_text(''); this._entryText.set_text('');
}, },
open : function() { open: function() {
if (this._isOpen) // Already shown
return;
if (!Main.pushModal(this._group))
return;
// Position the dialog on the current monitor
let monitor = global.get_focus_monitor();
this._historyIndex = this._history.length; this._historyIndex = this._history.length;
this._errorBox.hide();
this._box.set_position(monitor.x, monitor.y); this._entryText.set_text('');
this._box.set_size(monitor.width, monitor.height);
this._isOpen = true;
this._lightbox.show();
this._group.opacity = 0;
this._group.show();
Tweener.addTween(this._group,
{ opacity: 255,
time: DIALOG_FADE_TIME,
transition: 'easeOutQuad'
});
global.stage.set_key_focus(this._entryText);
},
close : function() {
if (!this._isOpen)
return;
this._isOpen = false;
this._commandError = false; this._commandError = false;
Main.popModal(this._group); ModalDialog.ModalDialog.prototype.open.call(this);
},
Tweener.addTween(this._group,
{ opacity: 0,
time: DIALOG_FADE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._errorBox.hide();
this._group.hide();
this._entryText.set_text('');
})
});
}
}; };
Signals.addSignalMethods(RunDialog.prototype); Signals.addSignalMethods(RunDialog.prototype);

View File

@ -1,6 +1,19 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Signals = imports.signals; const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const DISABLED_OPEN_SEARCH_PROVIDERS_KEY = 'disabled-open-search-providers';
const RESULT_ICON_SIZE = 48; const RESULT_ICON_SIZE = 48;
@ -211,6 +224,107 @@ SearchProvider.prototype = {
}; };
Signals.addSignalMethods(SearchProvider.prototype); Signals.addSignalMethods(SearchProvider.prototype);
function OpenSearchSystem() {
this._init();
}
OpenSearchSystem.prototype = {
_init: function() {
this._providers = [];
global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
this._refresh();
},
getProviders: function() {
let res = [];
for (let i = 0; i < this._providers.length; i++)
res.push({ id: i, name: this._providers[i].name });
return res;
},
setSearchTerms: function(terms) {
this._terms = terms;
},
_checkSupportedProviderLanguage: function(provider) {
if (provider.url.search(/{language}/) == -1)
return true;
let langs = GLib.get_language_names();
langs.push('en');
let lang = null;
for (let i = 0; i < langs.length; i++) {
for (let k = 0; k < provider.langs.length; k++) {
if (langs[i] == provider.langs[k])
lang = langs[i];
}
if (lang)
break;
}
provider.lang = lang;
return lang != null;
},
activateResult: function(id, params) {
let searchTerms = this._terms.join(' ');
let url = this._providers[id].url.replace('{searchTerms}', encodeURIComponent(searchTerms));
if (url.match('{language}'))
url = url.replace('{language}', this._providers[id].lang);
try {
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context());
} catch (e) {
// TODO: remove this after glib will be removed from moduleset
// In the default jhbuild, gio is in our prefix but gvfs is not
Util.spawn(['gvfs-open', url])
}
Main.overview.hide();
},
_addProvider: function(fileName) {
let file = Gio.file_new_for_path(global.datadir + '/search_providers/' + fileName);
let source = '';
file.load_contents_async(null, Lang.bind(this, function (obj, res) {
let [success, source] = file.load_contents_finish(res);
if (source) {
let [success, name, url, langs, icon_uri] = global.parse_search_provider(source);
let provider ={ name: name,
url: url,
id: this._providers.length,
icon_uri: icon_uri,
langs: langs };
if (this._checkSupportedProviderLanguage(provider)) {
this._providers.push(provider);
this.emit('changed');
}
}
}));
},
_refresh: function() {
this._providers = [];
let names = global.settings.get_strv(DISABLED_OPEN_SEARCH_PROVIDERS_KEY);
let file = Gio.file_new_for_path(global.datadir + '/search_providers');
FileUtils.listDirAsync(file, Lang.bind(this, function(files) {
for (let i = 0; i < files.length; i++) {
let enabled = true;
let name = files[i].get_name();
for (let k = 0; k < names.length; k++)
if (names[k] == name)
enabled = false;
if (enabled)
this._addProvider(name);
}
}));
}
}
Signals.addSignalMethods(OpenSearchSystem.prototype);
function SearchSystem() { function SearchSystem() {
this._init(); this._init();
} }

View File

@ -10,6 +10,7 @@ const St = imports.gi.St;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const IconGrid = imports.ui.iconGrid; const IconGrid = imports.ui.iconGrid;
const Main = imports.ui.main; const Main = imports.ui.main;
const Overview = imports.ui.overview;
const Search = imports.ui.search; const Search = imports.ui.search;
const MAX_SEARCH_RESULTS_ROWS = 2; const MAX_SEARCH_RESULTS_ROWS = 2;
@ -80,11 +81,11 @@ SearchResult.prototype = {
return new Clutter.Clone({ source: this.metaInfo['icon'] }); return new Clutter.Clone({ source: this.metaInfo['icon'] });
}, },
shellWorkspaceLaunch: function() { shellWorkspaceLaunch: function(params) {
if (this.provider.dragActivateResult) if (this.provider.dragActivateResult)
this.provider.dragActivateResult(this.metaInfo.id); this.provider.dragActivateResult(this.metaInfo.id, params);
else else
this.provider.activateResult(this.metaInfo.id); this.provider.activateResult(this.metaInfo.id, params);
} }
}; };
@ -149,28 +150,41 @@ GridSearchResults.prototype = {
}; };
function SearchResults(searchSystem) { function SearchResults(searchSystem, openSearchSystem) {
this._init(searchSystem); this._init(searchSystem, openSearchSystem);
} }
SearchResults.prototype = { SearchResults.prototype = {
_init: function(searchSystem) { _init: function(searchSystem, openSearchSystem) {
this._searchSystem = searchSystem; this._searchSystem = searchSystem;
this._openSearchSystem = openSearchSystem;
this.actor = new St.BoxLayout({ name: 'searchResults',
vertical: true });
this.actor = new St.Bin({ name: 'searchResults',
y_align: St.Align.START,
x_align: St.Align.START,
x_fill: true });
this._content = new St.BoxLayout({ name: 'searchResultsContent', this._content = new St.BoxLayout({ name: 'searchResultsContent',
vertical: true }); vertical: true });
let scrollView = new St.ScrollView({ x_fill: true, let scrollView = new St.ScrollView({ x_fill: true,
y_fill: false, y_fill: false,
vshadows: true }); vfade: true });
scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); scrollView.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
scrollView.add_actor(this._content); scrollView.add_actor(this._content);
this.actor.set_child(scrollView); this.actor.add(scrollView, { x_fill: true,
y_fill: false,
expand: true,
x_align: St.Align.START,
y_align: St.Align.START });
this.actor.connect('notify::mapped', Lang.bind(this,
function() {
if (!this.actor.mapped)
return;
let adjustment = scrollView.vscroll.adjustment;
let direction = Overview.SwipeScrollDirection.VERTICAL;
Main.overview.setScrollAdjustment(adjustment, direction);
}));
this._statusText = new St.Label({ style_class: 'search-statustext' }); this._statusText = new St.Label({ style_class: 'search-statustext' });
this._content.add(this._statusText); this._content.add(this._statusText);
@ -179,6 +193,51 @@ SearchResults.prototype = {
this._providerMeta = []; this._providerMeta = [];
for (let i = 0; i < this._providers.length; i++) for (let i = 0; i < this._providers.length; i++)
this.createProviderMeta(this._providers[i]); this.createProviderMeta(this._providers[i]);
this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
this.actor.add(this._searchProvidersBox);
this._openSearchProviders = [];
this._openSearchSystem.connect('changed', Lang.bind(this, this._updateOpenSearchProviderButtons));
this._updateOpenSearchProviderButtons();
},
_updateOpenSearchProviderButtons: function() {
this._selectedOpenSearchButton = -1;
for (let i = 0; i < this._openSearchProviders.length; i++)
this._openSearchProviders[i].actor.destroy();
this._openSearchProviders = this._openSearchSystem.getProviders();
for (let i = 0; i < this._openSearchProviders.length; i++)
this._createOpenSearchProviderButton(this._openSearchProviders[i]);
},
_updateOpenSearchButtonState: function() {
for (let i = 0; i < this._openSearchProviders.length; i++) {
if (i == this._selectedOpenSearchButton)
this._openSearchProviders[i].actor.add_style_pseudo_class('selected');
else
this._openSearchProviders[i].actor.remove_style_pseudo_class('selected');
}
},
_createOpenSearchProviderButton: function(provider) {
let clickable = new St.Clickable({ style_class: 'dash-search-button',
reactive: true,
x_fill: true,
y_align: St.Align.MIDDLE });
let bin = new St.Bin({ x_fill: false,
x_align:St.Align.MIDDLE });
clickable.connect('clicked', Lang.bind(this, function() {
this._openSearchSystem.activateResult(provider.id);
}));
let title = new St.Label({ text: provider.name,
style_class: 'dash-search-button-label' });
bin.set_child(title);
clickable.set_child(bin);
provider.actor = clickable;
this._searchProvidersBox.add(clickable);
}, },
createProviderMeta: function(provider) { createProviderMeta: function(provider) {
@ -227,6 +286,8 @@ SearchResults.prototype = {
this._searchSystem.reset(); this._searchSystem.reset();
this._statusText.hide(); this._statusText.hide();
this._clearDisplay(); this._clearDisplay();
this._selectedOpenSearchButton = -1;
this._updateOpenSearchButtonState();
}, },
startingSearch: function() { startingSearch: function() {
@ -247,12 +308,14 @@ SearchResults.prototype = {
if (results.length == 0) { if (results.length == 0) {
this._statusText.set_text(_("No matching results.")); this._statusText.set_text(_("No matching results."));
this._statusText.show(); this._statusText.show();
return true;
} else { } else {
this._selectedOpenSearchButton = -1;
this._updateOpenSearchButtonState();
this._statusText.hide(); this._statusText.hide();
} }
let terms = this._searchSystem.getTerms(); let terms = this._searchSystem.getTerms();
this._openSearchSystem.setSearchTerms(terms);
for (let i = 0; i < results.length; i++) { for (let i = 0; i < results.length; i++) {
let [provider, providerResults] = results[i]; let [provider, providerResults] = results[i];
@ -262,7 +325,8 @@ SearchResults.prototype = {
meta.count.set_text('' + providerResults.length); meta.count.set_text('' + providerResults.length);
} }
this.selectDown(false); if (this._selectedOpenSearchButton == -1)
this.selectDown(false);
return true; return true;
}, },
@ -284,16 +348,26 @@ SearchResults.prototype = {
}, },
selectUp: function(recursing) { selectUp: function(recursing) {
for (let i = this._selectedProvider; i >= 0; i--) { if (this._selectedOpenSearchButton == -1) {
let meta = this._providerMeta[i]; for (let i = this._selectedProvider; i >= 0; i--) {
if (!meta.actor.visible) let meta = this._providerMeta[i];
continue; if (!meta.actor.visible)
let success = this._modifyActorSelection(meta.resultDisplay, true); continue;
if (success) { let success = this._modifyActorSelection(meta.resultDisplay, true);
this._selectedProvider = i; if (success) {
return; this._selectedProvider = i;
return;
}
} }
} }
if (this._selectedOpenSearchButton == -1)
this._selectedOpenSearchButton = this._openSearchProviders.length;
this._selectedOpenSearchButton--;
this._updateOpenSearchButtonState();
if (this._selectedOpenSearchButton >= 0)
return;
if (this._providerMeta.length > 0 && !recursing) { if (this._providerMeta.length > 0 && !recursing) {
this._selectedProvider = this._providerMeta.length - 1; this._selectedProvider = this._providerMeta.length - 1;
this.selectUp(true); this.selectUp(true);
@ -302,18 +376,30 @@ SearchResults.prototype = {
selectDown: function(recursing) { selectDown: function(recursing) {
let current = this._selectedProvider; let current = this._selectedProvider;
if (current == -1) if (this._selectedOpenSearchButton == -1) {
current = 0; if (current == -1)
for (let i = current; i < this._providerMeta.length; i++) { current = 0;
let meta = this._providerMeta[i]; for (let i = current; i < this._providerMeta.length; i++) {
if (!meta.actor.visible) let meta = this._providerMeta[i];
continue; if (!meta.actor.visible)
let success = this._modifyActorSelection(meta.resultDisplay, false); continue;
if (success) { let success = this._modifyActorSelection(meta.resultDisplay, false);
this._selectedProvider = i; if (success) {
return; this._selectedProvider = i;
return;
}
} }
} }
this._selectedOpenSearchButton++;
if (this._selectedOpenSearchButton < this._openSearchProviders.length) {
this._updateOpenSearchButtonState();
return;
}
this._selectedOpenSearchButton = -1;
this._updateOpenSearchButtonState();
if (this._providerMeta.length > 0 && !recursing) { if (this._providerMeta.length > 0 && !recursing) {
this._selectedProvider = 0; this._selectedProvider = 0;
this.selectDown(true); this.selectDown(true);
@ -321,6 +407,13 @@ SearchResults.prototype = {
}, },
activateSelected: function() { activateSelected: function() {
if (this._selectedOpenSearchButton != -1) {
let provider = this._openSearchProviders[this._selectedOpenSearchButton];
this._openSearchSystem.activateResult(provider.id);
Main.overview.hide();
return;
}
let current = this._selectedProvider; let current = this._selectedProvider;
if (current < 0) if (current < 0)
return; return;

View File

@ -12,6 +12,7 @@ const St = imports.gi.St;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
@ -108,8 +109,7 @@ ATIndicator.prototype = {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Universal Access Settings"), function() { this.menu.addAction(_("Universal Access Settings"), function() {
let p = new Shell.Process({ args: ['gnome-control-center','universal-access'] }); Util.spawnDesktop('gnome-universal-access-panel');
p.run();
}); });
}, },

View File

@ -65,16 +65,17 @@ Indicator.prototype = {
this.menu.addMenuItem(this._discoverable); this.menu.addMenuItem(this._discoverable);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this._fullMenuItems = [new PopupMenu.PopupMenuItem(_("Send Files to Device...")), this._fullMenuItems = [new PopupMenu.PopupSeparatorMenuItem(),
new PopupMenu.PopupSeparatorMenuItem(), new PopupMenu.PopupMenuItem(_("Send Files to Device...")),
new PopupMenu.PopupSeparatorMenuItem(), new PopupMenu.PopupMenuItem(_("Setup a New Device...")),
new PopupMenu.PopupMenuItem(_("Setup a New Device..."))]; new PopupMenu.PopupSeparatorMenuItem()];
this._deviceSep = this._fullMenuItems[1]; // hidden if no device exists this._hasDevices = false;
this._deviceSep = this._fullMenuItems[0]; // hidden if no device exists
this._fullMenuItems[0].connect('activate', function() { this._fullMenuItems[1].connect('activate', function() {
GLib.spawn_command_line_async('bluetooth-sendto'); GLib.spawn_command_line_async('bluetooth-sendto');
}); });
this._fullMenuItems[3].connect('activate', function() { this._fullMenuItems[2].connect('activate', function() {
GLib.spawn_command_line_async('bluetooth-wizard'); GLib.spawn_command_line_async('bluetooth-wizard');
}); });
@ -83,7 +84,7 @@ Indicator.prototype = {
this.menu.addMenuItem(item); this.menu.addMenuItem(item);
} }
this._deviceItemPosition = 5; this._deviceItemPosition = 3;
this._deviceItems = []; this._deviceItems = [];
this._applet.connect('devices-changed', Lang.bind(this, this._updateDevices)); this._applet.connect('devices-changed', Lang.bind(this, this._updateDevices));
this._updateDevices(); this._updateDevices();
@ -104,12 +105,18 @@ Indicator.prototype = {
_updateKillswitch: function() { _updateKillswitch: function() {
let current_state = this._applet.killswitch_state; let current_state = this._applet.killswitch_state;
let on = current_state == GnomeBluetoothApplet.KillswitchState.UNBLOCKED; let on = current_state == GnomeBluetoothApplet.KillswitchState.UNBLOCKED;
let has_adapter = current_state != GnomeBluetoothApplet.KillswitchState.NO_ADAPTER;
let can_toggle = current_state != GnomeBluetoothApplet.KillswitchState.NO_ADAPTER && let can_toggle = current_state != GnomeBluetoothApplet.KillswitchState.NO_ADAPTER &&
current_state != GnomeBluetoothApplet.KillswitchState.HARD_BLOCKED; current_state != GnomeBluetoothApplet.KillswitchState.HARD_BLOCKED;
this._killswitch.setToggleState(on); this._killswitch.setToggleState(on);
this._killswitch.actor.reactive = can_toggle; this._killswitch.actor.reactive = can_toggle;
if (has_adapter)
this.actor.show();
else
this.actor.hide();
if (on) { if (on) {
this._discoverable.actor.show(); this._discoverable.actor.show();
this.setIcon('bluetooth-active'); this.setIcon('bluetooth-active');
@ -119,22 +126,56 @@ Indicator.prototype = {
} }
}, },
_updateDevices: function() { _deviceCompare: function(d1, d2) {
this._destroyAll(this._deviceItems); return d1.device_path == d2.device_path &&
this._deviceItems = []; d1.bdaddr == d2.bdaddr &&
d1.can_connect == d2.can_connect &&
d1.capabilities == d2.capabilities;
},
_updateDevices: function() {
let devices = this._applet.get_devices(); let devices = this._applet.get_devices();
let anydevice = false;
for (let i = 0; i < this._deviceItems.length; i++) {
let item = this._deviceItems[i];
let destroy = true;
for (let j = 0; j < devices.length; j++) {
// we need to deep compare because BluetoothSimpleDevice is a boxed type
// (but we take advantage of that, because _skip will disappear the next
// time get_devices() is called)
if (this._deviceCompare(item._device, devices[i])) {
item.label.text = devices[i].alias;
devices[i]._skip = true;
destroy = false;
}
}
if (destroy) {
item.destroy();
item._destroyed = true;
}
}
let newlist = [ ];
for (let i = 0; i < this._deviceItems.length; i++) {
let item = this._deviceItems[i];
if (!item._destroyed)
newlist.push(item);
}
this._deviceItems = newlist;
this._hasDevices = newlist.length > 0;
for (let i = 0; i < devices.length; i++) { for (let i = 0; i < devices.length; i++) {
let d = devices[i]; let d = devices[i];
if (d._skip)
continue;
let item = this._createDeviceItem(d); let item = this._createDeviceItem(d);
if (item) { if (item) {
this.menu.addMenuItem(item, this._deviceItemPosition + this._deviceItems.length); this.menu.addMenuItem(item, this._deviceItemPosition + this._deviceItems.length);
this._deviceItems.push(item); this._deviceItems.push(item);
anydevice = true; this._hasDevices = true;
} }
} }
if (anydevice) if (this._hasDevices)
this._deviceSep.actor.show(); this._deviceSep.actor.show();
else else
this._deviceSep.actor.hide(); this._deviceSep.actor.hide();
@ -233,7 +274,10 @@ Indicator.prototype = {
_updateFullMenu: function() { _updateFullMenu: function() {
if (this._applet.show_full_menu) { if (this._applet.show_full_menu) {
this._showAll(this._fullMenuItems); this._showAll(this._fullMenuItems);
this._showAll(this._deviceItems); if (this._hasDevices)
this._showAll(this._deviceItems);
else
this._deviceSep.actor.hide();
} else { } else {
this._hideAll(this._fullMenuItems); this._hideAll(this._fullMenuItems);
this._hideAll(this._deviceItems); this._hideAll(this._deviceItems);

206
js/ui/status/keyboard.js Normal file
View File

@ -0,0 +1,206 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
const Gkbd = imports.gi.Gkbd;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const INDICATOR_SCHEMA = 'org.gnome.settings-daemon.plugins.keyboard';
function LayoutMenuItem() {
this._init.apply(this, arguments);
}
LayoutMenuItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
_init: function(config, id, indicator, long_name) {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this._config = config;
this._id = id;
this.label = new St.Label({ text: long_name });
this.indicator = indicator;
this.addActor(this.label);
this.addActor(this.indicator);
},
activate: function(event) {
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
this._config.lock_group(this._id);
}
};
function XKBIndicator() {
this._init.call(this);
}
XKBIndicator.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this._container = new Shell.GenericContainer();
this._container.connect('get-preferred-width', Lang.bind(this, this._get_preferred_width));
this._container.connect('get-preferred-height', Lang.bind(this, this._get_preferred_height));
this._container.connect('allocate', Lang.bind(this, this._allocate));
this.actor.set_child(this._container);
this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._container.add_actor(this._iconActor);
this._labelActors = [ ];
this._layoutItems = [ ];
this._indicatorSettings = new Gio.Settings({ schema: INDICATOR_SCHEMA });
this._indicatorSettings.connect('changed::disable-indicator', Lang.bind(this, this._sync_config));
this._disableIndicator = false;
this._showFlags = false;
this._config = Gkbd.Configuration.get();
this._config.connect('changed', Lang.bind(this, this._sync_config));
this._config.connect('group-changed', Lang.bind(this, this._sync_group));
this._config.start_listen();
this._sync_config();
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Localization Settings"), function() {
GLib.spawn_command_line_async('gnome-control-center region');
});
},
_sync_config: function() {
this._disableIndicator = this._indicatorSettings.get_boolean('disable-indicator');
this._showFlags = this._config.if_flags_shown();
if (this._showFlags) {
this._container.set_skip_paint(this._iconActor, false);
} else {
this._container.set_skip_paint(this._iconActor, true);
}
let groups = this._config.get_group_names();
if (groups.length > 1 && !this._disableIndicator) {
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
for (let i = 0; i < this._layoutItems.length; i++)
this._layoutItems[i].destroy();
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].destroy();
let short_names = this._config.get_short_group_names();
this._selectedLayout = null;
this._layoutItems = [ ];
this._selectedLabel = null;
this._labelActors = [ ];
for (let i = 0; i < groups.length; i++) {
let icon_name = this._config.get_group_name(i);
let actor;
if (this._showFlags)
actor = new St.Icon({ icon_name: icon_name, icon_type: St.IconType.SYMBOLIC, style_class: 'popup-menu-icon' });
else
actor = new St.Label({ text: short_names[i] });
let item = new LayoutMenuItem(this._config, i, actor, groups[i]);
item._short_group_name = short_names[i];
item._icon_name = icon_name;
this._layoutItems.push(item);
this.menu.addMenuItem(item, i);
let shortLabel = new St.Label({ text: short_names[i] });
this._labelActors.push(shortLabel);
this._container.add_actor(shortLabel);
this._container.set_skip_paint(shortLabel, true);
}
this._sync_group();
},
_sync_group: function() {
let selected = this._config.get_current_group();
if (this._selectedLayout) {
this._selectedLayout.setShowDot(false);
this._selectedLayout = null;
}
if (this._selectedLabel) {
this._container.set_skip_paint(this._selectedLabel, true);
this._selectedLabel = null;
}
let item = this._layoutItems[selected];
item.setShowDot(true);
this._iconActor.icon_name = item._icon_name;
this._selectedLabel = this._labelActors[selected];
this._container.set_skip_paint(this._selectedLabel, this._showFlags);
this._selectedLayout = item;
},
_get_preferred_width: function(container, for_height, alloc) {
/* Here, and in _get_preferred_height, we need to query for the
height of all children, but we ignore the results for those
we don't actually display. */
let max_min_width = 0, max_natural_width = 0;
if (this._showFlags)
[max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
for (let i = 0; i < this._labelActors.length; i++) {
let [min_width, natural_width] = this._labelActors[i].get_preferred_width(for_height);
if (!this._showFlags) {
max_min_width = Math.max(max_min_width, min_width);
max_natural_width = Math.max(max_natural_width, natural_width);
}
}
alloc.min_size = max_min_width;
alloc.natural_size = max_natural_width;
},
_get_preferred_height: function(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0;
if (this._showFlags)
[max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
for (let i = 0; i < this._labelActors.length; i++) {
let [min_height, natural_height] = this._labelActors[i].get_preferred_height(for_width);
if (!this._showFlags) {
max_min_height = Math.max(max_min_height, min_height);
max_natural_height = Math.max(max_natural_height, natural_height);
}
}
alloc.min_size = max_min_height;
alloc.natural_size = max_natural_height;
},
_allocate: function(container, box, flags) {
// translate box to (0, 0)
box.x2 -= box.x1;
box.x1 = 0;
box.y2 -= box.y1;
box.y1 = 0;
this._iconActor.allocate_align_fill(box, 0.5, 0, false, false, flags);
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
}
};

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const DBus = imports.dbus; const DBus = imports.dbus;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
@ -10,6 +9,7 @@ const St = imports.gi.St;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
@ -83,7 +83,7 @@ Indicator.prototype = {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Power Settings"),function() { this.menu.addAction(_("Power Settings"),function() {
GLib.spawn_command_line_async('gnome-control-center power'); Util.spawnDesktop('gnome-power-panel');
}); });
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged)); this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
@ -134,8 +134,7 @@ Indicator.prototype = {
this._batteryItem.actor.reactive = true; this._batteryItem.actor.reactive = true;
this._batteryItem.actor.can_focus = true; this._batteryItem.actor.can_focus = true;
this._batteryItem.connect('activate', function(item) { this._batteryItem.connect('activate', function(item) {
let p = new Shell.Process({ args: ['gnome-power-statistics', '--device', device_id] }); Util.spawn(['gnome-power-statistics', '--device', device_id]);
p.run();
}); });
} else { } else {
// virtual device // virtual device
@ -164,8 +163,7 @@ Indicator.prototype = {
let item = new DeviceItem (devices[i]); let item = new DeviceItem (devices[i]);
item.connect('activate', function() { item.connect('activate', function() {
let p = new Shell.Process({ args: ['gnome-power-statistics', '--device', device_id] }); Util.spawn(['gnome-power-statistics', '--device', device_id]);
p.run();
}); });
this._deviceItems.push(item); this._deviceItems.push(item);
this.menu.addMenuItem(item, this._otherDevicePosition + position); this.menu.addMenuItem(item, this._otherDevicePosition + position);
@ -197,8 +195,8 @@ Indicator.prototype = {
_checkError: function(error) { _checkError: function(error) {
if (!this._restarted && error && error.message.match(/org\.freedesktop\.DBus\.Error\.(UnknownMethod|InvalidArgs)/)) { if (!this._restarted && error && error.message.match(/org\.freedesktop\.DBus\.Error\.(UnknownMethod|InvalidArgs)/)) {
GLib.spawn_command_line_sync('pkill -f "^gnome-power-manager$"'); Util.killall('gnome-power-manager');
GLib.spawn_command_line_async('gnome-power-manager'); Util.spawn(['gnome-power-manager']);
this._restarted = true; this._restarted = true;
} }
} }

View File

@ -11,6 +11,7 @@ const St = imports.gi.St;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
@ -60,8 +61,7 @@ Indicator.prototype = {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Sound Settings"), function() { this.menu.addAction(_("Sound Settings"), function() {
let p = new Shell.Process({ args: ['gnome-control-center', 'sound'] }); Util.spawnDesktop('gnome-sound-panel');
p.run();
}); });
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent)); this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));

View File

@ -6,6 +6,7 @@ const Signals = imports.signals;
const MessageTray = imports.ui.messageTray; const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon; const NotificationDaemon = imports.ui.notificationDaemon;
const Util = imports.misc.util;
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = { const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'bluetooth-applet': 'bluetooth', 'bluetooth-applet': 'bluetooth',
@ -15,7 +16,10 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'nm-applet': 'network', 'nm-applet': 'network',
'gnome-power-manager': 'battery', 'gnome-power-manager': 'battery',
'keyboard': 'keyboard', 'keyboard': 'keyboard',
'gnome-settings-daemon': 'display' 'a11y-keyboard': 'a11y',
'kbd-scrolllock': 'keyboard',
'kbd-numlock': 'keyboard',
'kbd-capslock': 'keyboard'
}; };
function StatusIconDispatcher() { function StatusIconDispatcher() {
@ -33,8 +37,7 @@ StatusIconDispatcher.prototype = {
// app-indicators, so that applications fall back to normal // app-indicators, so that applications fall back to normal
// status icons // status icons
// http://bugzilla.gnome.org/show_bug.cgi=id=621382 // http://bugzilla.gnome.org/show_bug.cgi=id=621382
let p = new Shell.Process({ args: ['pkill', '-f', '^([^ ]*/)?indicator-application-service$']}); Util.killall('indicator-application-service');
p.run();
}, },
_onTrayIconAdded: function(o, icon) { _onTrayIconAdded: function(o, icon) {

View File

@ -12,6 +12,7 @@ const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main; const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Util = imports.misc.util;
// Adapted from gdm/gui/user-switch-applet/applet.c // Adapted from gdm/gui/user-switch-applet/applet.c
// //
@ -31,7 +32,7 @@ StatusMenuButton.prototype = {
this.actor.set_child(box); this.actor.set_child(box);
this._gdm = Gdm.UserManager.ref_default(); this._gdm = Gdm.UserManager.ref_default();
this._gdm.queue_load() this._gdm.queue_load();
this._user = this._gdm.get_user(GLib.get_user_name()); this._user = this._gdm.get_user(GLib.get_user_name());
this._presence = new GnomeSession.Presence(); this._presence = new GnomeSession.Presence();
@ -153,17 +154,17 @@ StatusMenuButton.prototype = {
_onMyAccountActivate: function() { _onMyAccountActivate: function() {
Main.overview.hide(); Main.overview.hide();
this._spawn(['gnome-control-center', 'user-accounts']); Util.spawnDesktop('gnome-user-accounts-panel');
}, },
_onPreferencesActivate: function() { _onPreferencesActivate: function() {
Main.overview.hide(); Main.overview.hide();
this._spawn(['gnome-control-center', '-o']); Util.spawnDesktop('gnome-control-center');
}, },
_onLockScreenActivate: function() { _onLockScreenActivate: function() {
Main.overview.hide(); Main.overview.hide();
this._spawn(['gnome-screensaver-command', '--lock']); Util.spawn(['gnome-screensaver-command', '--lock']);
}, },
_onLoginScreenActivate: function() { _onLoginScreenActivate: function() {
@ -174,19 +175,11 @@ StatusMenuButton.prototype = {
_onQuitSessionActivate: function() { _onQuitSessionActivate: function() {
Main.overview.hide(); Main.overview.hide();
this._spawn(['gnome-session-save', '--logout-dialog']); Util.spawn(['gnome-session-save', '--logout-dialog']);
}, },
_onShutDownActivate: function() { _onShutDownActivate: function() {
Main.overview.hide(); Main.overview.hide();
this._spawn(['gnome-session-save', '--shutdown-dialog']); Util.spawn(['gnome-session-save', '--shutdown-dialog']);
},
_spawn: function(args) {
// FIXME: once Shell.Process gets support for signalling
// errors we should pop up an error dialog or something here
// on failure
let p = new Shell.Process({'args' : args});
p.run();
} }
}; };

View File

@ -455,6 +455,8 @@ Source.prototype = {
_init: function(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) { _init: function(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
MessageTray.Source.prototype._init.call(this, targetId); MessageTray.Source.prototype._init.call(this, targetId);
this.isChat = true;
this._accountPath = accountPath; this._accountPath = accountPath;
let connName = Telepathy.pathToName(connPath); let connName = Telepathy.pathToName(connPath);
@ -476,6 +478,7 @@ Source.prototype = {
} }
this._notification = new Notification(this); this._notification = new Notification(this);
this._notification.setUrgency(MessageTray.Urgency.HIGH);
// Since we only create sources when receiving a message, this // Since we only create sources when receiving a message, this
// is a plausible default // is a plausible default

View File

@ -247,9 +247,10 @@ SearchTab.prototype = {
this._focusBase = focusBase; this._focusBase = focusBase;
this._searchSystem = new Search.SearchSystem(); this._searchSystem = new Search.SearchSystem();
this._openSearchSystem = new Search.OpenSearchSystem();
this._searchEntry = new SearchEntry(focusBase); this._searchEntry = new SearchEntry(focusBase);
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem); this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
BaseTab.prototype._init.call(this, BaseTab.prototype._init.call(this,
this._searchEntry.actor, this._searchEntry.actor,
this._searchResults.actor); this._searchResults.actor);

View File

@ -497,6 +497,8 @@ WindowManager.prototype = {
for (let i = 0; i < switchData.windows.length; i++) { for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i]; let w = switchData.windows[i];
if (w.window.is_destroyed()) // Window gone
continue;
if (w.window.get_parent() == switchData.outGroup) { if (w.window.get_parent() == switchData.outGroup) {
w.window.reparent(w.parent); w.window.reparent(w.parent);
w.window.hide(); w.window.hide();
@ -523,23 +525,20 @@ WindowManager.prototype = {
}, },
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) { _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) if (global.screen.n_workspaces == 1)
return; return;
if (this._workspaceSwitcherPopup == null) if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup(); this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
if (binding == 'switch_to_workspace_left') { if (binding == 'switch_to_workspace_left')
this.actionMoveWorkspaceLeft(); this.actionMoveWorkspaceLeft();
} else if (binding == 'switch_to_workspace_right')
if (binding == 'switch_to_workspace_right') {
this.actionMoveWorkspaceRight(); this.actionMoveWorkspaceRight();
} else if (binding == 'switch_to_workspace_up')
this.actionMoveWorkspaceUp();
else if (binding == 'switch_to_workspace_down')
this.actionMoveWorkspaceDown();
}, },
actionMoveWorkspaceLeft: function() { actionMoveWorkspaceLeft: function() {
@ -570,6 +569,32 @@ WindowManager.prototype = {
if (indexToActivate != activeWorkspaceIndex) if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time()); global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, indexToActivate);
},
actionMoveWorkspaceUp: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let indexToActivate = activeWorkspaceIndex;
if (activeWorkspaceIndex > 0)
indexToActivate--;
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, indexToActivate);
},
actionMoveWorkspaceDown: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let indexToActivate = activeWorkspaceIndex;
if (activeWorkspaceIndex < global.screen.n_workspaces - 1)
indexToActivate++;
if (indexToActivate != activeWorkspaceIndex)
global.screen.get_workspace_by_index(indexToActivate).activate(global.get_current_time());
if (!Main.overview.visible) if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, indexToActivate); this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, indexToActivate);
} }

View File

@ -104,6 +104,10 @@ WindowClone.prototype = {
this._stackAbove = null; this._stackAbove = null;
this._sizeChangedId = this.realWindow.connect('size-changed', Lang.bind(this, function() {
this.emit('size-changed');
}));
this.actor.connect('button-release-event', this.actor.connect('button-release-event',
Lang.bind(this, this._onButtonRelease)); Lang.bind(this, this._onButtonRelease));
@ -157,6 +161,9 @@ WindowClone.prototype = {
}, },
_onDestroy: function() { _onDestroy: function() {
this.realWindow.disconnect(this._sizeChangedId);
this._sizeChangedId = 0;
this.metaWindow._delegate = null; this.metaWindow._delegate = null;
this.actor._delegate = null; this.actor._delegate = null;
if (this._zoomLightbox) if (this._zoomLightbox)
@ -517,20 +524,10 @@ Workspace.prototype = {
// Without this the drop area will be overlapped. // Without this the drop area will be overlapped.
this._windowOverlaysGroup.set_size(0, 0); this._windowOverlaysGroup.set_size(0, 0);
this.actor = new Clutter.Group({ reactive: true }); this.actor = new Clutter.Group();
this.actor._delegate = this; this.actor._delegate = this;
this.actor.connect('destroy', Lang.bind(this, this._onDestroy)); this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('button-release-event', Lang.bind(this,
function(actor, event) {
// Only switch to the workspace when there's no application
// windows open. The problem is that it's too easy to miss
// an app window and get the wrong one focused.
if (this._windows.length == 0) {
this.metaWorkspace.activate(event.get_time());
Main.overview.hide();
}
}));
// Items in _windowOverlaysGroup should not be scaled, so we don't // Items in _windowOverlaysGroup should not be scaled, so we don't
// add them to this.actor, but to its parent whenever it changes // add them to this.actor, but to its parent whenever it changes
@ -605,6 +602,10 @@ Workspace.prototype = {
return this._lookupIndex(metaWindow) >= 0; return this._lookupIndex(metaWindow) >= 0;
}, },
isEmpty: function() {
return this._windows.length == 0;
},
setShowOnlyWindows: function(showOnlyWindows, reposition) { setShowOnlyWindows: function(showOnlyWindows, reposition) {
this._showOnlyWindows = showOnlyWindows; this._showOnlyWindows = showOnlyWindows;
this._resetCloneVisibility(); this._resetCloneVisibility();
@ -1331,6 +1332,10 @@ Workspace.prototype = {
Lang.bind(this, function() { Lang.bind(this, function() {
this._windowIsZooming = false; this._windowIsZooming = false;
})); }));
clone.connect('size-changed',
Lang.bind(this, function() {
this.positionWindows(0);
}));
this.actor.add_actor(clone.actor); this.actor.add_actor(clone.actor);
@ -1397,7 +1402,7 @@ Workspace.prototype = {
}, },
acceptDrop : function(source, actor, x, y, time) { acceptDrop : function(source, actor, x, y, time) {
if (source instanceof WindowClone) { if (source.realWindow) {
let win = source.realWindow; let win = source.realWindow;
if (this._isMyWindow(win)) if (this._isMyWindow(win))
return false; return false;
@ -1416,8 +1421,8 @@ Workspace.prototype = {
time); time);
return true; return true;
} else if (source.shellWorkspaceLaunch) { } else if (source.shellWorkspaceLaunch) {
this.metaWorkspace.activate(time); source.shellWorkspaceLaunch({ workspace: this.metaWorkspace,
source.shellWorkspaceLaunch(); timestamp: time });
return true; return true;
} }

310
js/ui/workspaceThumbnail.js Normal file
View File

@ -0,0 +1,310 @@
/* -*- 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 Signals = imports.signals;
const St = imports.gi.St;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Workspace = imports.ui.workspace;
// Fraction of original screen size for thumbnails
let THUMBNAIL_SCALE = 1/8.;
function WindowClone(realWindow) {
this._init(realWindow);
}
WindowClone.prototype = {
_init : function(realWindow) {
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
clip_to_allocation: true,
reactive: true });
this.actor._delegate = this;
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
this.metaWindow._delegate = this;
this._positionChangedId = this.realWindow.connect('position-changed',
Lang.bind(this, this._onPositionChanged));
this._onPositionChanged();
this.actor.connect('button-release-event',
Lang.bind(this, this._onButtonRelease));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._draggable = DND.makeDraggable(this.actor,
{ restoreOnSuccess: true,
dragActorMaxSize: Workspace.WINDOW_DND_SIZE,
dragActorOpacity: Workspace.DRAGGING_WINDOW_OPACITY });
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
this._draggable.connect('drag-end', Lang.bind(this, this._onDragEnd));
this.inDrag = false;
this._selected = false;
},
setStackAbove: function (actor) {
this._stackAbove = actor;
if (this._stackAbove == null)
this.actor.lower_bottom();
else
this.actor.raise(this._stackAbove);
},
destroy: function () {
this.actor.destroy();
},
_onPositionChanged: function() {
let rect = this.metaWindow.get_outer_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y);
},
_onDestroy: function() {
this.metaWindow._delegate = null;
this.actor._delegate = null;
if (this._positionChangedId != 0) {
this.realWindow.disconnect(this._positionChangedId);
this._positionChangedId = 0;
}
if (this.inDrag) {
this.emit('drag-end');
this.inDrag = false;
}
this.disconnectAll();
},
_onButtonRelease : function (actor, event) {
this._selected = true;
this.emit('selected', event.get_time());
},
_onDragBegin : function (draggable, time) {
this.inDrag = true;
this.emit('drag-begin');
},
_onDragEnd : function (draggable, time, snapback) {
this.inDrag = false;
// We may not have a parent if DnD completed successfully, in
// which case our clone will shortly be destroyed and replaced
// with a new one on the target workspace.
if (this.actor.get_parent() != null) {
if (this._stackAbove == null)
this.actor.lower_bottom();
else
this.actor.raise(this._stackAbove);
}
this.emit('drag-end');
}
};
Signals.addSignalMethods(WindowClone.prototype);
/**
* @metaWorkspace: a #Meta.Workspace
*/
function WorkspaceThumbnail(metaWorkspace) {
this._init(metaWorkspace);
}
WorkspaceThumbnail.prototype = {
_init : function(metaWorkspace) {
// When dragging a window, we use this slot for reserve space.
this.metaWorkspace = metaWorkspace;
this.actor = new St.Bin({ reactive: true,
style_class: 'workspace-thumbnail' });
this.actor._delegate = this;
this._group = new Clutter.Group();
this.actor.add_actor(this._group);
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this.actor.connect('button-press-event', Lang.bind(this,
function(actor, event) {
return true;
}));
this.actor.connect('button-release-event', Lang.bind(this,
function(actor, event) {
this.metaWorkspace.activate(event.get_time());
return true;
}));
this._background = new Clutter.Clone({ source: global.background_actor });
this._group.add_actor(this._background);
this._group.set_size(THUMBNAIL_SCALE * global.screen_width, THUMBNAIL_SCALE * global.screen_height);
this._group.set_scale(THUMBNAIL_SCALE, THUMBNAIL_SCALE);
let windows = global.get_window_actors().filter(this._isMyWindow, this);
// Create clones for windows that should be visible in the Overview
this._windows = [];
for (let i = 0; i < windows.length; i++) {
if (this._isOverviewWindow(windows[i])) {
this._addWindowClone(windows[i]);
}
}
// Track window changes
this._windowAddedId = this.metaWorkspace.connect('window-added',
Lang.bind(this, this._windowAdded));
this._windowRemovedId = this.metaWorkspace.connect('window-removed',
Lang.bind(this, this._windowRemoved));
},
_lookupIndex: function (metaWindow) {
for (let i = 0; i < this._windows.length; i++) {
if (this._windows[i].metaWindow == metaWindow) {
return i;
}
}
return -1;
},
syncStacking: function(stackIndices) {
this._windows.sort(function (a, b) { return stackIndices[a.metaWindow.get_stable_sequence()] - stackIndices[b.metaWindow.get_stable_sequence()]; });
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
let metaWindow = clone.metaWindow;
if (i == 0) {
clone.setStackAbove(this._background);
} else {
let previousClone = this._windows[i - 1];
clone.setStackAbove(previousClone.actor);
}
}
},
_windowRemoved : function(metaWorkspace, metaWin) {
let win = metaWin.get_compositor_private();
// find the position of the window in our list
let index = this._lookupIndex (metaWin);
if (index == -1)
return;
let clone = this._windows[index];
this._windows.splice(index, 1);
clone.destroy();
},
_windowAdded : function(metaWorkspace, metaWin) {
if (this.leavingOverview)
return;
let win = metaWin.get_compositor_private();
if (!win) {
// Newly-created windows are added to a workspace before
// the compositor finds out about them...
Mainloop.idle_add(Lang.bind(this,
function () {
if (this.actor && metaWin.get_compositor_private())
this._windowAdded(metaWorkspace, metaWin);
return false;
}));
return;
}
if (!this._isOverviewWindow(win))
return;
let clone = this._addWindowClone(win);
},
destroy : function() {
this.actor.destroy();
},
_onDestroy: function(actor) {
this.metaWorkspace.disconnect(this._windowAddedId);
this.metaWorkspace.disconnect(this._windowRemovedId);
this._windows = [];
this.actor = null;
},
// Tests if @win belongs to this workspaces
_isMyWindow : function (win) {
return win.get_workspace() == this.metaWorkspace.index() ||
(win.get_meta_window() && win.get_meta_window().is_on_all_workspaces());
},
// Tests if @win should be shown in the Overview
_isOverviewWindow : function (win) {
let tracker = Shell.WindowTracker.get_default();
return tracker.is_window_interesting(win.get_meta_window());
},
// Create a clone of a (non-desktop) window and add it to the window list
_addWindowClone : function(win) {
let clone = new WindowClone(win);
clone.connect('selected',
Lang.bind(this, this._onCloneSelected));
clone.connect('drag-begin',
Lang.bind(this, function(clone) {
Main.overview.beginWindowDrag();
}));
clone.connect('drag-end',
Lang.bind(this, function(clone) {
Main.overview.endWindowDrag();
}));
this._group.add_actor(clone.actor);
this._windows.push(clone);
return clone;
},
_onCloneSelected : function (clone, time) {
this.metaWorkspace.activate(time);
},
// Draggable target interface
handleDragOver : function(source, actor, x, y, time) {
if (source.realWindow)
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP;
return DND.DragMotionResult.CONTINUE;
},
acceptDrop : function(source, actor, x, y, time) {
if (source.realWindow) {
let win = source.realWindow;
if (this._isMyWindow(win))
return false;
let metaWindow = win.get_meta_window();
metaWindow.change_workspace_by_index(this.metaWorkspace.index(),
false, // don't create workspace
time);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace,
timestamp: time });
return true;
}
return false;
}
};
Signals.addSignalMethods(WorkspaceThumbnail.prototype);

File diff suppressed because it is too large Load Diff

127
js/ui/xdndHandler.js Normal file
View File

@ -0,0 +1,127 @@
/* -*- 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 Signals = imports.signals;
const Mainloop = imports.mainloop;
const DND = imports.ui.dnd;
function XdndHandler() {
this._init();
}
XdndHandler.prototype = {
_init: function() {
// Used to display a clone of the cursor window when the
// window group is hidden (like it happens in the overview)
this._cursorWindowClone = null;
// Used as a drag actor in case we don't have a cursor window clone
this._dummy = new Clutter.Rectangle({ width: 1, height: 1, opacity: 0 });
global.stage.add_actor(this._dummy);
this._dummy.hide();
// Mutter delays the creation of the output window as long
// as possible to avoid flicker. In case a plugin wants to
// access it directly it has to connect to the stage's show
// signal. (see comment in compositor.c:meta_compositor_manage_screen)
global.stage.connect('show', function () {
global.init_xdnd();
return false;
});
global.connect('xdnd-enter', Lang.bind(this, this._onEnter));
global.connect('xdnd-position-changed', Lang.bind(this, this._onPositionChanged));
global.connect('xdnd-leave', Lang.bind(this, this._onLeave));
this._windowGroupVisibilityHandlerId = 0;
},
// Called when the user cancels the drag (i.e release the button)
_onLeave: function() {
if (this._windowGroupVisibilityHandlerId != 0) {
Mainloop.source_remove(this._windowGroupVisibilityHandlerId);
this._windowGroupVisibilityHandlerId = 0;
}
this.emit('drag-end');
},
_onEnter: function() {
this._windowGroupVisibilityHandlerId =
global.window_group.connect('notify::visible',
Lang.bind(this, this._onWindowGroupVisibilityChanged));
this.emit('drag-begin', global.get_current_time());
},
_onWindowGroupVisibilityChanged: function() {
if (!global.window_group.visible) {
if (this._cursorWindowClone)
return;
let windows = global.get_window_actors();
let cursorWindow = windows[windows.length - 1];
// FIXME: more reliable way?
if (!cursorWindow.is_override_redirect())
return;
let constraint_position = new Clutter.BindConstraint({ coordinate : Clutter.BindCoordinate.POSITION,
source: cursorWindow});
this._cursorWindowClone = new Clutter.Clone({ source: cursorWindow });
global.overlay_group.add_actor(this._cursorWindowClone);
Shell.util_set_hidden_from_pick(this._cursorWindowClone, true);
// Make sure that the clone has the same position as the source
this._cursorWindowClone.add_constraint(constraint_position);
} else {
if (this._cursorWindowClone)
{
this._cursorWindowClone.destroy();
this._cursorWindowClone = null;
}
}
},
_onPositionChanged: function(obj, x, y) {
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
// Make sure that the cursor window is on top
if (this._cursorWindowClone)
this._cursorWindowClone.raise_top();
let dragEvent = {
x: x,
y: y,
dragActor: this._cursorWindowClone ? this._cursorWindowClone : this._dummy,
source: this,
targetActor: pickedActor
};
for (let i = 0; i < DND.dragMonitors.length; i++) {
let motionFunc = DND.dragMonitors[i].dragMotion;
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DND.DragMotionResult.CONTINUE)
return;
}
}
while (pickedActor) {
if (pickedActor._delegate && pickedActor._delegate.handleDragOver) {
let result = pickedActor._delegate.handleDragOver(this,
dragEvent.dragActor,
x,
y,
global.get_current_time());
if (result != DND.DragMotionResult.CONTINUE)
return;
}
pickedActor = pickedActor.get_parent();
}
}
}
Signals.addSignalMethods(XdndHandler.prototype);

View File

@ -1,13 +1,16 @@
data/gnome-shell.desktop.in.in data/gnome-shell.desktop.in.in
data/gnome-shell-clock-preferences.desktop.in.in
data/org.gnome.shell.gschema.xml.in data/org.gnome.shell.gschema.xml.in
data/org.gnome.accessibility.magnifier.gschema.xml.in data/org.gnome.accessibility.magnifier.gschema.xml.in
[type: gettext/glade]data/clock-preferences.ui js/misc/util.js
js/ui/appDisplay.js js/ui/appDisplay.js
js/ui/appFavorites.js js/ui/appFavorites.js
js/ui/calendar.js
js/ui/dash.js js/ui/dash.js
js/ui/dateMenu.js
js/ui/docDisplay.js js/ui/docDisplay.js
js/ui/endSessionDialog.js
js/ui/lookingGlass.js js/ui/lookingGlass.js
js/ui/messageTray.js
js/ui/overview.js js/ui/overview.js
js/ui/panel.js js/ui/panel.js
js/ui/placeDisplay.js js/ui/placeDisplay.js
@ -16,6 +19,7 @@ js/ui/runDialog.js
js/ui/statusMenu.js js/ui/statusMenu.js
js/ui/status/accessibility.js js/ui/status/accessibility.js
js/ui/status/bluetooth.js js/ui/status/bluetooth.js
js/ui/status/keyboard.js
js/ui/status/power.js js/ui/status/power.js
js/ui/status/volume.js js/ui/status/volume.js
js/ui/telepathyClient.js js/ui/telepathyClient.js

725
po/ar.po

File diff suppressed because it is too large Load Diff

567
po/de.po
View File

@ -6,19 +6,21 @@
# #
# Hendrik Brandt <heb@gnome-de.org>, 2009. # Hendrik Brandt <heb@gnome-de.org>, 2009.
# Hendrik Richter <hendrikr@gnome.org>, 2009. # Hendrik Richter <hendrikr@gnome.org>, 2009.
# Mario Blättermann <mariobl@gnome.org>, 2009, 2010. # Mario Blättermann <mariobl@gnome.org>, 2009, 2010, 2011.
# Mario Klug <mario@klug.me>, 2010. # Mario Klug <mario@klug.me>, 2010.
# Christian Kirbach <Christian.Kirbach@googlemail.com>, 2009, 2010. # Jakob Kramer <jakob.kramer@gmx.de>, 2010.
# Paul Seyfert <pseyfert@mathphys.fsk.uni-heidelberg.de>, 2010.
# Christian Kirbach <Christian.Kirbach@googlemail.com>, 2009, 2010, 2011.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: \n"
"shell&component=general\n" "POT-Creation-Date: 2011-01-01 23:21+0100\n"
"POT-Creation-Date: 2010-10-10 03:14+0000\n" "PO-Revision-Date: 2011-01-01 16:25+0100\n"
"PO-Revision-Date: 2010-10-10 20:23+0200\n"
"Last-Translator: Christian Kirbach <Christian.Kirbach@googlemail.com>\n" "Last-Translator: Christian Kirbach <Christian.Kirbach@googlemail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n" "Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
@ -105,12 +107,8 @@ msgstr ""
msgid "List of desktop file IDs for favorite applications" msgid "List of desktop file IDs for favorite applications"
msgstr "Liste der Kennungen der Desktop-Dateien für bevorzugte Anwendungen" msgstr "Liste der Kennungen der Desktop-Dateien für bevorzugte Anwendungen"
#: ../data/org.gnome.shell.gschema.xml.in.h:13
msgid "Overview workspace view mode"
msgstr "Modus des Arbeitsflächen-Überblicks"
# Hier blicke ich überhaupt nicht durch. # Hier blicke ich überhaupt nicht durch.
#: ../data/org.gnome.shell.gschema.xml.in.h:14 #: ../data/org.gnome.shell.gschema.xml.in.h:13
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
"used for gst-launch. The pipeline should have an unconnected sink pad where " "used for gst-launch. The pipeline should have an unconnected sink pad where "
@ -130,22 +128,22 @@ msgstr ""
"Das kann zum Senden der Ausgabe über shout2send an einen Icecast-Server oder " "Das kann zum Senden der Ausgabe über shout2send an einen Icecast-Server oder "
"Ähnliches verwendet werden. Falls nicht (oder auf einen leeren Wert) " "Ähnliches verwendet werden. Falls nicht (oder auf einen leeren Wert) "
"gesetzt, so wird die vorgegebene Weiterleitung verwendet, welche derzeit " "gesetzt, so wird die vorgegebene Weiterleitung verwendet, welche derzeit "
"»videorate ! theoraenc ! oggmux« lautet und die Aufnahme im Ogg-Theora-Format " "»videorate ! theoraenc ! oggmux« lautet und die Aufnahme im Ogg-Theora-"
"speichert." "Format speichert."
#: ../data/org.gnome.shell.gschema.xml.in.h:15 #: ../data/org.gnome.shell.gschema.xml.in.h:14
msgid "Show date in clock" msgid "Show date in clock"
msgstr "Datum in der Uhr anzeigen" msgstr "Datum in der Uhr anzeigen"
#: ../data/org.gnome.shell.gschema.xml.in.h:16 #: ../data/org.gnome.shell.gschema.xml.in.h:15
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "Wochentag im Kalender anzeigen" msgstr "Wochentag im Kalender anzeigen"
#: ../data/org.gnome.shell.gschema.xml.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.h:16
msgid "Show time with seconds" msgid "Show time with seconds"
msgstr "Zeit sekundengenau anzeigen" msgstr "Zeit sekundengenau anzeigen"
#: ../data/org.gnome.shell.gschema.xml.in.h:18 #: ../data/org.gnome.shell.gschema.xml.in.h:17
msgid "" msgid ""
"The applications corresponding to these identifiers will be displayed in the " "The applications corresponding to these identifiers will be displayed in the "
"favorites area." "favorites area."
@ -153,7 +151,7 @@ msgstr ""
"Programme, welche auf diese Bezeichner zutreffen, werden im Favoriten-" "Programme, welche auf diese Bezeichner zutreffen, werden im Favoriten-"
"Bereich angezeigt." "Bereich angezeigt."
#: ../data/org.gnome.shell.gschema.xml.in.h:19 #: ../data/org.gnome.shell.gschema.xml.in.h:18
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@ -164,7 +162,7 @@ msgstr ""
"Dateiname sollte geändert werden, wenn Sie in einem anderen Containerformat " "Dateiname sollte geändert werden, wenn Sie in einem anderen Containerformat "
"aufnehmen." "aufnehmen."
#: ../data/org.gnome.shell.gschema.xml.in.h:20 #: ../data/org.gnome.shell.gschema.xml.in.h:19
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@ -173,19 +171,11 @@ msgstr ""
"der GNOME-Shell aufgezeichnet werden soll, in Einzelbildern pro Sekunde." "der GNOME-Shell aufgezeichnet werden soll, in Einzelbildern pro Sekunde."
# hmm Enkodieren oder Kodieren? # hmm Enkodieren oder Kodieren?
#: ../data/org.gnome.shell.gschema.xml.in.h:21 #: ../data/org.gnome.shell.gschema.xml.in.h:20
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "Die GStreamer-Weiterleitung zur Enkodierung des Screencasts" msgstr "Die GStreamer-Weiterleitung zur Enkodierung des Screencasts"
#: ../data/org.gnome.shell.gschema.xml.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.h:21
msgid ""
"The selected workspace view mode in the overview. Supported values are "
"\"single\" and \"grid\"."
msgstr ""
"Die gewählte Ansicht des Arbeitsflächen-Überblicks. Mögliche Werte sind "
"»single« (einfach) und »grid« (Raster)."
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "" msgid ""
"The shell normally monitors active applications in order to present the most " "The shell normally monitors active applications in order to present the most "
"used ones (e.g. in launchers). While this data will be kept private, you may " "used ones (e.g. in launchers). While this data will be kept private, you may "
@ -198,7 +188,7 @@ msgstr ""
"deaktivieren, um Ihre Privatsphäre zu schützen. Bitte beachten Sie, dass " "deaktivieren, um Ihre Privatsphäre zu schützen. Bitte beachten Sie, dass "
"bereits gespeicherte Daten hiervon nicht beeinflusst werden." "bereits gespeicherte Daten hiervon nicht beeinflusst werden."
#: ../data/org.gnome.shell.gschema.xml.in.h:24 #: ../data/org.gnome.shell.gschema.xml.in.h:22
msgid "" msgid ""
"This key specifies the format used by the panel clock when the format key is " "This key specifies the format used by the panel clock when the format key is "
"set to \"custom\". You can use conversion specifiers understood by strftime" "set to \"custom\". You can use conversion specifiers understood by strftime"
@ -211,7 +201,7 @@ msgstr ""
"Format zu erhalten. Weitere Informationen finden Sie in der Handbuchseite zu " "Format zu erhalten. Weitere Informationen finden Sie in der Handbuchseite zu "
"strftime()." "strftime()."
#: ../data/org.gnome.shell.gschema.xml.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "" msgid ""
"This key specifies the hour format used by the panel clock. Possible values " "This key specifies the hour format used by the panel clock. Possible values "
"are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", " "are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", "
@ -221,18 +211,18 @@ msgid ""
"the show_date and show_seconds keys are ignored." "the show_date and show_seconds keys are ignored."
msgstr "" msgstr ""
"Dieser Schlüssel legt das Stundenformat für die Anzeige der Panel-Uhr fest. " "Dieser Schlüssel legt das Stundenformat für die Anzeige der Panel-Uhr fest. "
"Mögliche Werte sind »12-hour«, »24-hour«, »unix« und »custom«. Wenn Sie »unix« " "Mögliche Werte sind »12-hour«, »24-hour«, »unix« und »custom«. Wenn Sie "
"verwenden, zeigt die Uhr die Sekunden seit Epoch, dem Beginn der Unix-" "»unix« verwenden, zeigt die Uhr die Sekunden seit Epoch, dem Beginn der Unix-"
"Zeitrechnung am 1. Januar 1970 an. Wenn Sie »custom« (benutzerdefiniert) " "Zeitrechnung am 1. Januar 1970 an. Wenn Sie »custom« (benutzerdefiniert) "
"verwenden, zeigt die Uhr die Zeit gemäß dem im Schlüssel »custom_format« " "verwenden, zeigt die Uhr die Zeit gemäß dem im Schlüssel »custom_format« "
"angegebenen Format an. Beachten Sie, dass bei »unix« oder »custom« die " "angegebenen Format an. Beachten Sie, dass bei »unix« oder »custom« die "
"Schlüssel »show_date« und »show_seconds« ignoriert werden." "Schlüssel »show_date« und »show_seconds« ignoriert werden."
#: ../data/org.gnome.shell.gschema.xml.in.h:26 #: ../data/org.gnome.shell.gschema.xml.in.h:24
msgid "Uuids of extensions to disable" msgid "Uuids of extensions to disable"
msgstr "UUIDs der zu deaktivierenden Erweiterungen" msgstr "UUIDs der zu deaktivierenden Erweiterungen"
#: ../data/org.gnome.shell.gschema.xml.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.h:25
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
msgstr "Legt fest, ob der Status der Anwendungsnutzung erfasst werden soll" msgstr "Legt fest, ob der Status der Anwendungsnutzung erfasst werden soll"
@ -266,14 +256,14 @@ msgid ""
msgstr "" msgstr ""
"Legt die Position des vergrößerten Bildes der Maus innerhalb der " "Legt die Position des vergrößerten Bildes der Maus innerhalb der "
"vergrößerten Ansicht fest, und wie die Maus auf die Mausbewegungen des " "vergrößerten Ansicht fest, und wie die Maus auf die Mausbewegungen des "
"Systems reagiert. Folgende Werte sind möglich: »none« - keine Mausverfolgung; " "Systems reagiert. Folgende Werte sind möglich: »none« - keine "
"»centered« - das Mausbild wird in der Mitte des vergrößerten Bereiches " "Mausverfolgung; »centered« - das Mausbild wird in der Mitte des vergrößerten "
"dargestellt (welche auch den Zeiger der Systemmaus darstellt), wobei der " "Bereiches dargestellt (welche auch den Zeiger der Systemmaus darstellt), "
"vergrößerte Inhalt gerollt wird, sobald die Systemmaus bewegt wird; " "wobei der vergrößerte Inhalt gerollt wird, sobald die Systemmaus bewegt "
"»proportional« - die Position der vergrößerten Maus im vergrößerten Bereich " "wird; »proportional« - die Position der vergrößerten Maus im vergrößerten "
"ist proportional zur Position der Systemmaus auf dem Bildschirm; »push« - " "Bereich ist proportional zur Position der Systemmaus auf dem Bildschirm; "
"wenn die vergrößerte Maus einen der Ränder des vergrößerten Bereichs " "»push« - wenn die vergrößerte Maus einen der Ränder des vergrößerten "
"berührt, wird der entsprechende Inhalt in die Ansicht geschoben." "Bereichs berührt, wird der entsprechende Inhalt in die Ansicht geschoben."
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:5 #: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:5
msgid "" msgid ""
@ -422,62 +412,46 @@ msgstr "_12-Stunden-Format"
msgid "_24 hour format" msgid "_24 hour format"
msgstr "_24-Stunden-Format" msgstr "_24-Stunden-Format"
#. **** Applications **** #. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:316 ../js/ui/dash.js:778 #: ../js/ui/appDisplay.js:155
msgid "All"
msgstr "Alle"
#: ../js/ui/appDisplay.js:236
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "ANWENDUNGEN" msgstr "ANWENDUNGEN"
#: ../js/ui/appDisplay.js:348 #: ../js/ui/appDisplay.js:266
msgid "PREFERENCES" msgid "PREFERENCES"
msgstr "EINSTELLUNGEN" msgstr "EINSTELLUNGEN"
#: ../js/ui/appDisplay.js:648 #: ../js/ui/appDisplay.js:563
msgid "New Window" msgid "New Window"
msgstr "Neues Fenster" msgstr "Neues Fenster"
#: ../js/ui/appDisplay.js:652 #: ../js/ui/appDisplay.js:567
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Aus Favoriten entfernen" msgstr "Aus Favoriten entfernen"
#: ../js/ui/appDisplay.js:653 #: ../js/ui/appDisplay.js:568
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Zu Favoriten hinzufügen" msgstr "Zu Favoriten hinzufügen"
#: ../js/ui/appDisplay.js:830 #: ../js/ui/appFavorites.js:91
msgid "Drag here to add favorites"
msgstr "Hier ablegen, um zu Favoriten hinzuzufügen"
#: ../js/ui/appFavorites.js:88
#, c-format #, c-format
msgid "%s has been added to your favorites." msgid "%s has been added to your favorites."
msgstr "%s wurde zu Ihren Favoriten hinzugefügt" msgstr "%s wurde zu Ihren Favoriten hinzugefügt"
#: ../js/ui/appFavorites.js:107 #: ../js/ui/appFavorites.js:122
#, c-format #, c-format
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s wurde aus Ihren Favoriten entfernt" msgstr "%s wurde aus Ihren Favoriten entfernt"
#: ../js/ui/dash.js:142 #: ../js/ui/dash.js:27
msgid "Find" msgid "Remove"
msgstr "Suchen" msgstr "Entfernen"
#: ../js/ui/dash.js:473 #: ../js/ui/docDisplay.js:494
msgid "Searching..."
msgstr "Suche läuft …"
#: ../js/ui/dash.js:487
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:797 ../js/ui/placeDisplay.js:554
msgid "PLACES & DEVICES"
msgstr "ORTE UND GERÄTE"
#. **** Documents ****
#: ../js/ui/dash.js:804 ../js/ui/docDisplay.js:494
msgid "RECENT ITEMS" msgid "RECENT ITEMS"
msgstr "ZULETZT GEÖFFNETE DOKUMENTE" msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
@ -489,7 +463,9 @@ msgstr "Keine Erweiterungen installiert"
msgid "Enabled" msgid "Enabled"
msgstr "Aktiviert" msgstr "Aktiviert"
#: ../js/ui/lookingGlass.js:591 #. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087
msgid "Disabled" msgid "Disabled"
msgstr "Deaktiviert" msgstr "Deaktiviert"
@ -509,63 +485,71 @@ msgstr "Quelle zeigen"
msgid "Web Page" msgid "Web Page"
msgstr "Webseite" msgstr "Webseite"
#: ../js/ui/overview.js:160 #: ../js/ui/overview.js:96
msgid "Undo" msgid "Undo"
msgstr "Rückgängig" msgstr "Rückgängig"
#: ../js/ui/overview.js:158
msgid "Windows"
msgstr "Fenster"
#: ../js/ui/overview.js:161
msgid "Applications"
msgstr "Anwendungen"
#. TODO - _quit() doesn't really work on apps in state STARTING yet #. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:468 #: ../js/ui/panel.js:474
#, c-format #, c-format
msgid "Quit %s" msgid "Quit %s"
msgstr "%s beenden" msgstr "%s beenden"
#: ../js/ui/panel.js:493 #: ../js/ui/panel.js:499
msgid "Preferences" msgid "Preferences"
msgstr "Einstellungen" msgstr "Einstellungen"
#. Translators: This is the time format with date used #. Translators: This is the time format with date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:579 #: ../js/ui/panel.js:585
msgid "%a %b %e, %R:%S" msgid "%a %b %e, %R:%S"
msgstr "%a, %e. %b, %R:%S" msgstr "%a, %e. %b, %R:%S"
#: ../js/ui/panel.js:580 #: ../js/ui/panel.js:586
msgid "%a %b %e, %R" msgid "%a %b %e, %R"
msgstr "%a, %e. %b, %R" msgstr "%a, %e. %b, %R"
#. Translators: This is the time format without date used #. Translators: This is the time format without date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:584 #: ../js/ui/panel.js:590
msgid "%a %R:%S" msgid "%a %R:%S"
msgstr "%a %R:%S" msgstr "%a %R:%S"
#: ../js/ui/panel.js:585 #: ../js/ui/panel.js:591
msgid "%a %R" msgid "%a %R"
msgstr "%a %R" msgstr "%a %R"
#. Translators: This is a time format with date used #. Translators: This is a time format with date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:592 #: ../js/ui/panel.js:598
msgid "%a %b %e, %l:%M:%S %p" msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a, %e. %b, %H:%M:%S" msgstr "%a, %e. %b, %H:%M:%S"
#: ../js/ui/panel.js:593 #: ../js/ui/panel.js:599
msgid "%a %b %e, %l:%M %p" msgid "%a %b %e, %l:%M %p"
msgstr "%a, %e. %b, %H:%M" msgstr "%a, %e. %b, %H:%M"
#. Translators: This is a time format without date used #. Translators: This is a time format without date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:597 #: ../js/ui/panel.js:603
msgid "%a %l:%M:%S %p" msgid "%a %l:%M:%S %p"
msgstr "%a %H:%M:%S" msgstr "%a %H:%M:%S"
#: ../js/ui/panel.js:598 #: ../js/ui/panel.js:604
msgid "%a %l:%M %p" msgid "%a %l:%M %p"
msgstr "%a %H:%M" msgstr "%a %H:%M"
#. Button on the left side of the panel. #. 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". #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:743 #: ../js/ui/panel.js:749
msgid "Activities" msgid "Activities"
msgstr "Aktivitäten" msgstr "Aktivitäten"
@ -582,6 +566,10 @@ msgstr "Erneut versuchen"
msgid "Connect to..." msgid "Connect to..."
msgstr "Verbinden mit …" msgstr "Verbinden mit …"
#: ../js/ui/placeDisplay.js:558
msgid "PLACES & DEVICES"
msgstr "ORTE UND GERÄTE"
#. Translators: this MUST be either "toggle-switch-us" #. Translators: this MUST be either "toggle-switch-us"
#. (for toggle switches containing the English words #. (for toggle switches containing the English words
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
@ -600,42 +588,332 @@ msgstr "Bitte geben Sie einen Befehl ein:"
msgid "Execution of '%s' failed:" msgid "Execution of '%s' failed:"
msgstr "Ausführung von »%s« ist gescheitert:" msgstr "Ausführung von »%s« ist gescheitert:"
#: ../js/ui/statusMenu.js:91 #: ../js/ui/statusMenu.js:101
msgid "Available" msgid "Available"
msgstr "Verfügbar" msgstr "Verfügbar"
#: ../js/ui/statusMenu.js:95 #: ../js/ui/statusMenu.js:106
msgid "Busy" msgid "Busy"
msgstr "Beschäftigt" msgstr "Beschäftigt"
#: ../js/ui/statusMenu.js:99 #: ../js/ui/statusMenu.js:114
msgid "Invisible" msgid "My Account"
msgstr "Unsichtbar" msgstr "Eigenes Konto"
#: ../js/ui/statusMenu.js:106 #: ../js/ui/statusMenu.js:118
msgid "Account Information..." msgid "System Settings"
msgstr "Benutzerinformationen …" msgstr "Systemeinstellungen"
#: ../js/ui/statusMenu.js:110 #: ../js/ui/statusMenu.js:125
msgid "System Settings..."
msgstr "Systemeinstellungen …"
#: ../js/ui/statusMenu.js:117
msgid "Lock Screen" msgid "Lock Screen"
msgstr "Bildschirm sperren" msgstr "Bildschirm sperren"
#: ../js/ui/statusMenu.js:121 #: ../js/ui/statusMenu.js:129
msgid "Switch User" msgid "Switch User"
msgstr "Benutzer wechseln" msgstr "Benutzer wechseln"
#: ../js/ui/statusMenu.js:126 #: ../js/ui/statusMenu.js:134
msgid "Log Out..." msgid "Log Out..."
msgstr "Abmelden …" msgstr "Abmelden …"
#: ../js/ui/statusMenu.js:130 #: ../js/ui/statusMenu.js:141
msgid "Suspend..."
msgstr "Bereitschaft …"
#: ../js/ui/statusMenu.js:145
msgid "Shut Down..." msgid "Shut Down..."
msgstr "Ausschalten …" msgstr "Ausschalten …"
#: ../js/ui/status/accessibility.js:82
msgid "Zoom"
msgstr "Vergrößern"
#: ../js/ui/status/accessibility.js:88
msgid "Screen Reader"
msgstr "Bildschirmleser"
#: ../js/ui/status/accessibility.js:91
msgid "Screen Keyboard"
msgstr "Bildschirmtastatur"
#: ../js/ui/status/accessibility.js:94
msgid "Visual Alerts"
msgstr "Visuelle Warnungen"
#: ../js/ui/status/accessibility.js:97
msgid "Sticky Keys"
msgstr "Klebrige Tasten"
#: ../js/ui/status/accessibility.js:100
msgid "Slow Keys"
msgstr "Tastenverzögerung"
#: ../js/ui/status/accessibility.js:103
msgid "Bounce Keys"
msgstr "Springende Tasten"
#: ../js/ui/status/accessibility.js:106
msgid "Mouse Keys"
msgstr "Maustasten"
#: ../js/ui/status/accessibility.js:110
msgid "Universal Access Settings"
msgstr "Einstellungen zur Barrierefreiheit"
#: ../js/ui/status/accessibility.js:163
msgid "High Contrast"
msgstr "Hoher Kontrast"
#: ../js/ui/status/accessibility.js:205
msgid "Large Text"
msgstr "Große Schrift"
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:234
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:55
msgid "Visibility"
msgstr "Sichtbarkeit"
#: ../js/ui/status/bluetooth.js:69
msgid "Send Files to Device..."
msgstr "Dateien an Gerät senden …"
#: ../js/ui/status/bluetooth.js:70
msgid "Setup a New Device..."
msgstr "Ein neues Gerät einrichten …"
#: ../js/ui/status/bluetooth.js:94
msgid "Bluetooth Settings"
msgstr "Bluetooth-Einstellungen"
#: ../js/ui/status/bluetooth.js:185
msgid "Connection"
msgstr "Verbindung"
#: ../js/ui/status/bluetooth.js:221
msgid "Send Files..."
msgstr "Dateien senden …"
#: ../js/ui/status/bluetooth.js:226
msgid "Browse Files..."
msgstr "Dateien durchsuchen …"
#: ../js/ui/status/bluetooth.js:235
msgid "Error browsing device"
msgstr "Fehler beim Durchsuchen des Geräts"
#: ../js/ui/status/bluetooth.js:236
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr ""
"Das angesprochene Gerät kann nicht durchsucht werden. Der Fehler lautet »%s«"
#: ../js/ui/status/bluetooth.js:244
msgid "Keyboard Settings"
msgstr "Tastatureinstellungen"
#: ../js/ui/status/bluetooth.js:249
msgid "Mouse Settings"
msgstr "Maus-Einstellungen"
#: ../js/ui/status/bluetooth.js:256 ../js/ui/status/volume.js:62
msgid "Sound Settings"
msgstr "Klangeinstellungen"
#: ../js/ui/status/bluetooth.js:327 ../js/ui/status/bluetooth.js:361
#: ../js/ui/status/bluetooth.js:401 ../js/ui/status/bluetooth.js:434
msgid "Bluetooth Agent"
msgstr "Bluetooth-Agent"
#: ../js/ui/status/bluetooth.js:362
#, c-format
msgid "Authorization request from %s"
msgstr "Legitimierungsanfrage von %s"
#: ../js/ui/status/bluetooth.js:368
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "Gerät »%s« bittet um Zugriff auf den Dienst »%s«"
#: ../js/ui/status/bluetooth.js:370
msgid "Always grant access"
msgstr "Immer Zugriff gewähren"
#: ../js/ui/status/bluetooth.js:371
msgid "Grant this time only"
msgstr "Nur dieses Mal gewähren"
#: ../js/ui/status/bluetooth.js:372
msgid "Reject"
msgstr "Abweisen"
#: ../js/ui/status/bluetooth.js:402
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Koppelungsbestätigung für %s"
#: ../js/ui/status/bluetooth.js:408 ../js/ui/status/bluetooth.js:442
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Gerät »%s« möchte mit diesem Rechner gekoppelt werden"
#: ../js/ui/status/bluetooth.js:409
#, c-format
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr ""
"Bitte bestätigen Sie, ob die PIN »%s« mit der des Gerätes übereinstimmt."
#: ../js/ui/status/bluetooth.js:411
msgid "Matches"
msgstr "Stimmt überein"
#: ../js/ui/status/bluetooth.js:412
msgid "Does not match"
msgstr "Stimmt nicht überein"
#: ../js/ui/status/bluetooth.js:435
#, c-format
msgid "Pairing request for %s"
msgstr "Koppelungsanfrage für %s"
#: ../js/ui/status/bluetooth.js:443
msgid "Please enter the PIN mentioned on the device."
msgstr "Bitte geben Sie die auf dem Gerät angezeigte PIN ein."
#: ../js/ui/status/bluetooth.js:459
msgid "OK"
msgstr "OK"
#: ../js/ui/status/bluetooth.js:460
msgid "Cancel"
msgstr "Abbrechen"
#: ../js/ui/status/power.js:85
msgid "Power Settings"
msgstr "Energieeinstellungen"
#: ../js/ui/status/power.js:112
#, c-format
msgid "%d hour remaining"
msgid_plural "%d hours remaining"
msgstr[0] "%d Stunde verbleibend"
msgstr[1] "%d Stunden verbleibend"
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#: ../js/ui/status/power.js:115
#, c-format
msgid "%d %s %d %s remaining"
msgstr "%d %s %d %s verbleibend"
#: ../js/ui/status/power.js:117
msgid "hour"
msgid_plural "hours"
msgstr[0] "Stunde"
msgstr[1] "Stunden"
#: ../js/ui/status/power.js:117
msgid "minute"
msgid_plural "minutes"
msgstr[0] "Minute"
msgstr[1] "Minuten"
#: ../js/ui/status/power.js:120
#, c-format
msgid "%d minute remaining"
msgid_plural "%d minutes remaining"
msgstr[0] "%d Minute verbleibend"
msgstr[1] "%d Minuten verbleibend"
#: ../js/ui/status/power.js:237
msgid "AC adapter"
msgstr "Netzteil"
#: ../js/ui/status/power.js:239
msgid "Laptop battery"
msgstr "Laptop-Akku"
#: ../js/ui/status/power.js:241
msgid "UPS"
msgstr "Notstromversorgung"
#: ../js/ui/status/power.js:243
msgid "Monitor"
msgstr "Bildschirm"
#: ../js/ui/status/power.js:245
msgid "Mouse"
msgstr "Maus"
#: ../js/ui/status/power.js:247
msgid "Keyboard"
msgstr "Tastatur"
#: ../js/ui/status/power.js:249
msgid "PDA"
msgstr "PDA"
#: ../js/ui/status/power.js:251
msgid "Cell phone"
msgstr "Mobiltelefon"
#: ../js/ui/status/power.js:253
msgid "Media player"
msgstr "Medienwiedergabegerät"
#: ../js/ui/status/power.js:255
msgid "Tablet"
msgstr "Tablet"
#: ../js/ui/status/power.js:257
msgid "Computer"
msgstr "Rechner"
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
msgid "Unknown"
msgstr "Unbekannt"
#: ../js/ui/status/volume.js:41
msgid "Volume"
msgstr "Lautstärke"
#: ../js/ui/status/volume.js:54
msgid "Microphone"
msgstr "Mikrofon"
#: ../js/ui/telepathyClient.js:560
#, c-format
msgid "%s is online."
msgstr "%s ist angemeldet."
#: ../js/ui/telepathyClient.js:565
#, c-format
msgid "%s is offline."
msgstr "%s ist abgemeldet."
#: ../js/ui/telepathyClient.js:568
#, c-format
msgid "%s is away."
msgstr "»%s« ist abwesend."
#: ../js/ui/telepathyClient.js:571
#, c-format
msgid "%s is busy."
msgstr "%s ist beschäftigt."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:665
#, no-c-format
msgid "Sent at %X on %A"
msgstr "Gesendet am %A um %X "
#: ../js/ui/viewSelector.js:26
msgid "Search your computer"
msgstr "Ihren Rechner durchsuchen"
#: ../js/ui/windowAttentionHandler.js:43 #: ../js/ui/windowAttentionHandler.js:43
#, c-format #, c-format
msgid "%s has finished starting" msgid "%s has finished starting"
@ -646,60 +924,82 @@ msgstr "Start von %s ist abgeschlossen"
msgid "'%s' is ready" msgid "'%s' is ready"
msgstr "»%s« ist bereit" msgstr "»%s« ist bereit"
#: ../js/ui/workspacesView.js:230 #: ../js/ui/workspacesView.js:244
msgid "" msgid ""
"Can't add a new workspace because maximum workspaces limit has been reached." "Can't add a new workspace because maximum workspaces limit has been reached."
msgstr "" msgstr ""
"Es kann keine weitere Arbeitsfläche hinzugefügt werden, weil das Maximum an " "Es kann keine weitere Arbeitsfläche hinzugefügt werden, weil das Maximum an "
"Arbeitsflächen erreicht worden ist." "Arbeitsflächen erreicht worden ist."
#: ../js/ui/workspacesView.js:247 #: ../js/ui/workspacesView.js:260
msgid "Can't remove the first workspace." msgid "Can't remove the first workspace."
msgstr "Die erste Arbeitsfläche kann nicht entfernt werden." msgstr "Die erste Arbeitsfläche kann nicht entfernt werden."
#: ../src/shell-global.c:1196 #. translators:
#. * The number of sound outputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1094
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
msgstr[0] "%u Ausgang"
msgstr[1] "%u Ausgänge"
#. translators:
#. * The number of sound inputs on a particular device
#: ../src/gvc/gvc-mixer-control.c:1104
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u Eingang"
msgstr[1] "%u Eingänge"
#: ../src/gvc/gvc-mixer-control.c:1402
msgid "System Sounds"
msgstr "Systemklänge"
#: ../src/shell-global.c:1156
msgid "Less than a minute ago" msgid "Less than a minute ago"
msgstr "Vor weniger als einer Minute" msgstr "Vor weniger als einer Minute"
#: ../src/shell-global.c:1200 #: ../src/shell-global.c:1160
#, c-format #, c-format
msgid "%d minute ago" msgid "%d minute ago"
msgid_plural "%d minutes ago" msgid_plural "%d minutes ago"
msgstr[0] "Vor %d Minute" msgstr[0] "Vor %d Minute"
msgstr[1] "Vor %d Minuten" msgstr[1] "Vor %d Minuten"
#: ../src/shell-global.c:1205 #: ../src/shell-global.c:1165
#, c-format #, c-format
msgid "%d hour ago" msgid "%d hour ago"
msgid_plural "%d hours ago" msgid_plural "%d hours ago"
msgstr[0] "Vor %d Stunde" msgstr[0] "Vor %d Stunde"
msgstr[1] "Vor %d Stunden" msgstr[1] "Vor %d Stunden"
#: ../src/shell-global.c:1210 #: ../src/shell-global.c:1170
#, c-format #, c-format
msgid "%d day ago" msgid "%d day ago"
msgid_plural "%d days ago" msgid_plural "%d days ago"
msgstr[0] "Vor %d Tag" msgstr[0] "Vor %d Tag"
msgstr[1] "Vor %d Tagen" msgstr[1] "Vor %d Tagen"
#: ../src/shell-global.c:1215 #: ../src/shell-global.c:1175
#, c-format #, c-format
msgid "%d week ago" msgid "%d week ago"
msgid_plural "%d weeks ago" msgid_plural "%d weeks ago"
msgstr[0] "Vor %d Woche" msgstr[0] "Vor %d Woche"
msgstr[1] "Vor %d Wochen" msgstr[1] "Vor %d Wochen"
#: ../src/shell-uri-util.c:89 #: ../src/shell-util.c:89
msgid "Home Folder" msgid "Home Folder"
msgstr "Persönlicher Ordner" msgstr "Persönlicher Ordner"
#. Translators: this is the same string as the one found in #. Translators: this is the same string as the one found in
#. * nautilus #. * nautilus
#: ../src/shell-uri-util.c:104 #: ../src/shell-util.c:104
msgid "File System" msgid "File System"
msgstr "Dateisystem" msgstr "Dateisystem"
#: ../src/shell-uri-util.c:250 #: ../src/shell-util.c:250
msgid "Search" msgid "Search"
msgstr "Suchen" msgstr "Suchen"
@ -708,11 +1008,42 @@ msgstr "Suchen"
#. * example, "Trash: some-directory". It means that the #. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash. #. * directory called "some-directory" is in the trash.
#. #.
#: ../src/shell-uri-util.c:300 #: ../src/shell-util.c:300
#, c-format #, c-format
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s" msgstr "%1$s: %2$s"
#~ msgid "What's using power..."
#~ msgstr "Energieverbraucher …"
#~ msgid "Overview workspace view mode"
#~ msgstr "Modus des Arbeitsflächen-Überblicks"
#~ msgid ""
#~ "The selected workspace view mode in the overview. Supported values are "
#~ "\"single\" and \"grid\"."
#~ msgstr ""
#~ "Die gewählte Ansicht des Arbeitsflächen-Überblicks. Mögliche Werte sind "
#~ "»single« (einfach) und »grid« (Raster)."
#~ msgid "Drag here to add favorites"
#~ msgstr "Hier ablegen, um zu Favoriten hinzuzufügen"
#~ msgid "Find"
#~ msgstr "Suchen"
#~ msgid "Searching..."
#~ msgstr "Suche läuft …"
#~ msgid "No matching results."
#~ msgstr "Keine passenden Ergebnisse."
#~ msgid "Invisible"
#~ msgstr "Unsichtbar"
#~ msgid "Account Information..."
#~ msgstr "Benutzerinformationen …"
#~ msgid "ON" #~ msgid "ON"
#~ msgstr "EIN" #~ msgstr "EIN"
@ -725,9 +1056,6 @@ msgstr "%1$s: %2$s"
#~ msgid "%H:%M" #~ msgid "%H:%M"
#~ msgstr "%H:%M" #~ msgstr "%H:%M"
#~ msgid "Applications"
#~ msgstr "Anwendungen"
#~ msgid "Recent Documents" #~ msgid "Recent Documents"
#~ msgstr "Zuletzt geöffnete Dokumente" #~ msgstr "Zuletzt geöffnete Dokumente"
@ -746,9 +1074,6 @@ msgstr "%1$s: %2$s"
#~ msgid "SEARCH RESULTS" #~ msgid "SEARCH RESULTS"
#~ msgstr "SUCHERGEBNISSE" #~ msgstr "SUCHERGEBNISSE"
#~ msgid "Unknown"
#~ msgstr "Unbekannt"
#~ msgid "Can't lock screen: %s" #~ msgid "Can't lock screen: %s"
#~ msgstr "Bildschirm kann nicht gesperrt werden: %s" #~ msgstr "Bildschirm kann nicht gesperrt werden: %s"

915
po/el.po

File diff suppressed because it is too large Load Diff

615
po/es.po

File diff suppressed because it is too large Load Diff

340
po/et.po
View File

@ -1,16 +1,21 @@
# GNOME kesta eesti keele tõlge.
# Estonian translation for gnome-shell. # Estonian translation for gnome-shell.
# Copyright (C) 2010 The Gnome Project #
# Copyright (C) 2010, 2011 The Gnome Project
#
# This file is distributed under the same license as the gnome-shell package. # This file is distributed under the same license as the gnome-shell package.
# Mattias Põldaru <mahfiaz gmail com>, 2010. #
# Mattias Põldaru <mahfiaz gmail com>, 2010, 2011.
# Ivar Smolin <okul linux ee>, 2011.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell MASTER\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n" "shell&component=general\n"
"POT-Creation-Date: 2010-12-18 23:05+0000\n" "POT-Creation-Date: 2011-01-29 18:34+0000\n"
"PO-Revision-Date: 2010-12-18 11:47+0200\n" "PO-Revision-Date: 2011-02-01 13:51+0300\n"
"Last-Translator: Ivar Smolin <okul@linux.ee>\n" "Last-Translator: Mattias Põldaru <mahfiaz gmail com>\n"
"Language-Team: Estonian <gnome-et@linux.ee>\n" "Language-Team: Estonian <gnome-et@linux.ee>\n"
"Language: et\n" "Language: et\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -26,12 +31,6 @@ msgstr "GNOME kest"
msgid "Window management and application launching" msgid "Window management and application launching"
msgstr "Aknahaldur ja rakenduste käivitaja" msgstr "Aknahaldur ja rakenduste käivitaja"
msgid "Clock"
msgstr "Kell"
msgid "Customize the panel clock"
msgstr "Paneelikella kohandamine"
msgid "" msgid ""
"Allows access to internal debugging and monitoring tools using the Alt-F2 " "Allows access to internal debugging and monitoring tools using the Alt-F2 "
"dialog." "dialog."
@ -39,15 +38,12 @@ msgstr ""
"Lubab ligipääsu sisemistele silumise ja monitoorimise tööriistadele Alt-F2 " "Lubab ligipääsu sisemistele silumise ja monitoorimise tööriistadele Alt-F2 "
"dialoogi kaudu." "dialoogi kaudu."
msgid "Custom format of the clock"
msgstr "Kellaaaja kohandatud vorming"
msgid "Enable internal tools useful for developers and testers from Alt-F2" msgid "Enable internal tools useful for developers and testers from Alt-F2"
msgstr "" msgstr ""
"Arendajate ja testijate jaoks sisemiste tööriistade lubamine Alt-F2 alt" "Arendajate ja testijate jaoks sisemiste tööriistade lubamine Alt-F2 alt"
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "Faililaiend, mida kasutatakse ekraanivideo salvestamisel" msgstr "Ekraanivideo salvestamisel kasutatav faililaiend"
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "Ekraanivideo lindistamisel kasutatav kaadrikiirus." msgstr "Ekraanivideo lindistamisel kasutatav kaadrikiirus."
@ -56,33 +52,25 @@ msgid ""
"GNOME Shell extensions have a uuid property; this key lists extensions which " "GNOME Shell extensions have a uuid property; this key lists extensions which "
"should not be loaded." "should not be loaded."
msgstr "" msgstr ""
"GNOME Shelli laiendustel on omadus UUID. Selle võtmega määratakse "
"laiendused, mida ei peaks laaditama."
msgid "History for command (Alt-F2) dialog" msgid "History for command (Alt-F2) dialog"
msgstr "Käsudialoogi (Alt-F2) ajalugu" msgstr "Käsudialoogi (Alt-F2) ajalugu"
msgid "Hour format" msgid "If true, display date in the clock, in addition to time."
msgstr "Tundide vorming" msgstr "Kui määratud, siis kuvatakse kellaaja kõrval ka kuupäeva."
msgid "" msgid "If true, display seconds in time."
"If true and format is either \"12-hour\" or \"24-hour\", display date in the " msgstr "Kui määratud, siis kuvatakse aja juures ka sekundeid."
"clock, in addition to time."
msgstr ""
"Kui tõene ja vorming on kas \"12-tundi\" või \"24-tundi\", kuvatakse "
"kellaaja kõrval ka kuupäeva."
msgid ""
"If true and format is either \"12-hour\" or \"24-hour\", display seconds in "
"time."
msgstr ""
"Kui tõene ja vorming on kas \"12-tundi\" või \"24-tundi\", kuvatakse "
"kellaaega koos sekunditega."
msgid "If true, display the ISO week date in the calendar." msgid "If true, display the ISO week date in the calendar."
msgstr "Kui tõene, kuvatakse kalendris kuupäeva ISO nädalate järgi." msgstr "Kui määratud, kuvatakse kalendris kuupäeva ISO nädalavormingus."
msgid "List of desktop file IDs for favorite applications" msgid "List of desktop file IDs for favorite applications"
msgstr "Lemmikrakenduste töölauafailide ID-de loend" msgstr "Lemmikrakenduste töölauafailide ID-de loend"
#, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
"used for gst-launch. The pipeline should have an unconnected sink pad where " "used for gst-launch. The pipeline should have an unconnected sink pad where "
@ -91,14 +79,16 @@ msgid ""
"pipeline can also take care of its own output - this might be used to send " "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 " "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 " "to an empty value, the default pipeline will be used. This is currently "
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora." "'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
"at the optimal thread count on the system."
msgstr "" msgstr ""
msgid "Show date in clock" msgid "Show date in clock"
msgstr "Kell näitab kuupäeva" msgstr "Kell näitab kuupäeva"
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "Kalendris näidatakse nädala kuupäeva" msgstr "Kalendris näidatakse kuupäeva nädalavormingus"
msgid "Show time with seconds" msgid "Show time with seconds"
msgstr "Kellaaega näidatakse sekunditega" msgstr "Kellaaega näidatakse sekunditega"
@ -113,6 +103,10 @@ msgid ""
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
"a different container format." "a different container format."
msgstr "" msgstr ""
"Ekraanivideo jaoks kasutatav failinimi on unikaalne, see sisaldab "
"salvestamise kuupäeva ja ka käesoleva võtmega määratud laiendit. Mõnda teise "
"konteinervormingusse salvestades tuleks ka sellele vormingule vastav laiend "
"määrata."
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
@ -129,28 +123,15 @@ msgid ""
"remove already saved data." "remove already saved data."
msgstr "" msgstr ""
msgid ""
"This key specifies the format used by the panel clock when the format key is "
"set to \"custom\". You can use conversion specifiers understood by strftime"
"() to obtain a specific format. See the strftime() manual for more "
"information."
msgstr ""
msgid ""
"This key specifies the hour format used by the panel clock. Possible values "
"are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", "
"the clock will display time in seconds since Epoch, i.e. 1970-01-01. If set "
"to \"custom\", the clock will display time according to the format specified "
"in the custom_format key. Note that if set to either \"unix\" or \"custom\", "
"the show_date and show_seconds keys are ignored."
msgstr ""
msgid "Uuids of extensions to disable" msgid "Uuids of extensions to disable"
msgstr "Keelatavate laienduste UUID-d" msgstr "Keelatavate laienduste UUID-d"
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
msgstr "" msgstr ""
msgid "disabled OpenSearch providers"
msgstr ""
msgid "Clip the crosshairs at the center" msgid "Clip the crosshairs at the center"
msgstr "Niitristi keskel on auk" msgstr "Niitristi keskel on auk"
@ -261,30 +242,25 @@ msgstr ""
msgid "Width of the vertical and horizontal lines that make up the crosshairs." msgid "Width of the vertical and horizontal lines that make up the crosshairs."
msgstr "Niitristi moodustavate püst- ja rõhtjoone laius" msgstr "Niitristi moodustavate püst- ja rõhtjoone laius"
msgid "Clock Format" msgid "Command not found"
msgstr "Kellaaja vorming"
msgid "Clock Preferences"
msgstr "Kella eelistused"
msgid "Panel Display"
msgstr "Paneelikuva"
msgid "Show seco_nds"
msgstr "_Sekundeid näidatakse"
msgid "Show the _date"
msgstr "_Kuupäeva näidatakse"
msgid "_12 hour format"
msgstr "_12 tunni vorming"
msgid "_24 hour format"
msgstr "_24 tunni vorming"
msgid "All"
msgstr "" msgstr ""
#. Replace "Error invoking GLib.shell_parse_argv: " with
#. something nicer
msgid "Could not parse command:"
msgstr "Käsku pole võimalik analüüsida:"
msgid "No such application"
msgstr "Sellist rakendust ei ole"
#, c-format
msgid "Execution of '%s' failed:"
msgstr "'%s' käivitamine nurjus:"
#. Translators: Filter to display all applications
msgid "All"
msgstr "Kõik"
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "Rakendused" msgstr "Rakendused"
@ -309,11 +285,66 @@ msgid "%s has been removed from your favorites."
msgstr "%s eemaldati lemmikutest." msgstr "%s eemaldati lemmikutest."
msgid "Remove" msgid "Remove"
msgstr "" msgstr "Eemalda"
msgid "RECENT ITEMS" msgid "RECENT ITEMS"
msgstr "Hiljutised dokumendid" msgstr "Hiljutised dokumendid"
#, c-format
msgid "Log Out %s"
msgstr "Logi %s välja"
msgid "Log Out"
msgstr "Logi välja"
msgid "Click Log Out to quit these applications and log out of the system."
msgstr ""
#, c-format
msgid "%s will be logged out automatically in %d seconds."
msgstr "%s logitakse %d sekundi pärast automaatselt välja."
#, c-format
msgid "You will be logged out automatically in %d seconds."
msgstr "Sind logitakse %d sekundi pärast automaatselt välja."
msgid "Logging out of the system."
msgstr "Süsteemist väljalogimine"
msgid "Shut Down"
msgstr "Lülita välja"
msgid "Click Shut Down to quit these applications and shut down the system."
msgstr ""
#, c-format
msgid "The system will shut down automatically in %d seconds."
msgstr "%d sekundi pärast lülitub süsteem automaatselt välja."
msgid "Shutting down the system."
msgstr "Süsteemi väljalülitamine."
msgid "Restart"
msgstr "Taaskäivita"
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
"Nende rakenduste sulgemiseks ja süsteemi taaskäivitamiseks klõpsa "
"\"Taaskäivita\"."
#, c-format
msgid "The system will restart automatically in %d seconds."
msgstr "Süsteem taaskäivitatakse automaatselt %d sekundi pärast."
msgid "Restarting the system."
msgstr "Süsteemi taaskäivitamine."
msgid "Confirm"
msgstr "Kinnita"
msgid "Cancel"
msgstr "Katkesta"
msgid "No extensions installed" msgid "No extensions installed"
msgstr "Ühtegi laiendust pole paigaldatud" msgstr "Ühtegi laiendust pole paigaldatud"
@ -337,6 +368,9 @@ msgstr "Kuva lähtekoodi"
msgid "Web Page" msgid "Web Page"
msgstr "Veebileht" msgstr "Veebileht"
msgid "System Information"
msgstr "Süsteemi andmed"
msgid "Undo" msgid "Undo"
msgstr "Võta tagasi" msgstr "Võta tagasi"
@ -351,9 +385,6 @@ msgstr "Rakendused"
msgid "Quit %s" msgid "Quit %s"
msgstr "Lõpeta %s" msgstr "Lõpeta %s"
msgid "Preferences"
msgstr "Eelistused"
#. Translators: This is the time format with date used #. Translators: This is the time format with date used
#. in 24-hour mode. #. in 24-hour mode.
msgid "%a %b %e, %R:%S" msgid "%a %b %e, %R:%S"
@ -415,10 +446,6 @@ msgstr "toggle-switch-intl"
msgid "Please enter a command:" msgid "Please enter a command:"
msgstr "Palun sisesta käsk:" msgstr "Palun sisesta käsk:"
#, c-format
msgid "Execution of '%s' failed:"
msgstr "'%s' käivitamine nurjus:"
msgid "Available" msgid "Available"
msgstr "Saadaval" msgstr "Saadaval"
@ -441,7 +468,7 @@ msgid "Log Out..."
msgstr "Logi välja..." msgstr "Logi välja..."
msgid "Suspend..." msgid "Suspend..."
msgstr "" msgstr "Peata..."
msgid "Shut Down..." msgid "Shut Down..."
msgstr "Lülita välja..." msgstr "Lülita välja..."
@ -465,7 +492,7 @@ msgid "Slow Keys"
msgstr "Aeglased klahvid" msgstr "Aeglased klahvid"
msgid "Bounce Keys" msgid "Bounce Keys"
msgstr "" msgstr "Põrkeklahvid"
msgid "Mouse Keys" msgid "Mouse Keys"
msgstr "Hiireklahvid" msgstr "Hiireklahvid"
@ -479,19 +506,110 @@ msgstr ""
msgid "Large Text" msgid "Large Text"
msgstr "" msgstr ""
msgid "Bluetooth"
msgstr "Bluetooth"
msgid "Visibility"
msgstr "Nähtavus"
msgid "Send Files to Device..."
msgstr "Failide saatmine seadmesse..."
msgid "Setup a New Device..."
msgstr ""
msgid "Bluetooth Settings"
msgstr "Bluetoothi sätted"
msgid "Connection"
msgstr "Ühendus"
msgid "Send Files..."
msgstr "Failide saatmine..."
msgid "Browse Files..."
msgstr "Failide sirvimine..."
msgid "Error browsing device"
msgstr "Viga seadme sirvimisel"
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr ""
msgid "Keyboard Settings"
msgstr "Klaviatuurisätted"
msgid "Mouse Settings"
msgstr "Hiiresätted"
msgid "Sound Settings"
msgstr "Helisätted"
msgid "Bluetooth Agent"
msgstr "Bluetoothi agent"
#, c-format
msgid "Authorization request from %s"
msgstr "Autoriseerimise päring seadmelt %s"
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "Seade %s soovib ligipääsu teenusele '%s'"
msgid "Always grant access"
msgstr "Luba alati"
msgid "Grant this time only"
msgstr "Luba ainult seekord"
msgid "Reject"
msgstr "Lükka tagasi"
#, c-format
msgid "Pairing confirmation for %s"
msgstr "Paardumise kinnitus seadmele %s"
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "Seade '%s' tahab selle arvutiga paarduda"
#, c-format
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr "Palun kontrolli, et PIN-kood '%s' kattuks seadme parooliga."
msgid "Matches"
msgstr "Kattub"
msgid "Does not match"
msgstr "Ei kattu"
#, c-format
msgid "Pairing request for %s"
msgstr "Seadmega %s paardumise päring"
msgid "Please enter the PIN mentioned on the device."
msgstr "Palun sisesta seadme poolt öeldav PIN-kood."
msgid "OK"
msgstr "Olgu"
msgid "Localization Settings"
msgstr "Lokaliseerimissätted"
msgid "Power Settings" msgid "Power Settings"
msgstr "Toitesätted..." msgstr "Toitesätted..."
#, c-format #, c-format
msgid "%d hour remaining" msgid "%d hour remaining"
msgid_plural "%d hours remaining" msgid_plural "%d hours remaining"
msgstr[0] "" msgstr[0] "jäänud %d tund"
msgstr[1] "" msgstr[1] "jäänud %d tundi"
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining" #. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#, c-format #, c-format
msgid "%d %s %d %s remaining" msgid "%d %s %d %s remaining"
msgstr "" msgstr "jäänud %d %s ja %d %s"
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
@ -506,8 +624,8 @@ msgstr[1] "minutit"
#, c-format #, c-format
msgid "%d minute remaining" msgid "%d minute remaining"
msgid_plural "%d minutes remaining" msgid_plural "%d minutes remaining"
msgstr[0] "" msgstr[0] "jäänud %d minut"
msgstr[1] "" msgstr[1] "jäänud %d minutit"
msgid "AC adapter" msgid "AC adapter"
msgstr "Võrgutoite adapter" msgstr "Võrgutoite adapter"
@ -528,7 +646,7 @@ msgid "Keyboard"
msgstr "Klaviatuur" msgstr "Klaviatuur"
msgid "PDA" msgid "PDA"
msgstr "" msgstr "Elektronmärkmik"
msgid "Cell phone" msgid "Cell phone"
msgstr "Mobiiltelefon" msgstr "Mobiiltelefon"
@ -537,7 +655,7 @@ msgid "Media player"
msgstr "Meediaesitaja" msgstr "Meediaesitaja"
msgid "Tablet" msgid "Tablet"
msgstr "" msgstr "Graafikalaud"
msgid "Computer" msgid "Computer"
msgstr "Arvuti" msgstr "Arvuti"
@ -551,9 +669,6 @@ msgstr "Helivaljus"
msgid "Microphone" msgid "Microphone"
msgstr "Mikrofon" msgstr "Mikrofon"
msgid "Sound Settings"
msgstr "Helisätted"
#, c-format #, c-format
msgid "%s is online." msgid "%s is online."
msgstr "%s on ühendatud." msgstr "%s on ühendatud."
@ -575,7 +690,7 @@ msgstr "%s on hõivatud."
#. locale, without seconds. #. locale, without seconds.
#, no-c-format #, no-c-format
msgid "Sent at %X on %A" msgid "Sent at %X on %A"
msgstr "" msgstr "Saadetud: %a, kell %X"
msgid "Search your computer" msgid "Search your computer"
msgstr "" msgstr ""
@ -661,6 +776,42 @@ msgstr "Otsing"
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s" msgstr "%1$s: %2$s"
#~ msgid "Clock"
#~ msgstr "Kell"
#~ msgid "Customize the panel clock"
#~ msgstr "Paneelikella kohandamine"
#~ msgid "Custom format of the clock"
#~ msgstr "Kellaaaja kohandatud vorming"
#~ msgid "Hour format"
#~ msgstr "Tundide vorming"
#~ msgid "Clock Format"
#~ msgstr "Kellaaja vorming"
#~ msgid "Clock Preferences"
#~ msgstr "Kella eelistused"
#~ msgid "Panel Display"
#~ msgstr "Paneelikuva"
#~ msgid "Show seco_nds"
#~ msgstr "_Sekundeid näidatakse"
#~ msgid "Show the _date"
#~ msgstr "_Kuupäeva näidatakse"
#~ msgid "_12 hour format"
#~ msgstr "_12 tunni vorming"
#~ msgid "_24 hour format"
#~ msgstr "_24 tunni vorming"
#~ msgid "Preferences"
#~ msgstr "Eelistused"
#~ msgid "Drag here to add favorites" #~ msgid "Drag here to add favorites"
#~ msgstr "Lemmikute lisamiseks lohista need siia" #~ msgstr "Lemmikute lisamiseks lohista need siia"
@ -675,6 +826,3 @@ msgstr "%1$s: %2$s"
#~ msgid "Invisible" #~ msgid "Invisible"
#~ msgstr "Nähtamatu" #~ msgstr "Nähtamatu"
#~ msgid "Account Information..."
#~ msgstr "Konto andmed..."

707
po/gl.po

File diff suppressed because it is too large Load Diff

564
po/he.po

File diff suppressed because it is too large Load Diff

466
po/it.po
View File

@ -3,13 +3,13 @@
# This file is distributed under the same license as the gnome-shell package. # This file is distributed under the same license as the gnome-shell package.
# #
# Milo Casagrande <milo@ubuntu.com>, 2009, 2010. # Milo Casagrande <milo@ubuntu.com>, 2009, 2010.
# Luca Ferretti <lferrett@gnome.org>, 2010. # Luca Ferretti <lferrett@gnome.org>, 2010, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell\n" "Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-12-20 22:54+0100\n" "POT-Creation-Date: 2011-01-29 16:06+0100\n"
"PO-Revision-Date: 2010-12-20 22:55+0100\n" "PO-Revision-Date: 2011-01-29 16:06+0100\n"
"Last-Translator: Luca Ferretti <lferrett@gnome.org>\n" "Last-Translator: Luca Ferretti <lferrett@gnome.org>\n"
"Language-Team: Italian <tp@lists.linux.it>\n" "Language-Team: Italian <tp@lists.linux.it>\n"
"Language: it\n" "Language: it\n"
@ -26,14 +26,6 @@ msgstr "GNOME Shell"
msgid "Window management and application launching" msgid "Window management and application launching"
msgstr "Gestisce finestre e avvia applicazioni" msgstr "Gestisce finestre e avvia applicazioni"
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:1
msgid "Clock"
msgstr "Orologio"
#: ../data/gnome-shell-clock-preferences.desktop.in.in.h:2
msgid "Customize the panel clock"
msgstr "Personalizza l'orologio sul pannello"
#: ../data/org.gnome.shell.gschema.xml.in.h:1 #: ../data/org.gnome.shell.gschema.xml.in.h:1
msgid "" msgid ""
"Allows access to internal debugging and monitoring tools using the Alt-F2 " "Allows access to internal debugging and monitoring tools using the Alt-F2 "
@ -43,24 +35,20 @@ msgstr ""
"utilizzando il dialogo Alt-F2." "utilizzando il dialogo Alt-F2."
#: ../data/org.gnome.shell.gschema.xml.in.h:2 #: ../data/org.gnome.shell.gschema.xml.in.h:2
msgid "Custom format of the clock"
msgstr "Formato personalizzato dell'orologio"
#: ../data/org.gnome.shell.gschema.xml.in.h:3
msgid "Enable internal tools useful for developers and testers from Alt-F2" msgid "Enable internal tools useful for developers and testers from Alt-F2"
msgstr "" msgstr ""
"Abilita gli strumenti interni utili a sviluppatori e beta-tester attraverso " "Abilita gli strumenti interni utili a sviluppatori e beta-tester attraverso "
"Alt-F2" "Alt-F2"
#: ../data/org.gnome.shell.gschema.xml.in.h:4 #: ../data/org.gnome.shell.gschema.xml.in.h:3
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "Estensione del file utilizzato per salvare lo screencast" msgstr "Estensione del file utilizzato per salvare lo screencast"
#: ../data/org.gnome.shell.gschema.xml.in.h:5 #: ../data/org.gnome.shell.gschema.xml.in.h:4
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "Framerate per la registrazione di screencast." msgstr "Framerate per la registrazione di screencast."
#: ../data/org.gnome.shell.gschema.xml.in.h:6 #: ../data/org.gnome.shell.gschema.xml.in.h:5
msgid "" msgid ""
"GNOME Shell extensions have a uuid property; this key lists extensions which " "GNOME Shell extensions have a uuid property; this key lists extensions which "
"should not be loaded." "should not be loaded."
@ -68,39 +56,28 @@ msgstr ""
"Le estensioni per la GNOME Shell dispongono di una proprietà UUID: questa " "Le estensioni per la GNOME Shell dispongono di una proprietà UUID: questa "
"chiave elenca le estensioni che non dovrebbero essere caricate." "chiave elenca le estensioni che non dovrebbero essere caricate."
#: ../data/org.gnome.shell.gschema.xml.in.h:7 #: ../data/org.gnome.shell.gschema.xml.in.h:6
msgid "History for command (Alt-F2) dialog" msgid "History for command (Alt-F2) dialog"
msgstr "Cronologia per il dialogo dei comandi (Alt-F2)" msgstr "Cronologia per il dialogo dei comandi (Alt-F2)"
#: ../data/org.gnome.shell.gschema.xml.in.h:7
msgid "If true, display date in the clock, in addition to time."
msgstr "Se VERO, mostra nell'orologio la data, oltre all'orario."
#: ../data/org.gnome.shell.gschema.xml.in.h:8 #: ../data/org.gnome.shell.gschema.xml.in.h:8
msgid "Hour format" msgid "If true, display seconds in time."
msgstr "Formato orario" msgstr "Se VERO, mostra i secondi nell'orario."
#: ../data/org.gnome.shell.gschema.xml.in.h:9 #: ../data/org.gnome.shell.gschema.xml.in.h:9
msgid "" msgid "If true, display the ISO week date in the calendar."
"If true and format is either \"12-hour\" or \"24-hour\", display date in the " msgstr "Se VERO, mostra il giorno della settimana ISO nel calendario."
"clock, in addition to time."
msgstr ""
"Se VERO e il formato è \"12-hour\" oppure \"24-hour\", visualizza anche la "
"data nell'orologio oltre all'orario."
#: ../data/org.gnome.shell.gschema.xml.in.h:10 #: ../data/org.gnome.shell.gschema.xml.in.h:10
msgid ""
"If true and format is either \"12-hour\" or \"24-hour\", display seconds in "
"time."
msgstr ""
"Se VERO e il formato è \"12-hour\" oppure \"24-hour\", visualizza i secondi "
"nell'ora."
#: ../data/org.gnome.shell.gschema.xml.in.h:11
msgid "If true, display the ISO week date in the calendar."
msgstr "Se VERO, visualizza il giorno della settimana ISO nel calendario."
#: ../data/org.gnome.shell.gschema.xml.in.h:12
msgid "List of desktop file IDs for favorite applications" msgid "List of desktop file IDs for favorite applications"
msgstr "Elenco di ID di file desktop per le applicazioni preferite" msgstr "Elenco di ID di file desktop per le applicazioni preferite"
#: ../data/org.gnome.shell.gschema.xml.in.h:13 #: ../data/org.gnome.shell.gschema.xml.in.h:12
#, fuzzy, no-c-format
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
"used for gst-launch. The pipeline should have an unconnected sink pad where " "used for gst-launch. The pipeline should have an unconnected sink pad where "
@ -109,7 +86,9 @@ msgid ""
"pipeline can also take care of its own output - this might be used to send " "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 " "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 " "to an empty value, the default pipeline will be used. This is currently "
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora." "'videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux' and "
"records to WEBM using the VP8 codec. %T is used as a placeholder for a guess "
"at the optimal thread count on the system."
msgstr "" msgstr ""
"Imposta la pipeline di GStreamer utilizzata per codificare le registrazioni, " "Imposta la pipeline di GStreamer utilizzata per codificare le registrazioni, "
"seguendo la sintassi di gst-launch. La pipeline dovrebbe disporre di un sink " "seguendo la sintassi di gst-launch. La pipeline dovrebbe disporre di un sink "
@ -121,19 +100,19 @@ msgstr ""
"alcun valore, viene usata la pipeline predefinita il cui valore è " "alcun valore, viene usata la pipeline predefinita il cui valore è "
"\"videorate ! theoraenc ! oggmux\" e che registra nel formato Ogg Theora." "\"videorate ! theoraenc ! oggmux\" e che registra nel formato Ogg Theora."
#: ../data/org.gnome.shell.gschema.xml.in.h:14 #: ../data/org.gnome.shell.gschema.xml.in.h:13
msgid "Show date in clock" msgid "Show date in clock"
msgstr "Mostra la data nell'orologio" msgstr "Mostra la data nell'orologio"
#: ../data/org.gnome.shell.gschema.xml.in.h:15 #: ../data/org.gnome.shell.gschema.xml.in.h:14
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "Mostra il giorno della settimana nel calendario" msgstr "Mostra il giorno della settimana nel calendario"
#: ../data/org.gnome.shell.gschema.xml.in.h:16 #: ../data/org.gnome.shell.gschema.xml.in.h:15
msgid "Show time with seconds" msgid "Show time with seconds"
msgstr "Mostra l'ora con i secondi" msgstr "Mostra l'ora con i secondi"
#: ../data/org.gnome.shell.gschema.xml.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.h:16
msgid "" msgid ""
"The applications corresponding to these identifiers will be displayed in the " "The applications corresponding to these identifiers will be displayed in the "
"favorites area." "favorites area."
@ -141,7 +120,7 @@ msgstr ""
"Le applicazioni che corrispondono a questi identificatori vengono " "Le applicazioni che corrispondono a questi identificatori vengono "
"visualizzate nell'area dei preferiti." "visualizzate nell'area dei preferiti."
#: ../data/org.gnome.shell.gschema.xml.in.h:18 #: ../data/org.gnome.shell.gschema.xml.in.h:17
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
@ -151,7 +130,7 @@ msgstr ""
"data corrente e utilizza questa estensione. Dovrebbe essere modificato " "data corrente e utilizza questa estensione. Dovrebbe essere modificato "
"quando si registra utilizzando un diverso formato contenitore." "quando si registra utilizzando un diverso formato contenitore."
#: ../data/org.gnome.shell.gschema.xml.in.h:19 #: ../data/org.gnome.shell.gschema.xml.in.h:18
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
@ -159,12 +138,12 @@ msgstr ""
"Il framerate in fotogrammi al secondo dello screencast registrato attraverso " "Il framerate in fotogrammi al secondo dello screencast registrato attraverso "
"il registratore della GNOME Shell." "il registratore della GNOME Shell."
#: ../data/org.gnome.shell.gschema.xml.in.h:20 #: ../data/org.gnome.shell.gschema.xml.in.h:19
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "La pipeline di gstreamer utilizzata per codificare lo screencast" msgstr "La pipeline di gstreamer utilizzata per codificare lo screencast"
# (ndt) quel "in launchers" non mi convince... # (ndt) quel "in launchers" non mi convince...
#: ../data/org.gnome.shell.gschema.xml.in.h:21 #: ../data/org.gnome.shell.gschema.xml.in.h:20
msgid "" msgid ""
"The shell normally monitors active applications in order to present the most " "The shell normally monitors active applications in order to present the most "
"used ones (e.g. in launchers). While this data will be kept private, you may " "used ones (e.g. in launchers). While this data will be kept private, you may "
@ -176,44 +155,19 @@ msgstr ""
"disabilitare questa funzionalità per motivi di privacy. I dati già salvati " "disabilitare questa funzionalità per motivi di privacy. I dati già salvati "
"non verranno comunque rimossi." "non verranno comunque rimossi."
#: ../data/org.gnome.shell.gschema.xml.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.h:21
msgid ""
"This key specifies the format used by the panel clock when the format key is "
"set to \"custom\". You can use conversion specifiers understood by strftime"
"() to obtain a specific format. See the strftime() manual for more "
"information."
msgstr ""
"Questa chiave indica il formato usato dall'orologio nel pannello quando la "
"chiave specifica è impostata a \"custom\". È possibile utilizzare gli "
"specificatori di formato compatibili con strftime(). Per maggiori "
"informazioni, consultare il manuale di strftime()."
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid ""
"This key specifies the hour format used by the panel clock. Possible values "
"are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", "
"the clock will display time in seconds since Epoch, i.e. 1970-01-01. If set "
"to \"custom\", the clock will display time according to the format specified "
"in the custom_format key. Note that if set to either \"unix\" or \"custom\", "
"the show_date and show_seconds keys are ignored."
msgstr ""
"Questa chiave indica il formato orario usato dall'orologio. I possibili "
"valori sono \"12-hour\", \"24-hour\", \"unix\" e \"custom\". Se impostata a "
"\"unix\", l'orologio visualizza l'ora in secondi a partire dall'era Epoch, "
"cioè dal 1970-01-01. Se impostata a \"custom\", l'orologio visualizza l'ora "
"in base al formato specificato nella chiave custom_format. Notare che se "
"impostata a \"unix\" o \"custom\", le chiavi show_date e show_seconds non "
"vengono considerate."
#: ../data/org.gnome.shell.gschema.xml.in.h:24
msgid "Uuids of extensions to disable" msgid "Uuids of extensions to disable"
msgstr "UUID delle estensioni da disabilitare" msgstr "UUID delle estensioni da disabilitare"
#: ../data/org.gnome.shell.gschema.xml.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.h:22
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
msgstr "" msgstr ""
"Indica se raccogliere statistiche riguardo l'utilizzo delle applicazioni" "Indica se raccogliere statistiche riguardo l'utilizzo delle applicazioni"
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "disabled OpenSearch providers"
msgstr ""
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1 #: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:1
msgid "Clip the crosshairs at the center" msgid "Clip the crosshairs at the center"
msgstr "" msgstr ""
@ -339,55 +293,47 @@ msgstr ""
msgid "Width of the vertical and horizontal lines that make up the crosshairs." msgid "Width of the vertical and horizontal lines that make up the crosshairs."
msgstr "" msgstr ""
#: ../data/clock-preferences.ui.h:1 #: ../js/misc/util.js:86
msgid "Clock Format" msgid "Command not found"
msgstr "Formato ora" msgstr ""
#: ../data/clock-preferences.ui.h:2 #. Replace "Error invoking GLib.shell_parse_argv: " with
msgid "Clock Preferences" #. something nicer
msgstr "Preferenze di Orologio" #: ../js/misc/util.js:113
msgid "Could not parse command:"
msgstr "Impossibile analizzare il comando:"
#: ../data/clock-preferences.ui.h:3 #: ../js/misc/util.js:135
msgid "Panel Display" msgid "No such application"
msgstr "Visualizzazione sul pannello" msgstr "Applicazione inesistente"
#: ../data/clock-preferences.ui.h:4 #: ../js/misc/util.js:148
msgid "Show seco_nds" #, c-format
msgstr "Mostrare i _secondi" msgid "Execution of '%s' failed:"
msgstr "Esecuzione di «%s» non riuscita:"
#: ../data/clock-preferences.ui.h:5 #. Translators: Filter to display all applications
msgid "Show the _date" #: ../js/ui/appDisplay.js:164
msgstr "Mostrare la _data"
#: ../data/clock-preferences.ui.h:6
msgid "_12 hour format"
msgstr "Formato _12 ore"
#: ../data/clock-preferences.ui.h:7
msgid "_24 hour format"
msgstr "Formato _24 ore"
#: ../js/ui/appDisplay.js:154
msgid "All" msgid "All"
msgstr "Tutte" msgstr "Tutte"
#: ../js/ui/appDisplay.js:235 #: ../js/ui/appDisplay.js:245
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "APPLICAZIONI" msgstr "APPLICAZIONI"
#: ../js/ui/appDisplay.js:265 #: ../js/ui/appDisplay.js:275
msgid "PREFERENCES" msgid "PREFERENCES"
msgstr "PREFERENZE" msgstr "PREFERENZE"
#: ../js/ui/appDisplay.js:562 #: ../js/ui/appDisplay.js:572
msgid "New Window" msgid "New Window"
msgstr "Nuova finestra" msgstr "Nuova finestra"
#: ../js/ui/appDisplay.js:566 #: ../js/ui/appDisplay.js:576
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Rimuovi dai preferiti" msgstr "Rimuovi dai preferiti"
#: ../js/ui/appDisplay.js:567 #: ../js/ui/appDisplay.js:577
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Aggiungi ai preferiti" msgstr "Aggiungi ai preferiti"
@ -407,128 +353,205 @@ msgstr "%s è stato rimosso dai preferiti."
msgid "Remove" msgid "Remove"
msgstr "Rimuovi" msgstr "Rimuovi"
#: ../js/ui/docDisplay.js:494 #: ../js/ui/docDisplay.js:18
msgid "RECENT ITEMS" msgid "RECENT ITEMS"
msgstr "Elementi recenti" msgstr "ELEMENTI RECENTI"
#: ../js/ui/lookingGlass.js:552 #: ../js/ui/endSessionDialog.js:63
#, c-format
msgid "Log Out %s"
msgstr "Termina sessione di %s"
#: ../js/ui/endSessionDialog.js:64 ../js/ui/endSessionDialog.js:69
msgid "Log Out"
msgstr "Termina sessione"
# oddio... abbandonare il sistema sembra la nave che affonda... (LF)
#: ../js/ui/endSessionDialog.js:65
msgid "Click Log Out to quit these applications and log out of the system."
msgstr ""
"Fare clic su «Termina sessione» per chiudere queste applicazioni e "
"abbandonare il sistema."
#: ../js/ui/endSessionDialog.js:66
#, c-format
msgid "%s will be logged out automatically in %d seconds."
msgstr "La sessione di %s verrà terminata automaticamente tra %d secondi."
#: ../js/ui/endSessionDialog.js:67
#, c-format
msgid "You will be logged out automatically in %d seconds."
msgstr "La sessione verrà terminata automaticamente tra %d secondi."
#: ../js/ui/endSessionDialog.js:68
msgid "Logging out of the system."
msgstr "Chiusura della sessione."
#: ../js/ui/endSessionDialog.js:74 ../js/ui/endSessionDialog.js:78
msgid "Shut Down"
msgstr "Arresta"
# usato un termine diverso, magari si capisce meglio (LF)
#: ../js/ui/endSessionDialog.js:75
msgid "Click Shut Down to quit these applications and shut down the system."
msgstr ""
"Fare clic su «Arresta» per chiudere queste applicazioni e spegnere il "
"sistema."
#: ../js/ui/endSessionDialog.js:76
#, c-format
msgid "The system will shut down automatically in %d seconds."
msgstr "Il sistema verrà arrestato automaticamente tra %d secondi."
#: ../js/ui/endSessionDialog.js:77
msgid "Shutting down the system."
msgstr "Arresto del sistema."
#: ../js/ui/endSessionDialog.js:84 ../js/ui/endSessionDialog.js:88
msgid "Restart"
msgstr "Riavvia"
#: ../js/ui/endSessionDialog.js:85
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
"Fare clic su «Riavvia» per chiudere queste applicazioni e riavviare il "
"sistema."
#: ../js/ui/endSessionDialog.js:86
#, c-format
msgid "The system will restart automatically in %d seconds."
msgstr "Il sistema verrà riavviato automaticamente tra %d secondi."
#: ../js/ui/endSessionDialog.js:87
msgid "Restarting the system."
msgstr "Riavvio del sistema."
#: ../js/ui/endSessionDialog.js:395
msgid "Confirm"
msgstr "Conferma"
#: ../js/ui/endSessionDialog.js:400 ../js/ui/status/bluetooth.js:470
msgid "Cancel"
msgstr "Annulla"
#: ../js/ui/lookingGlass.js:556
msgid "No extensions installed" msgid "No extensions installed"
msgstr "Nessuna estensione installata" msgstr "Nessuna estensione installata"
# (ndt) o abilitata? # (ndt) o abilitata?
#: ../js/ui/lookingGlass.js:589 #: ../js/ui/lookingGlass.js:593
msgid "Enabled" msgid "Enabled"
msgstr "Abilitato" msgstr "Abilitato"
# (ndt) o disabilitata? # (ndt) o disabilitata?
#. translators: #. translators:
#. * The device has been disabled #. * The device has been disabled
#: ../js/ui/lookingGlass.js:591 ../src/gvc/gvc-mixer-control.c:1087 #: ../js/ui/lookingGlass.js:595 ../src/gvc/gvc-mixer-control.c:1087
msgid "Disabled" msgid "Disabled"
msgstr "Disabilitato" msgstr "Disabilitato"
#: ../js/ui/lookingGlass.js:593 #: ../js/ui/lookingGlass.js:597
msgid "Error" msgid "Error"
msgstr "Errore" msgstr "Errore"
#: ../js/ui/lookingGlass.js:595 #: ../js/ui/lookingGlass.js:599
msgid "Out of date" msgid "Out of date"
msgstr "Non aggiornato" msgstr "Non aggiornato"
#: ../js/ui/lookingGlass.js:620 #: ../js/ui/lookingGlass.js:624
msgid "View Source" msgid "View Source"
msgstr "Visualizza sorgente" msgstr "Visualizza sorgente"
#: ../js/ui/lookingGlass.js:626 #: ../js/ui/lookingGlass.js:630
msgid "Web Page" msgid "Web Page"
msgstr "Pagina web" msgstr "Pagina web"
#: ../js/ui/overview.js:96 #: ../js/ui/messageTray.js:1778
msgid "System Information"
msgstr "Informazione di sistema"
#: ../js/ui/overview.js:88
msgid "Undo" msgid "Undo"
msgstr "Annulla" msgstr "Annulla"
#: ../js/ui/overview.js:158 #: ../js/ui/overview.js:159
msgid "Windows" msgid "Windows"
msgstr "Finestra" msgstr "Finestre"
#: ../js/ui/overview.js:161 #: ../js/ui/overview.js:162
msgid "Applications" msgid "Applications"
msgstr "Applicazioni" msgstr "Applicazioni"
#. TODO - _quit() doesn't really work on apps in state STARTING yet #. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:474 #: ../js/ui/panel.js:483
#, c-format #, c-format
msgid "Quit %s" msgid "Quit %s"
msgstr "Chiudi %s" msgstr "Chiudi %s"
#: ../js/ui/panel.js:499
msgid "Preferences"
msgstr "Preferenze"
#. Translators: This is the time format with date used #. Translators: This is the time format with date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:585 #: ../js/ui/panel.js:568
msgid "%a %b %e, %R:%S" msgid "%a %b %e, %R:%S"
msgstr "%a %e %b, %k.%M.%S" msgstr "%a %e %b, %k.%M.%S"
# (ndt) proviamo col k, se non funge, sappiamo il perché... # (ndt) proviamo col k, se non funge, sappiamo il perché...
#: ../js/ui/panel.js:586 #: ../js/ui/panel.js:569
msgid "%a %b %e, %R" msgid "%a %b %e, %R"
msgstr "%a %e %b, %k.%M" msgstr "%a %e %b, %k.%M"
#. Translators: This is the time format without date used #. Translators: This is the time format without date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:590 #: ../js/ui/panel.js:573
msgid "%a %R:%S" msgid "%a %R:%S"
msgstr "%a %k.%M.%S" msgstr "%a %k.%M.%S"
#: ../js/ui/panel.js:591 #: ../js/ui/panel.js:574
msgid "%a %R" msgid "%a %R"
msgstr "%a %k.%M" msgstr "%a %k.%M"
#. Translators: This is a time format with date used #. Translators: This is a time format with date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:598 #: ../js/ui/panel.js:581
msgid "%a %b %e, %l:%M:%S %p" msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %e %b, %l.%M.%S %P" msgstr "%a %e %b, %l.%M.%S %P"
#: ../js/ui/panel.js:599 #: ../js/ui/panel.js:582
msgid "%a %b %e, %l:%M %p" msgid "%a %b %e, %l:%M %p"
msgstr "%a %e %b, %l.%M %P" msgstr "%a %e %b, %l.%M %P"
#. Translators: This is a time format without date used #. Translators: This is a time format without date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:603 #: ../js/ui/panel.js:586
msgid "%a %l:%M:%S %p" msgid "%a %l:%M:%S %p"
msgstr "%a %l.%M.%S %P" msgstr "%a %l.%M.%S %P"
#: ../js/ui/panel.js:604 #: ../js/ui/panel.js:587
msgid "%a %l:%M %p" msgid "%a %l:%M %p"
msgstr "%a %l.%M %P" msgstr "%a %l.%M %P"
#. Button on the left side of the panel. #. 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". #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:749 #: ../js/ui/panel.js:732
msgid "Activities" msgid "Activities"
msgstr "Attività" msgstr "Attività"
# (ndt) libera, ma unmount non si può proprio vedere... # (ndt) libera, ma unmount non si può proprio vedere...
#: ../js/ui/placeDisplay.js:111 #: ../js/ui/placeDisplay.js:106
#, c-format #, c-format
msgid "Failed to unmount '%s'" msgid "Failed to unmount '%s'"
msgstr "Impossibile scollegare «%s»" msgstr "Impossibile scollegare «%s»"
#: ../js/ui/placeDisplay.js:114 #: ../js/ui/placeDisplay.js:109
msgid "Retry" msgid "Retry"
msgstr "Riprova" msgstr "Riprova"
#: ../js/ui/placeDisplay.js:159 #: ../js/ui/placeDisplay.js:150
msgid "Connect to..." msgid "Connect to..."
msgstr "Connetti a..." msgstr "Connetti a..."
#: ../js/ui/placeDisplay.js:558 #: ../js/ui/placeDisplay.js:386
msgid "PLACES & DEVICES" msgid "PLACES & DEVICES"
msgstr "Risorse e dispositivi" msgstr "RISORSE E DISPOSITIVI"
#. Translators: this MUST be either "toggle-switch-us" #. Translators: this MUST be either "toggle-switch-us"
#. (for toggle switches containing the English words #. (for toggle switches containing the English words
@ -537,86 +560,81 @@ msgstr "Risorse e dispositivi"
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:33 #: ../js/ui/popupMenu.js:33
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-us"
#: ../js/ui/runDialog.js:233 #: ../js/ui/runDialog.js:209
msgid "Please enter a command:" msgid "Please enter a command:"
msgstr "Inserire un comando:" msgstr "Inserire un comando:"
#: ../js/ui/runDialog.js:378 #: ../js/ui/statusMenu.js:102
#, c-format
msgid "Execution of '%s' failed:"
msgstr "Esecuzione di «%s» non riuscita:"
#: ../js/ui/statusMenu.js:101
msgid "Available" msgid "Available"
msgstr "Disponibile" msgstr "Disponibile"
#: ../js/ui/statusMenu.js:106 #: ../js/ui/statusMenu.js:107
msgid "Busy" msgid "Busy"
msgstr "Non disponibile" msgstr "Non disponibile"
#: ../js/ui/statusMenu.js:114 #: ../js/ui/statusMenu.js:115
msgid "My Account" msgid "My Account"
msgstr "Account personale" msgstr "Account personale"
#: ../js/ui/statusMenu.js:118 #: ../js/ui/statusMenu.js:119
msgid "System Settings" msgid "System Settings"
msgstr "Impostazioni di sistema" msgstr "Impostazioni di sistema"
#: ../js/ui/statusMenu.js:125 #: ../js/ui/statusMenu.js:126
msgid "Lock Screen" msgid "Lock Screen"
msgstr "Blocca schermo" msgstr "Blocca schermo"
#: ../js/ui/statusMenu.js:129 #: ../js/ui/statusMenu.js:130
msgid "Switch User" msgid "Switch User"
msgstr "Cambia utente" msgstr "Cambia utente"
#: ../js/ui/statusMenu.js:134 #: ../js/ui/statusMenu.js:135
msgid "Log Out..." msgid "Log Out..."
msgstr "Termina sessione..." msgstr "Termina sessione..."
#: ../js/ui/statusMenu.js:141 #: ../js/ui/statusMenu.js:142
msgid "Suspend..." msgid "Suspend..."
msgstr "Sospendi..." msgstr "Sospendi..."
#: ../js/ui/statusMenu.js:145 #: ../js/ui/statusMenu.js:146
msgid "Shut Down..." msgid "Shut Down..."
msgstr "Arresta..." msgstr "Arresta..."
#: ../js/ui/status/accessibility.js:82 #: ../js/ui/status/accessibility.js:83
msgid "Zoom" msgid "Zoom"
msgstr "Ingrandimento" msgstr "Ingrandimento"
#: ../js/ui/status/accessibility.js:88 #: ../js/ui/status/accessibility.js:89
msgid "Screen Reader" msgid "Screen Reader"
msgstr "Lettore schermo" msgstr "Lettore schermo"
#: ../js/ui/status/accessibility.js:91 #: ../js/ui/status/accessibility.js:92
msgid "Screen Keyboard" msgid "Screen Keyboard"
msgstr "Tastiera a schermo" msgstr "Tastiera a schermo"
#: ../js/ui/status/accessibility.js:94 #: ../js/ui/status/accessibility.js:95
msgid "Visual Alerts" msgid "Visual Alerts"
msgstr "Allerte visive" msgstr "Allerte visive"
#: ../js/ui/status/accessibility.js:97 #: ../js/ui/status/accessibility.js:98
msgid "Sticky Keys" msgid "Sticky Keys"
msgstr "Permanenza tasti" msgstr "Permanenza tasti"
#: ../js/ui/status/accessibility.js:100 #: ../js/ui/status/accessibility.js:101
msgid "Slow Keys" msgid "Slow Keys"
msgstr "Rallentamento tasti" msgstr "Rallentamento tasti"
#: ../js/ui/status/accessibility.js:103 #: ../js/ui/status/accessibility.js:104
msgid "Bounce Keys" msgid "Bounce Keys"
msgstr "Pressione ravvicinata tasti" msgstr "Pressione ravvicinata tasti"
#: ../js/ui/status/accessibility.js:106 #: ../js/ui/status/accessibility.js:107
msgid "Mouse Keys" msgid "Mouse Keys"
msgstr "Mouse da tastiera" msgstr "Mouse da tastiera"
#: ../js/ui/status/accessibility.js:110 #: ../js/ui/status/accessibility.js:111
msgid "Universal Access Settings" msgid "Universal Access Settings"
msgstr "Impostazioni accesso universale" msgstr "Impostazioni accesso universale"
@ -628,7 +646,7 @@ msgstr "Contrasto elevato"
msgid "Large Text" msgid "Large Text"
msgstr "Caratteri grandi" msgstr "Caratteri grandi"
#: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:200 #: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:241
msgid "Bluetooth" msgid "Bluetooth"
msgstr "Bluetooth" msgstr "Bluetooth"
@ -637,119 +655,119 @@ msgstr "Bluetooth"
msgid "Visibility" msgid "Visibility"
msgstr "Rilevabile" msgstr "Rilevabile"
#: ../js/ui/status/bluetooth.js:68 #: ../js/ui/status/bluetooth.js:69
msgid "Send Files to Device..." msgid "Send Files to Device..."
msgstr "Invia file al dispositivo..." msgstr "Invia file al dispositivo..."
#: ../js/ui/status/bluetooth.js:71 #: ../js/ui/status/bluetooth.js:70
msgid "Setup a New Device..." msgid "Setup a New Device..."
msgstr "Imposta un nuovo dispositivo..." msgstr "Imposta un nuovo dispositivo..."
#: ../js/ui/status/bluetooth.js:94 #: ../js/ui/status/bluetooth.js:95
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "Impostazioni Bluetooth" msgstr "Impostazioni Bluetooth"
# indica lo stato del device BT, per esempio gli auricolari # indica lo stato del device BT, per esempio gli auricolari
# credo sia meglio l'aggettivo che il sostantivo # credo sia meglio l'aggettivo che il sostantivo
#: ../js/ui/status/bluetooth.js:151 #: ../js/ui/status/bluetooth.js:192
msgid "Connection" msgid "Connection"
msgstr "Collegato" msgstr "Collegato"
#: ../js/ui/status/bluetooth.js:187 #: ../js/ui/status/bluetooth.js:228
msgid "Send Files..." msgid "Send Files..."
msgstr "Invia file..." msgstr "Invia file..."
#: ../js/ui/status/bluetooth.js:192 #: ../js/ui/status/bluetooth.js:233
msgid "Browse Files..." msgid "Browse Files..."
msgstr "Esplora file..." msgstr "Esplora file..."
#: ../js/ui/status/bluetooth.js:201 #: ../js/ui/status/bluetooth.js:242
msgid "Error browsing device" msgid "Error browsing device"
msgstr "Errore nell'esplorare il dispositivo" msgstr "Errore nell'esplorare il dispositivo"
#: ../js/ui/status/bluetooth.js:202 #: ../js/ui/status/bluetooth.js:243
#, c-format #, c-format
msgid "The requested device cannot be browsed, error is '%s'" msgid "The requested device cannot be browsed, error is '%s'"
msgstr "Non è possibile esplorare il dispositivo richiesto, l'errore è «%s»" msgstr "Non è possibile esplorare il dispositivo richiesto, l'errore è «%s»"
#: ../js/ui/status/bluetooth.js:210 #: ../js/ui/status/bluetooth.js:251
msgid "Keyboard Settings" msgid "Keyboard Settings"
msgstr "Impostazioni tastiera" msgstr "Impostazioni tastiera"
#: ../js/ui/status/bluetooth.js:215 #: ../js/ui/status/bluetooth.js:256
msgid "Mouse Settings" msgid "Mouse Settings"
msgstr "Impostazioni mouse" msgstr "Impostazioni mouse"
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/volume.js:62 #: ../js/ui/status/bluetooth.js:263 ../js/ui/status/volume.js:63
msgid "Sound Settings" msgid "Sound Settings"
msgstr "Impostazioni audio" msgstr "Impostazioni audio"
#: ../js/ui/status/bluetooth.js:293 ../js/ui/status/bluetooth.js:327 #: ../js/ui/status/bluetooth.js:337 ../js/ui/status/bluetooth.js:371
#: ../js/ui/status/bluetooth.js:367 ../js/ui/status/bluetooth.js:400 #: ../js/ui/status/bluetooth.js:411 ../js/ui/status/bluetooth.js:444
msgid "Bluetooth Agent" msgid "Bluetooth Agent"
msgstr "" msgstr ""
#: ../js/ui/status/bluetooth.js:328 #: ../js/ui/status/bluetooth.js:372
#, c-format #, c-format
msgid "Authorization request from %s" msgid "Authorization request from %s"
msgstr "Richesta autorizzazione da %s" msgstr "Richesta autorizzazione da %s"
#: ../js/ui/status/bluetooth.js:334 #: ../js/ui/status/bluetooth.js:378
#, c-format #, c-format
msgid "Device %s wants access to the service '%s'" msgid "Device %s wants access to the service '%s'"
msgstr "Il dispositivo %s vuole accedere al servizio «%s»" msgstr "Il dispositivo %s vuole accedere al servizio «%s»"
#: ../js/ui/status/bluetooth.js:336 #: ../js/ui/status/bluetooth.js:380
msgid "Always grant access" msgid "Always grant access"
msgstr "Consenti sempre accesso" msgstr "Consenti sempre accesso"
#: ../js/ui/status/bluetooth.js:337 #: ../js/ui/status/bluetooth.js:381
msgid "Grant this time only" msgid "Grant this time only"
msgstr "Consenti solo stavolta" msgstr "Consenti solo stavolta"
#: ../js/ui/status/bluetooth.js:338 #: ../js/ui/status/bluetooth.js:382
msgid "Reject" msgid "Reject"
msgstr "Rifiuta" msgstr "Rifiuta"
#: ../js/ui/status/bluetooth.js:368 #: ../js/ui/status/bluetooth.js:412
#, c-format #, c-format
msgid "Pairing confirmation for %s" msgid "Pairing confirmation for %s"
msgstr "Conferma associazione per %s" msgstr "Conferma associazione per %s"
#: ../js/ui/status/bluetooth.js:374 ../js/ui/status/bluetooth.js:408 #: ../js/ui/status/bluetooth.js:418 ../js/ui/status/bluetooth.js:452
#, c-format #, c-format
msgid "Device %s wants to pair with this computer" msgid "Device %s wants to pair with this computer"
msgstr "Il dispositivo %s vuole associarsi con questo computer" msgstr "Il dispositivo %s vuole associarsi con questo computer"
#: ../js/ui/status/bluetooth.js:375 #: ../js/ui/status/bluetooth.js:419
#, c-format #, c-format
msgid "Please confirm whether the PIN '%s' matches the one on the device." msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr "Confermare la corrispondenza del PIN «%s» con quello sul dispositivo." msgstr "Confermare la corrispondenza del PIN «%s» con quello sul dispositivo."
#: ../js/ui/status/bluetooth.js:377 #: ../js/ui/status/bluetooth.js:421
msgid "Matches" msgid "Matches"
msgstr "Corrisponde" msgstr "Corrisponde"
#: ../js/ui/status/bluetooth.js:378 #: ../js/ui/status/bluetooth.js:422
msgid "Does not match" msgid "Does not match"
msgstr "Non corrisponde" msgstr "Non corrisponde"
#: ../js/ui/status/bluetooth.js:401 #: ../js/ui/status/bluetooth.js:445
#, c-format #, c-format
msgid "Pairing request for %s" msgid "Pairing request for %s"
msgstr "Richiesta associazione per %s" msgstr "Richiesta associazione per %s"
#: ../js/ui/status/bluetooth.js:409 #: ../js/ui/status/bluetooth.js:453
msgid "Please enter the PIN mentioned on the device." msgid "Please enter the PIN mentioned on the device."
msgstr "Inserire il PIN indicato sul dispositivo." msgstr "Inserire il PIN indicato sul dispositivo."
#: ../js/ui/status/bluetooth.js:425 #: ../js/ui/status/bluetooth.js:469
msgid "OK" msgid "OK"
msgstr "OK" msgstr "OK"
#: ../js/ui/status/bluetooth.js:426 #: ../js/ui/status/keyboard.js:78
msgid "Cancel" msgid "Localization Settings"
msgstr "Annulla" msgstr "Impostazioni localizzazione"
#: ../js/ui/status/power.js:85 #: ../js/ui/status/power.js:85
msgid "Power Settings" msgid "Power Settings"
@ -787,79 +805,79 @@ msgid_plural "%d minutes remaining"
msgstr[0] "%d minuto rimanente" msgstr[0] "%d minuto rimanente"
msgstr[1] "%d minuti rimanenti" msgstr[1] "%d minuti rimanenti"
#: ../js/ui/status/power.js:237 #: ../js/ui/status/power.js:235
msgid "AC adapter" msgid "AC adapter"
msgstr "Alimentatore di corrente" msgstr "Alimentatore di corrente"
#: ../js/ui/status/power.js:239 #: ../js/ui/status/power.js:237
msgid "Laptop battery" msgid "Laptop battery"
msgstr "Batteria del portatile" msgstr "Batteria del portatile"
#: ../js/ui/status/power.js:241 #: ../js/ui/status/power.js:239
msgid "UPS" msgid "UPS"
msgstr "UPS" msgstr "UPS"
#: ../js/ui/status/power.js:243 #: ../js/ui/status/power.js:241
msgid "Monitor" msgid "Monitor"
msgstr "Monitor" msgstr "Monitor"
#: ../js/ui/status/power.js:245 #: ../js/ui/status/power.js:243
msgid "Mouse" msgid "Mouse"
msgstr "Mouse" msgstr "Mouse"
#: ../js/ui/status/power.js:247 #: ../js/ui/status/power.js:245
msgid "Keyboard" msgid "Keyboard"
msgstr "Tastiera" msgstr "Tastiera"
#: ../js/ui/status/power.js:249 #: ../js/ui/status/power.js:247
msgid "PDA" msgid "PDA"
msgstr "PDS" msgstr "PDS"
# c'era una discussione su tp... # c'era una discussione su tp...
#: ../js/ui/status/power.js:251 #: ../js/ui/status/power.js:249
msgid "Cell phone" msgid "Cell phone"
msgstr "Cellulare" msgstr "Cellulare"
#: ../js/ui/status/power.js:253 #: ../js/ui/status/power.js:251
msgid "Media player" msgid "Media player"
msgstr "Lettore multimediale" msgstr "Lettore multimediale"
#: ../js/ui/status/power.js:255 #: ../js/ui/status/power.js:253
msgid "Tablet" msgid "Tablet"
msgstr "Tablet" msgstr "Tablet"
#: ../js/ui/status/power.js:257 #: ../js/ui/status/power.js:255
msgid "Computer" msgid "Computer"
msgstr "Computer" msgstr "Computer"
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012 #: ../js/ui/status/power.js:257 ../src/shell-app-system.c:1012
msgid "Unknown" msgid "Unknown"
msgstr "Sconosciuto" msgstr "Sconosciuto"
#: ../js/ui/status/volume.js:41 #: ../js/ui/status/volume.js:42
msgid "Volume" msgid "Volume"
msgstr "Volume" msgstr "Volume"
#: ../js/ui/status/volume.js:54 #: ../js/ui/status/volume.js:55
msgid "Microphone" msgid "Microphone"
msgstr "Microfono" msgstr "Microfono"
#: ../js/ui/telepathyClient.js:560 #: ../js/ui/telepathyClient.js:561
#, c-format #, c-format
msgid "%s is online." msgid "%s is online."
msgstr "%s è disponibile." msgstr "%s è disponibile."
#: ../js/ui/telepathyClient.js:565 #: ../js/ui/telepathyClient.js:566
#, c-format #, c-format
msgid "%s is offline." msgid "%s is offline."
msgstr "%s è fuori rete." msgstr "%s è fuori rete."
#: ../js/ui/telepathyClient.js:568 #: ../js/ui/telepathyClient.js:569
#, c-format #, c-format
msgid "%s is away." msgid "%s is away."
msgstr "%s è assente." msgstr "%s è assente."
#: ../js/ui/telepathyClient.js:571 #: ../js/ui/telepathyClient.js:572
#, c-format #, c-format
msgid "%s is busy." msgid "%s is busy."
msgstr "%s non è disponibile." msgstr "%s non è disponibile."
@ -867,10 +885,10 @@ msgstr "%s non è disponibile."
#. Translators: this is a time format string followed by a date. #. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your #. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds. #. locale, without seconds.
#: ../js/ui/telepathyClient.js:664 #: ../js/ui/telepathyClient.js:666
#, no-c-format #, no-c-format
msgid "Sent at %X on %A" msgid "Sent at %X on %A"
msgstr "Inviato alle %-H.%M.%S di %A" msgstr "Inviato alle %-H.%M di %A"
# FIXME ma ha senso in inglese??? # FIXME ma ha senso in inglese???
#: ../js/ui/viewSelector.js:26 #: ../js/ui/viewSelector.js:26
@ -889,14 +907,14 @@ msgid "'%s' is ready"
msgstr "«%s» è pronto" msgstr "«%s» è pronto"
# (ndt) un po' liberetta... # (ndt) un po' liberetta...
#: ../js/ui/workspacesView.js:244 #: ../js/ui/workspacesView.js:243
msgid "" msgid ""
"Can't add a new workspace because maximum workspaces limit has been reached." "Can't add a new workspace because maximum workspaces limit has been reached."
msgstr "" msgstr ""
"Impossibile aggiungere un nuovo spazio di lavoro: raggiunto il limite " "Impossibile aggiungere un nuovo spazio di lavoro: raggiunto il limite "
"massimo consentito." "massimo consentito."
#: ../js/ui/workspacesView.js:260 #: ../js/ui/workspacesView.js:259
msgid "Can't remove the first workspace." msgid "Can't remove the first workspace."
msgstr "Impossibile rimuovere il primo spazio di lavoro." msgstr "Impossibile rimuovere il primo spazio di lavoro."
@ -922,32 +940,32 @@ msgstr[1] "%u ingressi"
msgid "System Sounds" msgid "System Sounds"
msgstr "Audio di sistema" msgstr "Audio di sistema"
#: ../src/shell-global.c:1155 #: ../src/shell-global.c:1365
msgid "Less than a minute ago" msgid "Less than a minute ago"
msgstr "Meno di un minuto fa" msgstr "Meno di un minuto fa"
#: ../src/shell-global.c:1159 #: ../src/shell-global.c:1369
#, c-format #, c-format
msgid "%d minute ago" msgid "%d minute ago"
msgid_plural "%d minutes ago" msgid_plural "%d minutes ago"
msgstr[0] "%d minuto fa" msgstr[0] "%d minuto fa"
msgstr[1] "%d minuti fa" msgstr[1] "%d minuti fa"
#: ../src/shell-global.c:1164 #: ../src/shell-global.c:1374
#, c-format #, c-format
msgid "%d hour ago" msgid "%d hour ago"
msgid_plural "%d hours ago" msgid_plural "%d hours ago"
msgstr[0] "%d ora fa" msgstr[0] "%d ora fa"
msgstr[1] "%d ore fa" msgstr[1] "%d ore fa"
#: ../src/shell-global.c:1169 #: ../src/shell-global.c:1379
#, c-format #, c-format
msgid "%d day ago" msgid "%d day ago"
msgid_plural "%d days ago" msgid_plural "%d days ago"
msgstr[0] "%d giorno fa" msgstr[0] "%d giorno fa"
msgstr[1] "%d giorni fa" msgstr[1] "%d giorni fa"
#: ../src/shell-global.c:1174 #: ../src/shell-global.c:1384
#, c-format #, c-format
msgid "%d week ago" msgid "%d week ago"
msgid_plural "%d weeks ago" msgid_plural "%d weeks ago"

694
po/nb.po

File diff suppressed because it is too large Load Diff

889
po/pa.po

File diff suppressed because it is too large Load Diff

765
po/sv.po

File diff suppressed because it is too large Load Diff

525
po/ug.po
View File

@ -1,16 +1,15 @@
# Uyghur translation for gnome-shell. # Uyghur translation for gnome-shell.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# Gheyret Kenji<gheyret@yahoo.com>,2010. # Gheyret Kenji<gheyret@yahoo.com>,2010.
# Sahran <sahran.ug@gmail.com>, 2010. # Sahran <sahran.ug@gmail.com>, 2010.
# Zeper <zeper@msn.com>, 2010. # Zeper <zeper@msn.com>, 2010.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell\n" "Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell&component=general\n"
"shell&component=general\n" "POT-Creation-Date: 2010-12-20 21:07+0000\n"
"POT-Creation-Date: 2010-11-25 14:32+0000\n"
"PO-Revision-Date: 2010-11-25 14:28+0600\n" "PO-Revision-Date: 2010-11-25 14:28+0600\n"
"Last-Translator: Sahran <sahran@live.com>\n" "Last-Translator: Sahran <sahran@live.com>\n"
"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n" "Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
@ -47,28 +46,21 @@ msgstr "سائەتنىڭ ئىختىيارىي فورماتى"
#: ../data/org.gnome.shell.gschema.xml.in.h:3 #: ../data/org.gnome.shell.gschema.xml.in.h:3
msgid "Enable internal tools useful for developers and testers from Alt-F2" msgid "Enable internal tools useful for developers and testers from Alt-F2"
msgstr "" msgstr "ئىچكى قورال قوزغىتىلسا ئىجادكارلار ۋە سىنىغۇچىلارنىڭ Alt-F2 ئارقىلىق كىرىشىگە قۇلايلىق"
"ئىچكى قورال قوزغىتىلسا ئىجادكارلار ۋە سىنىغۇچىلارنىڭ Alt-F2 ئارقىلىق "
"كىرىشىگە قۇلايلىق"
#: ../data/org.gnome.shell.gschema.xml.in.h:4 #: ../data/org.gnome.shell.gschema.xml.in.h:4
msgid "File extension used for storing the screencast" msgid "File extension used for storing the screencast"
msgstr "" msgstr "ئېكران كەسمىسى (screencasts) ساقلاشتا ئىشلىتىلىدىغان ھۆججەتنىڭ كېڭەيتىلگەن ئاتى"
"ئېكران كەسمىسى (screencasts) ساقلاشتا ئىشلىتىلىدىغان ھۆججەتنىڭ كېڭەيتىلگەن "
"ئاتى "
#: ../data/org.gnome.shell.gschema.xml.in.h:5 #: ../data/org.gnome.shell.gschema.xml.in.h:5
msgid "Framerate used for recording screencasts." msgid "Framerate used for recording screencasts."
msgstr "" msgstr "ئېكران كەسمىسى (screencasts) خاتىرىلەشتە ئىشلىتىلىدىغان كاندۇك تېزلىكى."
"ئېكران كەسمىسى (screencasts) خاتىرىلەشتە ئىشلىتىلىدىغان كاندۇك تېزلىكى."
#: ../data/org.gnome.shell.gschema.xml.in.h:6 #: ../data/org.gnome.shell.gschema.xml.in.h:6
msgid "" msgid ""
"GNOME Shell extensions have a uuid property; this key lists extensions which " "GNOME Shell extensions have a uuid property; this key lists extensions which "
"should not be loaded." "should not be loaded."
msgstr "" msgstr "GNOME چاپان (Shell)كېڭەيتىلمىسىنىڭ uuid خاسلىقى بار؛ بۇ كۇنۇپكا يۈكلەنمەيدىغان كېڭەيتىلمىلەر تىزىملىكىنى كۆرسىتىدۇ."
"GNOME چاپان (Shell)كېڭەيتىلمىسىنىڭ uuid خاسلىقى بار؛ بۇ كۇنۇپكا "
"يۈكلەنمەيدىغان كېڭەيتىلمىلەر تىزىملىكىنى كۆرسىتىدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:7 #: ../data/org.gnome.shell.gschema.xml.in.h:7
msgid "History for command (Alt-F2) dialog" msgid "History for command (Alt-F2) dialog"
@ -82,17 +74,13 @@ msgstr "سائەت فورماتى"
msgid "" msgid ""
"If true and format is either \"12-hour\" or \"24-hour\", display date in the " "If true and format is either \"12-hour\" or \"24-hour\", display date in the "
"clock, in addition to time." "clock, in addition to time."
msgstr "" msgstr "ئەگەر راست (true) بولسا سائەتتە ۋاقىت فورماتىنى «12 سائەت» ياكى «24 سائەت» كۆرسەتكەندىن سىرت چېسلانىمۇ كۆرسىتىدۇ."
"ئەگەر راست (true) بولسا سائەتتە ۋاقىت فورماتىنى «12 سائەت» ياكى «24 سائەت» "
"كۆرسەتكەندىن سىرت چېسلانىمۇ كۆرسىتىدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:10 #: ../data/org.gnome.shell.gschema.xml.in.h:10
msgid "" msgid ""
"If true and format is either \"12-hour\" or \"24-hour\", display seconds in " "If true and format is either \"12-hour\" or \"24-hour\", display seconds in "
"time." "time."
msgstr "" msgstr "ئەگەر راست (true) بولسا سائەتتە ۋاقىت فورماتىنى «12 سائەت» ياكى «24 سائەت» كۆرسەتكەندىن سىرت سېكۇنتنىمۇ كۆرسىتىدۇ."
"ئەگەر راست (true) بولسا سائەتتە ۋاقىت فورماتىنى «12 سائەت» ياكى «24 سائەت» "
"كۆرسەتكەندىن سىرت سېكۇنتنىمۇ كۆرسىتىدۇ. "
#: ../data/org.gnome.shell.gschema.xml.in.h:11 #: ../data/org.gnome.shell.gschema.xml.in.h:11
msgid "If true, display the ISO week date in the calendar." msgid "If true, display the ISO week date in the calendar."
@ -100,13 +88,9 @@ msgstr "ئەگەر راست(true) بولسا يىلنامىدىكى ISO ھەپت
#: ../data/org.gnome.shell.gschema.xml.in.h:12 #: ../data/org.gnome.shell.gschema.xml.in.h:12
msgid "List of desktop file IDs for favorite applications" msgid "List of desktop file IDs for favorite applications"
msgstr "ئامراق قوللىنىشچان پروگراممىلارنىڭ ئۈستەل ئۈستى ھۆججەت ID تىزىملىكى" msgstr "ئامراق پروگراممىلارنىڭ ئۈستەلئۈستى ھۆججەت ID تىزىملىكى"
#: ../data/org.gnome.shell.gschema.xml.in.h:13 #: ../data/org.gnome.shell.gschema.xml.in.h:13
msgid "Overview workspace view mode"
msgstr "خىزمەت رايون كۆرۈنۈش ھالىتى ھەققىدە قىسقىچە بايان"
#: ../data/org.gnome.shell.gschema.xml.in.h:14
msgid "" msgid ""
"Sets the GStreamer pipeline used to encode recordings. It follows the syntax " "Sets the GStreamer pipeline used to encode recordings. It follows the syntax "
"used for gst-launch. The pipeline should have an unconnected sink pad where " "used for gst-launch. The pipeline should have an unconnected sink pad where "
@ -116,91 +100,60 @@ msgid ""
"the output to an icecast server via shout2send or similar. When unset or set " "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 " "to an empty value, the default pipeline will be used. This is currently "
"'videorate ! theoraenc ! oggmux' and records to Ogg Theora." "'videorate ! theoraenc ! oggmux' and records to Ogg Theora."
msgstr "" msgstr "ئۈن ئېلىشنى كودلاشتا ئىشلىتىلىدىغان GStreamer ئاقما لىنىيىنى تەڭشەيدۇ. ئۇ gst-launch گرامماتىكىسىغا بوي سۇنىدۇ. بۇ ئاقما لىنىيىدە ئۇلانمىغان sink pad بولۇشى لازىم، خاتىرىلىنىدىغان سىن مۇشۇ جايدا خاتىرىلىنىدۇ. بۇ لىنىيىدە ئادەتتە يەنە بىر ئۇلانمىغان مەنبە pad بولىدۇ؛ بۇ pad چىقارغان ئۇچۇرلار ھۆججەتكە يېزىلىدۇ. ئەمما ئاقما لىنىيە ئۆزىنىڭ چىقىرىشىنى بىر تەرەپ قىلالايدۇ، بۇنداق بولغاندا shout2send ئارقىلىق ياكى شۇنىڭغا ئوخشاش ئۇسۇلدا چىقىرىشنى icecast مۇلازىمېتىرىغا يوللايدۇ. ئاقما لىنىيە تەڭشەلمىگەن ياكى بوش قىممەتكە تەڭشەلگەندە كۆڭۈلدىكى ئاقما لىنىيە قوزغىتىلىدۇ. ئۇنىڭ نۆۋەتتىكى قىممىتى 'videorate ! theoraenc ! oggmux' بولۇپ، فورماتى Ogg شەكلىدە خاتىرىلىنىدۇ."
"ئۈن ئېلىشنى كودلاشتا ئىشلىتىلىدىغان GStreamer ئاقما لىنىيىنى تەڭشەيدۇ. ئۇ "
"gst-launch گرامماتىكىسىغا بوي سۇنىدۇ. بۇ ئاقما لىنىيىدە ئۇلانمىغان sink pad "
"بولۇشى لازىم، خاتىرىلىنىدىغان سىن مۇشۇ جايدا خاتىرىلىنىدۇ. بۇ لىنىيىدە "
"ئادەتتە يەنە بىر ئۇلانمىغان مەنبە pad بولىدۇ؛ بۇ pad چىقارغان ئۇچۇرلار "
"ھۆججەتكە يېزىلىدۇ. ئەمما ئاقما لىنىيە ئۆزىنىڭ چىقىرىشىنى بىر تەرەپ "
"قىلالايدۇ، بۇنداق بولغاندا shout2send ئارقىلىق ياكى شۇنىڭغا ئوخشاش ئۇسۇلدا "
"چىقىرىشنى icecast مۇلازىمېتىرىغا يوللايدۇ. ئاقما لىنىيە تەڭشەلمىگەن ياكى بوش "
"قىممەتكە تەڭشەلگەندە كۆڭۈلدىكى ئاقما لىنىيە قوزغىتىلىدۇ. ئۇنىڭ نۆۋەتتىكى "
"قىممىتى 'videorate ! theoraenc ! oggmux' بولۇپ، فورماتى Ogg شەكلىدە "
"خاتىرىلىنىدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:15 #: ../data/org.gnome.shell.gschema.xml.in.h:14
msgid "Show date in clock" msgid "Show date in clock"
msgstr "سائەت ئىچىدە چېسلا كۆرسەت" msgstr "سائەت ئىچىدە چېسلا كۆرسەت"
#: ../data/org.gnome.shell.gschema.xml.in.h:16 #: ../data/org.gnome.shell.gschema.xml.in.h:15
msgid "Show the week date in the calendar" msgid "Show the week date in the calendar"
msgstr "يىلنامىدە ھەپتىنى كۆرسىتىدۇ" msgstr "يىلنامىدە ھەپتىنى كۆرسىتىدۇ"
#: ../data/org.gnome.shell.gschema.xml.in.h:17 #: ../data/org.gnome.shell.gschema.xml.in.h:16
msgid "Show time with seconds" msgid "Show time with seconds"
msgstr "ۋاقىت ئىچىدە سېكۇنتنى بىللە كۆرسەت" msgstr "ۋاقىت ئىچىدە سېكۇنتنى بىللە كۆرسەت"
#: ../data/org.gnome.shell.gschema.xml.in.h:18 #: ../data/org.gnome.shell.gschema.xml.in.h:17
msgid "" msgid ""
"The applications corresponding to these identifiers will be displayed in the " "The applications corresponding to these identifiers will be displayed in the "
"favorites area." "favorites area."
msgstr "مۇناسىپ پروگرامما بەلگىسى يىغقۇچ رايونىدا كۆرسىتىلىدۇ." msgstr "مۇناسىپ پروگرامما بەلگىسى يىغقۇچ رايونىدا كۆرسىتىلىدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:19 #: ../data/org.gnome.shell.gschema.xml.in.h:18
msgid "" msgid ""
"The filename for recorded screencasts will be a unique filename based on the " "The filename for recorded screencasts will be a unique filename based on the "
"current date, and use this extension. It should be changed when recording to " "current date, and use this extension. It should be changed when recording to "
"a different container format." "a different container format."
msgstr "" msgstr "خاتىرىلەنگەن ئېكراننىڭ ھۆججەت ئاتى نۆۋەتتىكى چېسلا ئاساسىدا بىردىنبىر بولۇپ بۇ كېڭەيتىلگەن ئاتىنى ئىشلىتىدۇ. ئۇ ئۆزگەرسە ئوخشاش بولمىغان قاچا فورماتىدا خاتىرىلەيدۇ."
"خاتىرىلەنگەن ئېكراننىڭ ھۆججەت ئاتى نۆۋەتتىكى چېسلا ئاساسىدا بىردىنبىر بولۇپ "
"بۇ كېڭەيتىلگەن ئاتىنى ئىشلىتىدۇ. ئۇ ئۆزگەرسە ئوخشاش بولمىغان قاچا فورماتىدا "
"خاتىرىلەيدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:20 #: ../data/org.gnome.shell.gschema.xml.in.h:19
msgid "" msgid ""
"The framerate of the resulting screencast recordered by GNOME Shell's " "The framerate of the resulting screencast recordered by GNOME Shell's "
"screencast recorder in frames-per-second." "screencast recorder in frames-per-second."
msgstr "" msgstr "GNOME Shell ئېكران خاتىرىلىگۈچ ھەر سېكۇنتتا خاتىرىلەيدىغان ئېكران كەسمىسى كاندۇك سۈرىتى(ھەر سېكۇنتتىكى كاندۇك سانى)."
"GNOME Shell ئېكران خاتىرىلىگۈچ ھەر سېكۇنتتا خاتىرىلەيدىغان ئېكران كەسمىسى "
"كاندۇك سۈرىتى(ھەر سېكۇنتتىكى كاندۇك سانى)."
#: ../data/org.gnome.shell.gschema.xml.in.h:21 #: ../data/org.gnome.shell.gschema.xml.in.h:20
msgid "The gstreamer pipeline used to encode the screencast" msgid "The gstreamer pipeline used to encode the screencast"
msgstr "ئېكران كەسمىسىنى كودلاشتا ئىشلىتىلىدىغان gstreamer ئاقما لىنىيىسى" msgstr "ئېكران كەسمىسىنى كودلاشتا ئىشلىتىلىدىغان gstreamer ئاقما لىنىيىسى"
#: ../data/org.gnome.shell.gschema.xml.in.h:22 #: ../data/org.gnome.shell.gschema.xml.in.h:21
msgid ""
"The selected workspace view mode in the overview. Supported values are "
"\"single\" and \"grid\"."
msgstr ""
"قىسقىچە باياندىكى تاللانغان خىزمەت رايونىنىڭ كۆرۈنۈش ھالىتى. ئىشلىتىشكە "
"بولىدىغان قىممەتلەر «يەككە» ۋە «سېتكا»"
#: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "" msgid ""
"The shell normally monitors active applications in order to present the most " "The shell normally monitors active applications in order to present the most "
"used ones (e.g. in launchers). While this data will be kept private, you may " "used ones (e.g. in launchers). While this data will be kept private, you may "
"want to disable this for privacy reasons. Please note that doing so won't " "want to disable this for privacy reasons. Please note that doing so won't "
"remove already saved data." "remove already saved data."
msgstr "" msgstr "چاپان (shell) ئادەتتىكى ئەھۋالدا كۆپ ئىشلىتىلىدىغان ئاكتىپ پروگراممىلار(مەسىلەن، ئىجرا قىلىنىۋاتقان)نى كۆزىتىدۇ. گەرچە بۇ سانلىق مەلۇماتلار مەخپىي ساقلانسىمۇ، شەخسىي سىر سەۋەبىدىن بۇنى چەكلىشىڭىز مۇمكىن. دىققەت بۇنداق قىلغاندا ئاللىبۇرۇن ساقلانغان سانلىق مەلۇماتلار چىقىرىۋېتىلمەيدۇ."
"چاپان (shell) ئادەتتىكى ئەھۋالدا كۆپ ئىشلىتىلىدىغان ئاكتىپ پروگراممىلار"
"(مەسىلەن، ئىجرا قىلىنىۋاتقان)نى كۆزىتىدۇ. گەرچە بۇ سانلىق مەلۇماتلار مەخپىي "
"ساقلانسىمۇ، شەخسىي سىر سەۋەبىدىن بۇنى چەكلىشىڭىز مۇمكىن. دىققەت بۇنداق "
"قىلغاندا ئاللىبۇرۇن ساقلانغان سانلىق مەلۇماتلار چىقىرىۋېتىلمەيدۇ."
#: ../data/org.gnome.shell.gschema.xml.in.h:24 #: ../data/org.gnome.shell.gschema.xml.in.h:22
msgid "" msgid ""
"This key specifies the format used by the panel clock when the format key is " "This key specifies the format used by the panel clock when the format key is "
"set to \"custom\". You can use conversion specifiers understood by strftime" "set to \"custom\". You can use conversion specifiers understood by strftime"
"() to obtain a specific format. See the strftime() manual for more " "() to obtain a specific format. See the strftime() manual for more "
"information." "information."
msgstr "" msgstr "format (فورمات) كۇنۇپكىسى \"custom\" (ئىختىيارى) قىلىپ تەڭشەلسە بۇ كۇنۇپكا تاختا سائەت ئىشلىتىدىغان فورماتنى بەلگىلەيدۇ. سىز strftime()نىڭ فورمات بەلگىسىنى ئىشلىتىپ بەلگىلەنگەن فورماتقا ئېرىشەلەيسىز. تەپسىلاتىنى strftime() نىڭ قوللانمىسىدىن كۆرۈڭ."
"format (فورمات) كۇنۇپكىسى \"custom\" (ئىختىيارى) قىلىپ تەڭشەلسە بۇ كۇنۇپكا "
"تاختا سائەت ئىشلىتىدىغان فورماتنى بەلگىلەيدۇ. سىز strftime()نىڭ فورمات "
"بەلگىسىنى ئىشلىتىپ بەلگىلەنگەن فورماتقا ئېرىشەلەيسىز. تەپسىلاتىنى strftime() "
"نىڭ قوللانمىسىدىن كۆرۈڭ."
#: ../data/org.gnome.shell.gschema.xml.in.h:25 #: ../data/org.gnome.shell.gschema.xml.in.h:23
msgid "" msgid ""
"This key specifies the hour format used by the panel clock. Possible values " "This key specifies the hour format used by the panel clock. Possible values "
"are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", " "are \"12-hour\", \"24-hour\", \"unix\" and \"custom\". If set to \"unix\", "
@ -208,20 +161,13 @@ msgid ""
"to \"custom\", the clock will display time according to the format specified " "to \"custom\", the clock will display time according to the format specified "
"in the custom_format key. Note that if set to either \"unix\" or \"custom\", " "in the custom_format key. Note that if set to either \"unix\" or \"custom\", "
"the show_date and show_seconds keys are ignored." "the show_date and show_seconds keys are ignored."
msgstr "" msgstr "بۇ كۇنۇپكا تاختا سائەت ئىشلەتكەن سائەت فورماتىنى بەلگىلىگەن. ئىشلەتكىلى بولىدىغان قىممىتى \"12-hour\" يەنى (12 سائەت)، \"24-hour\" يەنى (24 سائەت)، \"unix\" ۋە \"custom\" (ئىختىيارى). ئەگەر \"unix\" قىلىپ تەڭشەلسە سائەت ئۆزلۈكىدىن يېڭى ئېرا (يەنى، 1970-01-01) دىن ئۆتكەن سېكۇنتنى ئاساس قىلىدۇ. ئەگەر \"custom\" قىلىپ تەڭشەلسە سائەت custom_format كۇنۇپكا قىممىتىگە ئاساسەن ۋاقىتنى كۆرسىتىدۇ. ئەگەر \"unix\" ياكى \"custom\" قىلىپ تەڭشەلسە show_date ۋە show_seconds قىممىتىگە پەرۋا قىلمايدۇ"
"بۇ كۇنۇپكا تاختا سائەت ئىشلەتكەن سائەت فورماتىنى بەلگىلىگەن. ئىشلەتكىلى "
"بولىدىغان قىممىتى \"12-hour\" يەنى (12 سائەت)، \"24-hour\" يەنى (24 سائەت)، "
"\"unix\" ۋە \"custom\" (ئىختىيارى). ئەگەر \"unix\" قىلىپ تەڭشەلسە سائەت "
"ئۆزلۈكىدىن يېڭى ئېرا (يەنى، 1970-01-01) دىن ئۆتكەن سېكۇنتنى ئاساس قىلىدۇ. "
"ئەگەر \"custom\" قىلىپ تەڭشەلسە سائەت custom_format كۇنۇپكا قىممىتىگە "
"ئاساسەن ۋاقىتنى كۆرسىتىدۇ. ئەگەر \"unix\" ياكى \"custom\" قىلىپ تەڭشەلسە "
"show_date ۋە show_seconds قىممىتىگە پەرۋا قىلمايدۇ"
#: ../data/org.gnome.shell.gschema.xml.in.h:26 #: ../data/org.gnome.shell.gschema.xml.in.h:24
msgid "Uuids of extensions to disable" msgid "Uuids of extensions to disable"
msgstr "چەكلىنىدىغان كېڭەيتىلمىنىڭ Uuid سى" msgstr "چەكلىنىدىغان كېڭەيتىلمىنىڭ Uuid سى"
#: ../data/org.gnome.shell.gschema.xml.in.h:27 #: ../data/org.gnome.shell.gschema.xml.in.h:25
msgid "Whether to collect stats about applications usage" msgid "Whether to collect stats about applications usage"
msgstr "پروگراممىنىڭ ئىشلىتىلىشى ھەققىدىكى ستاتىستىكىنى توپلامدۇ يوق" msgstr "پروگراممىنىڭ ئىشلىتىلىشى ھەققىدىكى ستاتىستىكىنى توپلامدۇ يوق"
@ -237,8 +183,7 @@ msgstr "نىشانلىغۇچنىڭ رەڭگى"
msgid "" msgid ""
"Determines the length of the vertical and horizontal lines that make up the " "Determines the length of the vertical and horizontal lines that make up the "
"crosshairs." "crosshairs."
msgstr "" msgstr "نىشانلىغۇچنى ھاسىل قىلىدىغان توغرا ۋە بوي سىزىقنىڭ ئۇزۇنلۇقى بەلگىلىنىدۇ."
"نىشانلىغۇچنى ھاسىل قىلىدىغان توغرا ۋە بوي سىزىقنىڭ ئۇزۇنلۇقى بەلگىلىنىدۇ."
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:4 #: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:4
msgid "" msgid ""
@ -305,7 +250,7 @@ msgstr "ئېكران ئورنى"
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:15 #: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:15
msgid "Scroll magnified contents beyond the edges of the desktop" msgid "Scroll magnified contents beyond the edges of the desktop"
msgstr "دومىلىما چوڭايتقۇچ ئۈستەل ئۈستى گىرۋەك مەزمۇنىدىن ھالقىپ كەتتى" msgstr "دومىلىما چوڭايتقۇچ ئۈستەلئۈستى گىرۋەك مەزمۇنىدىن ھالقىپ كەتتى"
#: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:16 #: ../data/org.gnome.accessibility.magnifier.gschema.xml.in.h:16
msgid "Show or hide crosshairs" msgid "Show or hide crosshairs"
@ -379,62 +324,45 @@ msgstr "_12 سائەت فورماتى"
msgid "_24 hour format" msgid "_24 hour format"
msgstr "_24 سائەت فورماتى" msgstr "_24 سائەت فورماتى"
#. **** Applications **** #: ../js/ui/appDisplay.js:154
#: ../js/ui/appDisplay.js:316 ../js/ui/dash.js:778 msgid "All"
msgstr "ھەممىسى"
#: ../js/ui/appDisplay.js:235
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "پروگراممىلار" msgstr "پروگراممىلار"
#: ../js/ui/appDisplay.js:348 #: ../js/ui/appDisplay.js:265
msgid "PREFERENCES" msgid "PREFERENCES"
msgstr "مايىللىق" msgstr "مايىللىق"
#: ../js/ui/appDisplay.js:647 #: ../js/ui/appDisplay.js:562
msgid "New Window" msgid "New Window"
msgstr "يېڭى كۆزنەك" msgstr "يېڭى كۆزنەك"
#: ../js/ui/appDisplay.js:651 #: ../js/ui/appDisplay.js:566
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "يىغقۇچتىن چىقىرىۋەت" msgstr "يىغقۇچتىن چىقىرىۋەت"
#: ../js/ui/appDisplay.js:652 #: ../js/ui/appDisplay.js:567
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "يىغقۇچقا قوش" msgstr "يىغقۇچقا قوش"
#: ../js/ui/appDisplay.js:829 #: ../js/ui/appFavorites.js:91
msgid "Drag here to add favorites"
msgstr "بۇ جايغا سۆرەپ يىغقۇچقا قوش"
#: ../js/ui/appFavorites.js:88
#, c-format #, c-format
msgid "%s has been added to your favorites." msgid "%s has been added to your favorites."
msgstr "%s يىغقۇچىڭىزغا قوشۇلدى." msgstr "%s يىغقۇچىڭىزغا قوشۇلدى."
#: ../js/ui/appFavorites.js:107 #: ../js/ui/appFavorites.js:122
#, c-format #, c-format
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s يىغقۇچىڭىزدىن چىقىرىۋېتىلىدۇ." msgstr "%s يىغقۇچىڭىزدىن چىقىرىۋېتىلىدۇ."
#: ../js/ui/dash.js:142 #: ../js/ui/dash.js:27
msgid "Find" msgid "Remove"
msgstr "ئىزدە" msgstr "چىقىرىۋەت"
#: ../js/ui/dash.js:473 #: ../js/ui/docDisplay.js:494
msgid "Searching..."
msgstr "ئىزدەۋاتىدۇ..."
#: ../js/ui/dash.js:487
msgid "No matching results."
msgstr "ماس كېلىدىغان نەتىجە يوق."
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:797 ../js/ui/placeDisplay.js:558
msgid "PLACES & DEVICES"
msgstr "ئورۇن ۋە ئۈسكۈنىلەر"
#. **** Documents ****
#: ../js/ui/dash.js:804 ../js/ui/docDisplay.js:494
msgid "RECENT ITEMS" msgid "RECENT ITEMS"
msgstr "يېقىنقى تۈرلەر" msgstr "يېقىنقى تۈرلەر"
@ -468,63 +396,72 @@ msgstr "مەنبەنى كۆرسەت"
msgid "Web Page" msgid "Web Page"
msgstr "توربەت" msgstr "توربەت"
#: ../js/ui/overview.js:160 #: ../js/ui/overview.js:96
msgid "Undo" msgid "Undo"
msgstr "يېنىۋال" msgstr "يېنىۋال"
#: ../js/ui/overview.js:158
#| msgid "New Window"
msgid "Windows"
msgstr "كۆزنەكلەر"
#: ../js/ui/overview.js:161
msgid "Applications"
msgstr "پروگراممىلار"
#. TODO - _quit() doesn't really work on apps in state STARTING yet #. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:470 #: ../js/ui/panel.js:474
#, c-format #, c-format
msgid "Quit %s" msgid "Quit %s"
msgstr "%s چېكىن" msgstr "%s چېكىن"
#: ../js/ui/panel.js:495 #: ../js/ui/panel.js:499
msgid "Preferences" msgid "Preferences"
msgstr "مايىللىق" msgstr "مايىللىق"
#. Translators: This is the time format with date used #. Translators: This is the time format with date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:581 #: ../js/ui/panel.js:585
msgid "%a %b %e, %R:%S" msgid "%a %b %e, %R:%S"
msgstr "%a %b %e، %R:%S" msgstr "%a %b %e، %R:%S"
#: ../js/ui/panel.js:582 #: ../js/ui/panel.js:586
msgid "%a %b %e, %R" msgid "%a %b %e, %R"
msgstr "%a %b %e، %R" msgstr "%a %b %e، %R"
#. Translators: This is the time format without date used #. Translators: This is the time format without date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:586 #: ../js/ui/panel.js:590
msgid "%a %R:%S" msgid "%a %R:%S"
msgstr "%a %R:%S" msgstr "%a %R:%S"
#: ../js/ui/panel.js:587 #: ../js/ui/panel.js:591
msgid "%a %R" msgid "%a %R"
msgstr "%a %R" msgstr "%a %R"
#. Translators: This is a time format with date used #. Translators: This is a time format with date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:594 #: ../js/ui/panel.js:598
msgid "%a %b %e, %l:%M:%S %p" msgid "%a %b %e, %l:%M:%S %p"
msgstr "%a %b %e، %l:%M:%S %p" msgstr "%a %b %e، %l:%M:%S %p"
#: ../js/ui/panel.js:595 #: ../js/ui/panel.js:599
msgid "%a %b %e, %l:%M %p" msgid "%a %b %e, %l:%M %p"
msgstr "%a %b %e، %l:%M %p" msgstr "%a %b %e، %l:%M %p"
#. Translators: This is a time format without date used #. Translators: This is a time format without date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:599 #: ../js/ui/panel.js:603
msgid "%a %l:%M:%S %p" msgid "%a %l:%M:%S %p"
msgstr "%a %l:%M:%S %p" msgstr "%a %l:%M:%S %p"
#: ../js/ui/panel.js:600 #: ../js/ui/panel.js:604
msgid "%a %l:%M %p" msgid "%a %l:%M %p"
msgstr "%p%l:%M (%a)" msgstr "%p%l:%M (%a)"
#. Button on the left side of the panel. #. 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". #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:745 #: ../js/ui/panel.js:749
msgid "Activities" msgid "Activities"
msgstr "پائالىيەتلەر" msgstr "پائالىيەتلەر"
@ -541,6 +478,10 @@ msgstr "قايتا سىنا"
msgid "Connect to..." msgid "Connect to..."
msgstr "باغلىنىش…" msgstr "باغلىنىش…"
#: ../js/ui/placeDisplay.js:558
msgid "PLACES & DEVICES"
msgstr "ئورۇن ۋە ئۈسكۈنىلەر"
#. Translators: this MUST be either "toggle-switch-us" #. Translators: this MUST be either "toggle-switch-us"
#. (for toggle switches containing the English words #. (for toggle switches containing the English words
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
@ -568,16 +509,14 @@ msgid "Busy"
msgstr "ئالدىراش" msgstr "ئالدىراش"
#: ../js/ui/statusMenu.js:114 #: ../js/ui/statusMenu.js:114
#, fuzzy
#| msgid "My Account..." #| msgid "My Account..."
msgid "My Account" msgid "My Account"
msgstr "ھېساباتىم" msgstr "ھېساباتىم"
#: ../js/ui/statusMenu.js:118 #: ../js/ui/statusMenu.js:118
#, fuzzy
#| msgid "System Settings..." #| msgid "System Settings..."
msgid "System Settings" msgid "System Settings"
msgstr "سىستېما تەڭشەكلىرى..." msgstr "سىستېما تەڭشىكى"
#: ../js/ui/statusMenu.js:125 #: ../js/ui/statusMenu.js:125
msgid "Lock Screen" msgid "Lock Screen"
@ -592,15 +531,18 @@ msgid "Log Out..."
msgstr "تىزىمدىن چىقىش…" msgstr "تىزىمدىن چىقىش…"
#: ../js/ui/statusMenu.js:141 #: ../js/ui/statusMenu.js:141
#, fuzzy
#| msgid "Suspend" #| msgid "Suspend"
msgid "Suspend..." msgid "Suspend..."
msgstr "توڭلات" msgstr ""
#: ../js/ui/statusMenu.js:145 #: ../js/ui/statusMenu.js:145
msgid "Shut Down..." msgid "Shut Down..."
msgstr "تاقا…" msgstr "تاقا…"
#: ../js/ui/status/accessibility.js:82
msgid "Zoom"
msgstr "كېڭەيت تارايت"
#: ../js/ui/status/accessibility.js:88 #: ../js/ui/status/accessibility.js:88
msgid "Screen Reader" msgid "Screen Reader"
msgstr "ئېكران ئوقۇغۇچ" msgstr "ئېكران ئوقۇغۇچ"
@ -641,9 +583,262 @@ msgstr "يۇقىرى ئاق-قارىلىقى"
msgid "Large Text" msgid "Large Text"
msgstr "چوڭ تېكىست" msgstr "چوڭ تېكىست"
#: ../js/ui/status/accessibility.js:224 #: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:200
msgid "Zoom" msgid "Bluetooth"
msgstr "كېڭەيت تارايت" msgstr "كۆكچىش"
#: ../js/ui/status/bluetooth.js:55
msgid "Visibility"
msgstr "كۆرۈشچانلىقى"
#: ../js/ui/status/bluetooth.js:68
msgid "Send Files to Device..."
msgstr ""
#: ../js/ui/status/bluetooth.js:71
msgid "Setup a New Device..."
msgstr ""
#: ../js/ui/status/bluetooth.js:94
#| msgid "System Settings..."
msgid "Bluetooth Settings"
msgstr ""
#: ../js/ui/status/bluetooth.js:151
#| msgid "Connect to..."
msgid "Connection"
msgstr "باغلىنىش"
#: ../js/ui/status/bluetooth.js:187
#| msgid "Suspend"
msgid "Send Files..."
msgstr ""
#: ../js/ui/status/bluetooth.js:192
msgid "Browse Files..."
msgstr ""
#: ../js/ui/status/bluetooth.js:201
msgid "Error browsing device"
msgstr ""
#: ../js/ui/status/bluetooth.js:202
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr ""
#: ../js/ui/status/bluetooth.js:210
#| msgid "System Settings..."
msgid "Keyboard Settings"
msgstr ""
#: ../js/ui/status/bluetooth.js:215
#| msgid "System Settings..."
msgid "Mouse Settings"
msgstr ""
#: ../js/ui/status/bluetooth.js:222 ../js/ui/status/volume.js:62
#| msgid "System Settings..."
msgid "Sound Settings"
msgstr ""
#: ../js/ui/status/bluetooth.js:293 ../js/ui/status/bluetooth.js:327
#: ../js/ui/status/bluetooth.js:367 ../js/ui/status/bluetooth.js:400
msgid "Bluetooth Agent"
msgstr ""
#: ../js/ui/status/bluetooth.js:328
#, c-format
msgid "Authorization request from %s"
msgstr ""
#: ../js/ui/status/bluetooth.js:334
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr ""
#: ../js/ui/status/bluetooth.js:336
msgid "Always grant access"
msgstr ""
#: ../js/ui/status/bluetooth.js:337
msgid "Grant this time only"
msgstr ""
#: ../js/ui/status/bluetooth.js:338
msgid "Reject"
msgstr "رەت قىل"
#: ../js/ui/status/bluetooth.js:368
#, c-format
msgid "Pairing confirmation for %s"
msgstr ""
#: ../js/ui/status/bluetooth.js:374 ../js/ui/status/bluetooth.js:408
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr ""
#: ../js/ui/status/bluetooth.js:375
#, c-format
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr ""
#: ../js/ui/status/bluetooth.js:377
msgid "Matches"
msgstr "جۈپلەش تۈرى"
#: ../js/ui/status/bluetooth.js:378
msgid "Does not match"
msgstr "جۈپلىمە"
#: ../js/ui/status/bluetooth.js:401
#, c-format
msgid "Pairing request for %s"
msgstr ""
#: ../js/ui/status/bluetooth.js:409
msgid "Please enter the PIN mentioned on the device."
msgstr ""
#: ../js/ui/status/bluetooth.js:425
msgid "OK"
msgstr "جەزملە"
#: ../js/ui/status/bluetooth.js:426
msgid "Cancel"
msgstr "ۋاز كەچ"
#: ../js/ui/status/power.js:85
#| msgid "System Settings..."
msgid "Power Settings"
msgstr ""
#: ../js/ui/status/power.js:112
#, c-format
#| msgid "%d hour ago"
#| msgid_plural "%d hours ago"
msgid "%d hour remaining"
msgid_plural "%d hours remaining"
msgstr[0] ""
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#: ../js/ui/status/power.js:115
#, c-format
msgid "%d %s %d %s remaining"
msgstr ""
#: ../js/ui/status/power.js:117
msgid "hour"
msgid_plural "hours"
msgstr[0] "سائەت"
#: ../js/ui/status/power.js:117
#| msgid "%d minute ago"
#| msgid_plural "%d minutes ago"
msgid "minute"
msgid_plural "minutes"
msgstr[0] "مىنۇت"
#: ../js/ui/status/power.js:120
#, c-format
#| msgid "%d minute ago"
#| msgid_plural "%d minutes ago"
msgid "%d minute remaining"
msgid_plural "%d minutes remaining"
msgstr[0] ""
#: ../js/ui/status/power.js:237
msgid "AC adapter"
msgstr ""
#: ../js/ui/status/power.js:239
msgid "Laptop battery"
msgstr ""
#: ../js/ui/status/power.js:241
msgid "UPS"
msgstr "UPS"
#: ../js/ui/status/power.js:243
msgid "Monitor"
msgstr "ئېكران"
#: ../js/ui/status/power.js:245
#| msgid "Mouse Keys"
msgid "Mouse"
msgstr "چاشقىنەك"
#: ../js/ui/status/power.js:247
#| msgid "Screen Keyboard"
msgid "Keyboard"
msgstr "ھەرپتاختا"
#: ../js/ui/status/power.js:249
msgid "PDA"
msgstr "PDA"
#: ../js/ui/status/power.js:251
msgid "Cell phone"
msgstr ""
#: ../js/ui/status/power.js:253
msgid "Media player"
msgstr "Media چالغۇ"
#: ../js/ui/status/power.js:255
#| msgid "Enabled"
msgid "Tablet"
msgstr "سەزمە تاختا"
#: ../js/ui/status/power.js:257
msgid "Computer"
msgstr "كومپيۇتېر"
#: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
msgid "Unknown"
msgstr "نامەلۇم"
#: ../js/ui/status/volume.js:41
msgid "Volume"
msgstr "دىسكا"
#: ../js/ui/status/volume.js:54
msgid "Microphone"
msgstr ""
#: ../js/ui/telepathyClient.js:560
#, c-format
msgid "%s is online."
msgstr ""
#: ../js/ui/telepathyClient.js:565
#, c-format
msgid "%s is offline."
msgstr ""
#: ../js/ui/telepathyClient.js:568
#, c-format
#| msgid "'%s' is ready"
msgid "%s is away."
msgstr ""
#: ../js/ui/telepathyClient.js:571
#, c-format
msgid "%s is busy."
msgstr ""
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:664
#, no-c-format
msgid "Sent at %X on %A"
msgstr ""
#: ../js/ui/viewSelector.js:26
msgid "Search your computer"
msgstr ""
#: ../js/ui/windowAttentionHandler.js:43 #: ../js/ui/windowAttentionHandler.js:43
#, c-format #, c-format
@ -655,12 +850,12 @@ msgstr "%s باشلاشنى تاماملىدى"
msgid "'%s' is ready" msgid "'%s' is ready"
msgstr "«%s» تەييار" msgstr "«%s» تەييار"
#: ../js/ui/workspacesView.js:229 #: ../js/ui/workspacesView.js:244
msgid "" msgid ""
"Can't add a new workspace because maximum workspaces limit has been reached." "Can't add a new workspace because maximum workspaces limit has been reached."
msgstr "يېڭى خىزمەت رايونى قوشالمايدۇ چۈنكى ئەڭ كۆپ خىزمەت رايون چېكىگە يەتتى." msgstr "يېڭى خىزمەت رايونى قوشالمايدۇ چۈنكى ئەڭ كۆپ خىزمەت رايون چېكىگە يەتتى."
#: ../js/ui/workspacesView.js:246 #: ../js/ui/workspacesView.js:260
msgid "Can't remove the first workspace." msgid "Can't remove the first workspace."
msgstr "بىرىنچى خىزمەت رايونىنى چىقىرىۋەتكىلى بولمايدۇ." msgstr "بىرىنچى خىزمەت رايونىنى چىقىرىۋەتكىلى بولمايدۇ."
@ -684,33 +879,29 @@ msgstr[0] "%u كىرگۈزۈلمە"
msgid "System Sounds" msgid "System Sounds"
msgstr "سىستېما ئاۋازى" msgstr "سىستېما ئاۋازى"
#: ../src/shell-app-system.c:1012 #: ../src/shell-global.c:1155
msgid "Unknown"
msgstr "نامەلۇم"
#: ../src/shell-global.c:1163
msgid "Less than a minute ago" msgid "Less than a minute ago"
msgstr "بىر مىنۇتتىنمۇ ئىلگىرى" msgstr "بىر مىنۇتتىنمۇ ئىلگىرى"
#: ../src/shell-global.c:1167 #: ../src/shell-global.c:1159
#, c-format #, c-format
msgid "%d minute ago" msgid "%d minute ago"
msgid_plural "%d minutes ago" msgid_plural "%d minutes ago"
msgstr[0] "%d مىنۇت ئىلگىرى" msgstr[0] "%d مىنۇت ئىلگىرى"
#: ../src/shell-global.c:1172 #: ../src/shell-global.c:1164
#, c-format #, c-format
msgid "%d hour ago" msgid "%d hour ago"
msgid_plural "%d hours ago" msgid_plural "%d hours ago"
msgstr[0] "%d سائەت ئىلگىرى" msgstr[0] "%d سائەت ئىلگىرى"
#: ../src/shell-global.c:1177 #: ../src/shell-global.c:1169
#, c-format #, c-format
msgid "%d day ago" msgid "%d day ago"
msgid_plural "%d days ago" msgid_plural "%d days ago"
msgstr[0] "%d كۈن ئىلگىرى" msgstr[0] "%d كۈن ئىلگىرى"
#: ../src/shell-global.c:1182 #: ../src/shell-global.c:1174
#, c-format #, c-format
msgid "%d week ago" msgid "%d week ago"
msgid_plural "%d weeks ago" msgid_plural "%d weeks ago"
@ -738,7 +929,29 @@ msgstr "ئىزدە"
#: ../src/shell-util.c:300 #: ../src/shell-util.c:300
#, c-format #, c-format
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s " msgstr "%1$s: %2$s"
#~ msgid "Overview workspace view mode"
#~ msgstr "خىزمەت رايون كۆرۈنۈش ھالىتى ھەققىدە قىسقىچە بايان"
#~ msgid ""
#~ "The selected workspace view mode in the overview. Supported values are "
#~ "\"single\" and \"grid\"."
#~ msgstr ""
#~ "قىسقىچە باياندىكى تاللانغان خىزمەت رايونىنىڭ كۆرۈنۈش ھالىتى. ئىشلىتىشكە "
#~ "بولىدىغان قىممەتلەر «يەككە» ۋە «سېتكا»"
#~ msgid "Drag here to add favorites"
#~ msgstr "بۇ جايغا سۆرەپ يىغقۇچقا قوش"
#~ msgid "Find"
#~ msgstr "ئىزدە"
#~ msgid "Searching..."
#~ msgstr "ئىزدەۋاتىدۇ..."
#~ msgid "No matching results."
#~ msgstr "ماس كېلىدىغان نەتىجە يوق."
#~ msgid "Invisible" #~ msgid "Invisible"
#~ msgstr "يوشۇرۇن" #~ msgstr "يوشۇرۇن"

893
po/vi.po

File diff suppressed because it is too large Load Diff

View File

@ -7,14 +7,15 @@
# Jessica Ban <bancage@gmail.com>, 2010. # Jessica Ban <bancage@gmail.com>, 2010.
# YunQiang Su <wzssyqa@gmail.com>, 2010. # YunQiang Su <wzssyqa@gmail.com>, 2010.
# zhang ping <zhangping159@gmail.com>, 2010. # zhang ping <zhangping159@gmail.com>, 2010.
# 指冷玉笙寒 (dhyang) <dhyang555@gmail.com>, 2010
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n" "shell&component=general\n"
"POT-Creation-Date: 2010-12-10 00:17+0000\n" "POT-Creation-Date: 2010-12-23 17:30+0000\n"
"PO-Revision-Date: 2010-12-12 15:45+0800\n" "PO-Revision-Date: 2010-12-25 20:54+0800\n"
"Last-Translator: Aron Xu <happyaron.xu@gmail.com>\n" "Last-Translator: Aron Xu <happyaron.xu@gmail.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n" "Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -356,23 +357,28 @@ msgstr "_12 时格式"
msgid "_24 hour format" msgid "_24 hour format"
msgstr "_24 小时格式" msgstr "_24 小时格式"
#: ../js/ui/appDisplay.js:215 #. Translators: Filter to display all applications
#: ../js/ui/appDisplay.js:155
msgid "All"
msgstr "全部"
#: ../js/ui/appDisplay.js:236
msgid "APPLICATIONS" msgid "APPLICATIONS"
msgstr "应用程序" msgstr "应用程序"
#: ../js/ui/appDisplay.js:245 #: ../js/ui/appDisplay.js:266
msgid "PREFERENCES" msgid "PREFERENCES"
msgstr "首选项" msgstr "首选项"
#: ../js/ui/appDisplay.js:542 #: ../js/ui/appDisplay.js:563
msgid "New Window" msgid "New Window"
msgstr "新窗口" msgstr "新窗口"
#: ../js/ui/appDisplay.js:546 #: ../js/ui/appDisplay.js:567
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "从收藏夹中移除" msgstr "从收藏夹中移除"
#: ../js/ui/appDisplay.js:547 #: ../js/ui/appDisplay.js:568
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "添加到收藏夹" msgstr "添加到收藏夹"
@ -424,63 +430,71 @@ msgstr "查看源"
msgid "Web Page" msgid "Web Page"
msgstr "网页" msgstr "网页"
#: ../js/ui/overview.js:112 #: ../js/ui/overview.js:96
msgid "Undo" msgid "Undo"
msgstr "撤销" msgstr "撤销"
#: ../js/ui/overview.js:158
msgid "Windows"
msgstr "窗口"
#: ../js/ui/overview.js:161
msgid "Applications"
msgstr "应用程序"
#. TODO - _quit() doesn't really work on apps in state STARTING yet #. TODO - _quit() doesn't really work on apps in state STARTING yet
#: ../js/ui/panel.js:470 #: ../js/ui/panel.js:474
#, c-format #, c-format
msgid "Quit %s" msgid "Quit %s"
msgstr "退出 %s" msgstr "退出 %s"
#: ../js/ui/panel.js:495 #: ../js/ui/panel.js:499
msgid "Preferences" msgid "Preferences"
msgstr "首选项" msgstr "首选项"
#. Translators: This is the time format with date used #. Translators: This is the time format with date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:581 #: ../js/ui/panel.js:585
msgid "%a %b %e, %R:%S" msgid "%a %b %e, %R:%S"
msgstr "%A %b %e, %R:%S" msgstr "%A %b %e, %R:%S"
#: ../js/ui/panel.js:582 #: ../js/ui/panel.js:586
msgid "%a %b %e, %R" msgid "%a %b %e, %R"
msgstr "%A %m月%d日 %R" msgstr "%A %m月%d日 %R"
#. Translators: This is the time format without date used #. Translators: This is the time format without date used
#. in 24-hour mode. #. in 24-hour mode.
#: ../js/ui/panel.js:586 #: ../js/ui/panel.js:590
msgid "%a %R:%S" msgid "%a %R:%S"
msgstr "%A %R:%S" msgstr "%A %R:%S"
#: ../js/ui/panel.js:587 #: ../js/ui/panel.js:591
msgid "%a %R" msgid "%a %R"
msgstr "%A %R" msgstr "%A %R"
#. Translators: This is a time format with date used #. Translators: This is a time format with date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:594 #: ../js/ui/panel.js:598
msgid "%a %b %e, %l:%M:%S %p" msgid "%a %b %e, %l:%M:%S %p"
msgstr "%A %m月%d日 %p%I:%M:%S" msgstr "%A %m月%d日 %p%I:%M:%S"
#: ../js/ui/panel.js:595 #: ../js/ui/panel.js:599
msgid "%a %b %e, %l:%M %p" msgid "%a %b %e, %l:%M %p"
msgstr "%A %m月%d日 %p%I:%M" msgstr "%A %m月%d日 %p%I:%M"
#. Translators: This is a time format without date used #. Translators: This is a time format without date used
#. for AM/PM. #. for AM/PM.
#: ../js/ui/panel.js:599 #: ../js/ui/panel.js:603
msgid "%a %l:%M:%S %p" msgid "%a %l:%M:%S %p"
msgstr "%A %p%I:%M:%S" msgstr "%A %p%I:%M:%S"
#: ../js/ui/panel.js:600 #: ../js/ui/panel.js:604
msgid "%a %l:%M %p" msgid "%a %l:%M %p"
msgstr "%a %l:%M %p" msgstr "%a %l:%M %p"
#. Button on the left side of the panel. #. 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". #. Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview".
#: ../js/ui/panel.js:745 #: ../js/ui/panel.js:749
msgid "Activities" msgid "Activities"
msgstr "活动" msgstr "活动"
@ -599,87 +613,203 @@ msgstr "高对比度"
msgid "Large Text" msgid "Large Text"
msgstr "大号文本" msgstr "大号文本"
#: ../js/ui/status/power.js:87 #: ../js/ui/status/bluetooth.js:42 ../js/ui/status/bluetooth.js:234
msgid "What's using power..." msgid "Bluetooth"
msgstr "哪些设备在用电..." msgstr "蓝牙"
#: ../js/ui/status/power.js:90 #: ../js/ui/status/bluetooth.js:55
msgid "Visibility"
msgstr "可见性"
#: ../js/ui/status/bluetooth.js:69
msgid "Send Files to Device..."
msgstr "发送文件到设备..."
#: ../js/ui/status/bluetooth.js:70
msgid "Setup a New Device..."
msgstr "安装新设备..."
#: ../js/ui/status/bluetooth.js:94
msgid "Bluetooth Settings"
msgstr "蓝牙设置"
#: ../js/ui/status/bluetooth.js:185
msgid "Connection"
msgstr "连接"
#: ../js/ui/status/bluetooth.js:221
msgid "Send Files..."
msgstr "发送文件..."
#: ../js/ui/status/bluetooth.js:226
msgid "Browse Files..."
msgstr "浏览文件..."
#: ../js/ui/status/bluetooth.js:235
msgid "Error browsing device"
msgstr "浏览设备出错"
#: ../js/ui/status/bluetooth.js:236
#, c-format
msgid "The requested device cannot be browsed, error is '%s'"
msgstr "无法浏览请求的设备,错误为 %s"
#: ../js/ui/status/bluetooth.js:244
msgid "Keyboard Settings"
msgstr "键盘设置"
#: ../js/ui/status/bluetooth.js:249
msgid "Mouse Settings"
msgstr "鼠标设置"
#: ../js/ui/status/bluetooth.js:256 ../js/ui/status/volume.js:62
msgid "Sound Settings"
msgstr "声音设置"
#: ../js/ui/status/bluetooth.js:327 ../js/ui/status/bluetooth.js:361
#: ../js/ui/status/bluetooth.js:401 ../js/ui/status/bluetooth.js:434
msgid "Bluetooth Agent"
msgstr "蓝牙助手"
#: ../js/ui/status/bluetooth.js:362
#, c-format
msgid "Authorization request from %s"
msgstr "来自 %s 的认证请求"
#: ../js/ui/status/bluetooth.js:368
#, c-format
msgid "Device %s wants access to the service '%s'"
msgstr "设备 %s 希望访问 %s 服务"
#: ../js/ui/status/bluetooth.js:370
msgid "Always grant access"
msgstr "始终允许"
#: ../js/ui/status/bluetooth.js:371
msgid "Grant this time only"
msgstr "允许一次"
#: ../js/ui/status/bluetooth.js:372
msgid "Reject"
msgstr "拒绝"
#: ../js/ui/status/bluetooth.js:402
#, c-format
msgid "Pairing confirmation for %s"
msgstr "%s 的配对确认"
#: ../js/ui/status/bluetooth.js:408 ../js/ui/status/bluetooth.js:442
#, c-format
msgid "Device %s wants to pair with this computer"
msgstr "设备 %s 希望与此电脑配对"
#: ../js/ui/status/bluetooth.js:409
#, c-format
msgid "Please confirm whether the PIN '%s' matches the one on the device."
msgstr "请确认 PIN 码 %s 和要配对的设备是否相同。"
#: ../js/ui/status/bluetooth.js:411
msgid "Matches"
msgstr "相同"
#: ../js/ui/status/bluetooth.js:412
msgid "Does not match"
msgstr "不同"
#: ../js/ui/status/bluetooth.js:435
#, c-format
msgid "Pairing request for %s"
msgstr "%s 的配对请求"
#: ../js/ui/status/bluetooth.js:443
msgid "Please enter the PIN mentioned on the device."
msgstr "请输入设备上的 PIN 码。"
#: ../js/ui/status/bluetooth.js:459
msgid "OK"
msgstr "确定"
#: ../js/ui/status/bluetooth.js:460
msgid "Cancel"
msgstr "取消"
#: ../js/ui/status/power.js:85
msgid "Power Settings" msgid "Power Settings"
msgstr "电源设置" msgstr "电源设置"
#: ../js/ui/status/power.js:117 #: ../js/ui/status/power.js:112
#, c-format #, c-format
msgid "%d hour remaining" msgid "%d hour remaining"
msgid_plural "%d hours remaining" msgid_plural "%d hours remaining"
msgstr[0] "剩余 %d 小时" msgstr[0] "剩余 %d 小时"
#. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining" #. TRANSLATORS: this is a time string, as in "%d hours %d minutes remaining"
#: ../js/ui/status/power.js:120 #: ../js/ui/status/power.js:115
#, c-format #, c-format
msgid "%d %s %d %s remaining" msgid "%d %s %d %s remaining"
msgstr "剩余 %d %s %d %s" msgstr "剩余 %d %s %d %s"
#: ../js/ui/status/power.js:122 #: ../js/ui/status/power.js:117
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "小时" msgstr[0] "小时"
#: ../js/ui/status/power.js:122 #: ../js/ui/status/power.js:117
msgid "minute" msgid "minute"
msgid_plural "minutes" msgid_plural "minutes"
msgstr[0] "分钟" msgstr[0] "分钟"
#: ../js/ui/status/power.js:125 #: ../js/ui/status/power.js:120
#, c-format #, c-format
msgid "%d minute remaining" msgid "%d minute remaining"
msgid_plural "%d minutes remaining" msgid_plural "%d minutes remaining"
msgstr[0] "剩余 %d 分钟" msgstr[0] "剩余 %d 分钟"
#: ../js/ui/status/power.js:244 #: ../js/ui/status/power.js:237
msgid "AC adapter" msgid "AC adapter"
msgstr "AC 适配器" msgstr "AC 适配器"
#: ../js/ui/status/power.js:246 #: ../js/ui/status/power.js:239
msgid "Laptop battery" msgid "Laptop battery"
msgstr "笔记本电池" msgstr "笔记本电池"
#: ../js/ui/status/power.js:248 #: ../js/ui/status/power.js:241
msgid "UPS" msgid "UPS"
msgstr "UPS" msgstr "UPS"
#: ../js/ui/status/power.js:250 #: ../js/ui/status/power.js:243
msgid "Monitor" msgid "Monitor"
msgstr "显示器" msgstr "显示器"
#: ../js/ui/status/power.js:252 #: ../js/ui/status/power.js:245
msgid "Mouse" msgid "Mouse"
msgstr "鼠标" msgstr "鼠标"
#: ../js/ui/status/power.js:254 #: ../js/ui/status/power.js:247
msgid "Keyboard" msgid "Keyboard"
msgstr "键盘" msgstr "键盘"
#: ../js/ui/status/power.js:256 #: ../js/ui/status/power.js:249
msgid "PDA" msgid "PDA"
msgstr "PDA" msgstr "PDA"
#: ../js/ui/status/power.js:258 #: ../js/ui/status/power.js:251
msgid "Cell phone" msgid "Cell phone"
msgstr "手机" msgstr "手机"
#: ../js/ui/status/power.js:260 #: ../js/ui/status/power.js:253
msgid "Media player" msgid "Media player"
msgstr "媒体播放器" msgstr "媒体播放器"
#: ../js/ui/status/power.js:262 #: ../js/ui/status/power.js:255
msgid "Tablet" msgid "Tablet"
msgstr "触摸板" msgstr "触摸板"
#: ../js/ui/status/power.js:264 #: ../js/ui/status/power.js:257
msgid "Computer" msgid "Computer"
msgstr "计算机" msgstr "计算机"
#: ../js/ui/status/power.js:266 ../src/shell-app-system.c:1012 #: ../js/ui/status/power.js:259 ../src/shell-app-system.c:1012
msgid "Unknown" msgid "Unknown"
msgstr "未知" msgstr "未知"
@ -691,9 +821,33 @@ msgstr "音量"
msgid "Microphone" msgid "Microphone"
msgstr "麦克风" msgstr "麦克风"
#: ../js/ui/status/volume.js:62 #: ../js/ui/telepathyClient.js:560
msgid "Sound Settings" #, c-format
msgstr "声音设置" msgid "%s is online."
msgstr "%s 在线。"
#: ../js/ui/telepathyClient.js:565
#, c-format
msgid "%s is offline."
msgstr "%s 离线。"
#: ../js/ui/telepathyClient.js:568
#, c-format
msgid "%s is away."
msgstr "%s 离开。"
#: ../js/ui/telepathyClient.js:571
#, c-format
msgid "%s is busy."
msgstr "%s 忙碌。"
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:665
#, no-c-format
msgid "Sent at %X on %A"
msgstr "发送于 %X on %A"
#: ../js/ui/viewSelector.js:26 #: ../js/ui/viewSelector.js:26
msgid "Search your computer" msgid "Search your computer"
@ -738,29 +892,29 @@ msgstr[0] "%u 个输入"
msgid "System Sounds" msgid "System Sounds"
msgstr "系统声音" msgstr "系统声音"
#: ../src/shell-global.c:1155 #: ../src/shell-global.c:1156
msgid "Less than a minute ago" msgid "Less than a minute ago"
msgstr "少于一分钟前" msgstr "少于一分钟前"
#: ../src/shell-global.c:1159 #: ../src/shell-global.c:1160
#, c-format #, c-format
msgid "%d minute ago" msgid "%d minute ago"
msgid_plural "%d minutes ago" msgid_plural "%d minutes ago"
msgstr[0] "%d 分钟前" msgstr[0] "%d 分钟前"
#: ../src/shell-global.c:1164 #: ../src/shell-global.c:1165
#, c-format #, c-format
msgid "%d hour ago" msgid "%d hour ago"
msgid_plural "%d hours ago" msgid_plural "%d hours ago"
msgstr[0] "%d 小时前" msgstr[0] "%d 小时前"
#: ../src/shell-global.c:1169 #: ../src/shell-global.c:1170
#, c-format #, c-format
msgid "%d day ago" msgid "%d day ago"
msgid_plural "%d days ago" msgid_plural "%d days ago"
msgstr[0] "%d 天前" msgstr[0] "%d 天前"
#: ../src/shell-global.c:1174 #: ../src/shell-global.c:1175
#, c-format #, c-format
msgid "%d week ago" msgid "%d week ago"
msgid_plural "%d weeks ago" msgid_plural "%d weeks ago"
@ -790,6 +944,9 @@ msgstr "搜索"
msgid "%1$s: %2$s" msgid "%1$s: %2$s"
msgstr "%1$s: %2$s" msgstr "%1$s: %2$s"
#~ msgid "What's using power..."
#~ msgstr "哪些设备在用电..."
#~ msgid "Overview workspace view mode" #~ msgid "Overview workspace view mode"
#~ msgstr "工作区视图模式的总览" #~ msgstr "工作区视图模式的总览"
@ -830,9 +987,6 @@ msgstr "%1$s: %2$s"
#~ msgid "%H:%M" #~ msgid "%H:%M"
#~ msgstr "%H:%M" #~ msgstr "%H:%M"
#~ msgid "Applications"
#~ msgstr "应用程序"
#~ msgid "Recent Documents" #~ msgid "Recent Documents"
#~ msgstr "最近文档" #~ msgstr "最近文档"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
noinst_LTLIBRARIES += libcalendar-client.la
libcalendar_client_la_SOURCES = \
calendar-client/calendar-client.h calendar-client/calendar-client.c \
calendar-client/calendar-debug.h \
calendar-client/calendar-sources.c calendar-client/calendar-sources.h \
$(NULL)
libcalendar_client_la_CFLAGS = \
-I$(top_srcdir)/src \
-DPREFIX=\""$(prefix)"\" \
-DLIBDIR=\""$(libdir)"\" \
-DDATADIR=\""$(datadir)"\" \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"CalendarClient\" \
$(LIBECAL_CFLAGS) \
$(NULL)
libcalendar_client_la_LIBADD = $(LIBECAL_LIBS)
EXTRA_DIST += calendar-client/README

View File

@ -98,15 +98,22 @@ st_source_h = \
st/st-tooltip.h \ st/st-tooltip.h \
st/st-types.h \ st/st-types.h \
st/st-widget.h \ st/st-widget.h \
st/st-widget-accessible.h \
$(NULL) $(NULL)
st.h: Makefile st.h: stamp-st.h
@true
stamp-st.h: Makefile
$(AM_V_GEN) (echo "#define ST_H_INSIDE 1"; \ $(AM_V_GEN) (echo "#define ST_H_INSIDE 1"; \
for name in $(st_source_h); do \ for name in $(st_source_h); do \
echo "#include <"$$name">"; \ echo "#include <"$$name">"; \
done; echo "#undef ST_H_INSIDE") > st.h.tmp && mv st.h.tmp st.h done; echo "#undef ST_H_INSIDE") > $@.tmp && \
(cmp -s $@.tmp st.h || cp $@.tmp st.h) && \
rm -f $@.tmp && \
echo timestamp > $(@F)
BUILT_SOURCES += st.h BUILT_SOURCES += st.h
CLEANFILES += stamp-st.h
st_source_private_h = \ st_source_private_h = \
st/st-private.h \ st/st-private.h \
@ -152,11 +159,17 @@ st_source_c = \
st/st-widget.c \ st/st-widget.c \
$(NULL) $(NULL)
st_non_gir_sources = \
st/st-scroll-view-fade.c \
st/st-scroll-view-fade.h \
$(NULL)
noinst_LTLIBRARIES += libst-1.0.la noinst_LTLIBRARIES += libst-1.0.la
libst_1_0_la_LIBADD = -lm $(ST_LIBS) libst_1_0_la_LIBADD = -lm $(ST_LIBS)
libst_1_0_la_SOURCES = \ libst_1_0_la_SOURCES = \
$(st_source_c) \ $(st_source_c) \
$(st_non_gir_sources) \
$(st_source_private_h) \ $(st_source_private_h) \
$(st_source_private_c) \ $(st_source_private_c) \
$(st_source_h) \ $(st_source_h) \

View File

@ -15,7 +15,6 @@ TRAY_STAMP_FILES = stamp-na-marshal.h
# please, keep this sorted alphabetically # please, keep this sorted alphabetically
tray_source = \ tray_source = \
gtk-compat.h \
tray/na-tray-child.c \ tray/na-tray-child.c \
tray/na-tray-child.h \ tray/na-tray-child.h \
tray/na-tray-manager.c \ tray/na-tray-manager.c \

View File

@ -8,7 +8,7 @@ noinst_PROGRAMS =
.AUTOPARALLEL: .AUTOPARALLEL:
bin_SCRIPTS = gnome-shell gnome-shell-clock-preferences bin_SCRIPTS = gnome-shell
gnome-shell: gnome-shell.in gnome-shell: gnome-shell.in
$(AM_V_GEN) sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \ $(AM_V_GEN) sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \
@ -23,19 +23,11 @@ gnome-shell: gnome-shell.in
CLEANFILES += gnome-shell CLEANFILES += gnome-shell
EXTRA_DIST += gnome-shell.in EXTRA_DIST += gnome-shell.in
gnome-shell-clock-preferences: gnome-shell-clock-preferences.in
$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
-e "s|@localedir[@]|$(datadir)/locale|" \
-e "s|@GJS_CONSOLE[@]|$(GJS_CONSOLE)|" \
$< > $@ && chmod a+x $@
CLEANFILES += gnome-shell-clock-preferences
EXTRA_DIST += gnome-shell-clock-preferences.in
include Makefile-gdmuser.am include Makefile-gdmuser.am
include Makefile-st.am include Makefile-st.am
include Makefile-tray.am include Makefile-tray.am
include Makefile-gvc.am include Makefile-gvc.am
include Makefile-calendar-client.am
gnome_shell_cflags = \ gnome_shell_cflags = \
$(MUTTER_PLUGIN_CFLAGS) \ $(MUTTER_PLUGIN_CFLAGS) \
@ -68,7 +60,6 @@ shell_public_headers_h = \
shell-embedded-window.h \ shell-embedded-window.h \
shell-generic-container.h \ shell-generic-container.h \
shell-gtk-embed.h \ shell-gtk-embed.h \
shell-process.h \
shell-global.h \ shell-global.h \
shell-perf-log.h \ shell-perf-log.h \
shell-slicer.h \ shell-slicer.h \
@ -90,17 +81,19 @@ libgnome_shell_la_SOURCES = \
shell-window-tracker-private.h \ shell-window-tracker-private.h \
shell-wm-private.h \ shell-wm-private.h \
gnome-shell-plugin.c \ gnome-shell-plugin.c \
gtk-compat.h \
shell-app.c \ shell-app.c \
shell-a11y.h \
shell-a11y.c \
shell-app-system.c \ shell-app-system.c \
shell-app-usage.c \ shell-app-usage.c \
shell-arrow.c \ shell-arrow.c \
shell-doc-system.c \ shell-doc-system.c \
shell-drawing.c \ shell-drawing.c \
shell-embedded-window.c \ shell-embedded-window.c \
shell-evolution-event-source.h \
shell-evolution-event-source.c \
shell-generic-container.c \ shell-generic-container.c \
shell-gtk-embed.c \ shell-gtk-embed.c \
shell-process.c \
shell-global.c \ shell-global.c \
shell-perf-log.c \ shell-perf-log.c \
shell-slicer.c \ shell-slicer.c \
@ -222,7 +215,9 @@ libgnome_shell_la_LIBADD = \
libst-1.0.la \ libst-1.0.la \
libgdmuser-1.0.la \ libgdmuser-1.0.la \
libtray.la \ libtray.la \
libgvc.la libgvc.la \
libcalendar-client.la \
$(NULL)
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags) libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
@ -272,7 +267,7 @@ St-1.0.gir: $(mutter) $(G_IR_SCANNER) libst-1.0.la Makefile
--libtool="$(LIBTOOL)" \ --libtool="$(LIBTOOL)" \
--library=libst-1.0.la \ --library=libst-1.0.la \
-DST_COMPILATION \ -DST_COMPILATION \
$(filter-out %-private.h, $(addprefix $(srcdir)/,$(st_source_h))) \ $(filter-out %-private.h $(st_non_gir_sources), $(addprefix $(srcdir)/,$(st_source_h))) \
$(addprefix $(srcdir)/,$(st_source_c)) \ $(addprefix $(srcdir)/,$(st_source_c)) \
$(srcdir)/st-enum-types.h \ $(srcdir)/st-enum-types.h \
$(st_cflags) \ $(st_cflags) \

View File

@ -0,0 +1 @@
Please keep in sync with gnome-panel.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2004 Free Software Foundation, Inc.
*
* This program is free software; 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.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors:
* Mark McLoughlin <mark@skynet.ie>
* William Jon McCann <mccann@jhu.edu>
* Martin Grimme <martin@pycage.de>
* Christian Kellner <gicmo@xatom.net>
*/
#ifndef __CALENDAR_CLIENT_H__
#define __CALENDAR_CLIENT_H__
#include <glib-object.h>
G_BEGIN_DECLS
typedef enum
{
CALENDAR_EVENT_APPOINTMENT = 1 << 0,
CALENDAR_EVENT_TASK = 1 << 1,
CALENDAR_EVENT_ALL = (1 << 2) - 1
} CalendarEventType;
#define CALENDAR_TYPE_CLIENT (calendar_client_get_type ())
#define CALENDAR_CLIENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_CLIENT, CalendarClient))
#define CALENDAR_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_CLIENT, CalendarClientClass))
#define CALENDAR_IS_CLIENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_CLIENT))
#define CALENDAR_IS_CLIENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_CLIENT))
#define CALENDAR_CLIENT_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_CLIENT, CalendarClientClass))
typedef struct _CalendarClient CalendarClient;
typedef struct _CalendarClientClass CalendarClientClass;
typedef struct _CalendarClientPrivate CalendarClientPrivate;
struct _CalendarClient
{
GObject parent;
CalendarClientPrivate *priv;
};
struct _CalendarClientClass
{
GObjectClass parent_class;
void (* appointments_changed) (CalendarClient *client);
void (* tasks_changed) (CalendarClient *client);
};
typedef struct
{
time_t start_time;
time_t end_time;
} CalendarOccurrence;
typedef struct
{
char *uid;
char *rid;
char *uri;
char *summary;
char *description;
char *color_string;
time_t start_time;
time_t end_time;
guint is_all_day : 1;
/* Only used internally */
GSList *occurrences;
} CalendarAppointment;
typedef struct
{
char *uid;
char *summary;
char *description;
char *color_string;
char *url;
time_t start_time;
time_t due_time;
guint percent_complete;
time_t completed_time;
int priority;
} CalendarTask;
typedef struct
{
union
{
CalendarAppointment appointment;
CalendarTask task;
} event;
CalendarEventType type;
} CalendarEvent;
#define CALENDAR_EVENT(e) ((CalendarEvent *)(e))
#define CALENDAR_APPOINTMENT(e) ((CalendarAppointment *)(e))
#define CALENDAR_TASK(e) ((CalendarTask *)(e))
typedef void (* CalendarDayIter) (CalendarClient *client,
guint day,
gpointer user_data);
GType calendar_client_get_type (void) G_GNUC_CONST;
CalendarClient *calendar_client_new (void);
void calendar_client_get_date (CalendarClient *client,
guint *year,
guint *month,
guint *day);
void calendar_client_select_month (CalendarClient *client,
guint month,
guint year);
void calendar_client_select_day (CalendarClient *client,
guint day);
GSList *calendar_client_get_events (CalendarClient *client,
CalendarEventType event_mask);
void calendar_client_foreach_appointment_day (CalendarClient *client,
CalendarDayIter iter_func,
gpointer user_data);
void calendar_client_set_task_completed (CalendarClient *client,
char *task_uid,
gboolean task_completed,
guint percent_complete);
void calendar_event_free (CalendarEvent *event);
G_END_DECLS
#endif /* __CALENDAR_CLIENT_H__ */

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2004 Free Software Foundation, Inc.
*
* This program is free software; 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.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors:
* Mark McLoughlin <mark@skynet.ie>
*/
#ifndef __CALENDAR_DEBUG_H__
#define __CALENDAR_DEBUG_H__
#include <glib.h>
G_BEGIN_DECLS
#ifdef CALENDAR_ENABLE_DEBUG
#include <stdio.h>
#ifdef G_HAVE_ISO_VARARGS
# define dprintf(...) fprintf (stderr, __VA_ARGS__);
#elif defined(G_HAVE_GNUC_VARARGS)
# define dprintf(args...) fprintf (stderr, args);
#endif
#else /* if !defined (CALENDAR_DEBUG) */
#ifdef G_HAVE_ISO_VARARGS
# define dprintf(...)
#elif defined(G_HAVE_GNUC_VARARGS)
# define dprintf(args...)
#endif
#endif /* CALENDAR_ENABLE_DEBUG */
G_END_DECLS
#endif /* __CALENDAR_DEBUG_H__ */

View File

@ -0,0 +1,658 @@
/*
* Copyright (C) 2004 Free Software Foundation, Inc.
*
* This program is free software; 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.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors:
* Mark McLoughlin <mark@skynet.ie>
* William Jon McCann <mccann@jhu.edu>
* Martin Grimme <martin@pycage.de>
* Christian Kellner <gicmo@xatom.net>
*/
#include <config.h>
#include "calendar-sources.h"
#include <libintl.h>
#include <string.h>
#include <gconf/gconf-client.h>
#define HANDLE_LIBICAL_MEMORY
#include <libecal/e-cal.h>
#include <libedataserver/e-source-list.h>
#include <libedataserverui/e-passwords.h>
#undef CALENDAR_ENABLE_DEBUG
#include "calendar-debug.h"
#ifndef _
#define _(x) gettext(x)
#endif
#ifndef N_
#define N_(x) x
#endif
#define CALENDAR_SOURCES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesPrivate))
#define CALENDAR_SOURCES_EVO_DIR "/apps/evolution"
#define CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/calendar/sources"
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/display"
#define CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR "/selected_calendars"
#define CALENDAR_SOURCES_TASK_SOURCES_KEY CALENDAR_SOURCES_EVO_DIR "/tasks/sources"
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR CALENDAR_SOURCES_EVO_DIR "/calendar/tasks"
#define CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR "/selected_tasks"
typedef struct _CalendarSourceData CalendarSourceData;
struct _CalendarSourceData
{
ECalSourceType source_type;
CalendarSources *sources;
guint changed_signal;
GSList *clients;
GSList *selected_sources;
ESourceList *esource_list;
guint selected_sources_listener;
char *selected_sources_dir;
guint timeout_id;
guint loaded : 1;
};
struct _CalendarSourcesPrivate
{
CalendarSourceData appointment_sources;
CalendarSourceData task_sources;
GConfClient *gconf_client;
};
static void calendar_sources_class_init (CalendarSourcesClass *klass);
static void calendar_sources_init (CalendarSources *sources);
static void calendar_sources_finalize (GObject *object);
static void backend_died_cb (ECal *client, CalendarSourceData *source_data);
static void calendar_sources_esource_list_changed (ESourceList *source_list,
CalendarSourceData *source_data);
enum
{
APPOINTMENT_SOURCES_CHANGED,
TASK_SOURCES_CHANGED,
LAST_SIGNAL
};
static guint signals [LAST_SIGNAL] = { 0, };
static GObjectClass *parent_class = NULL;
static CalendarSources *calendar_sources_singleton = NULL;
GType
calendar_sources_get_type (void)
{
static GType sources_type = 0;
if (!sources_type)
{
static const GTypeInfo sources_info =
{
sizeof (CalendarSourcesClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) calendar_sources_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (CalendarSources),
0, /* n_preallocs */
(GInstanceInitFunc) calendar_sources_init,
};
sources_type = g_type_register_static (G_TYPE_OBJECT,
"CalendarSources",
&sources_info, 0);
}
return sources_type;
}
static void
calendar_sources_class_init (CalendarSourcesClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->finalize = calendar_sources_finalize;
g_type_class_add_private (klass, sizeof (CalendarSourcesPrivate));
signals [APPOINTMENT_SOURCES_CHANGED] =
g_signal_new ("appointment-sources-changed",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (CalendarSourcesClass,
appointment_sources_changed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
signals [TASK_SOURCES_CHANGED] =
g_signal_new ("task-sources-changed",
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (CalendarSourcesClass,
task_sources_changed),
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static void
calendar_sources_init (CalendarSources *sources)
{
sources->priv = CALENDAR_SOURCES_GET_PRIVATE (sources);
sources->priv->appointment_sources.source_type = E_CAL_SOURCE_TYPE_EVENT;
sources->priv->appointment_sources.sources = sources;
sources->priv->appointment_sources.changed_signal = signals [APPOINTMENT_SOURCES_CHANGED];
sources->priv->appointment_sources.timeout_id = 0;
sources->priv->task_sources.source_type = E_CAL_SOURCE_TYPE_TODO;
sources->priv->task_sources.sources = sources;
sources->priv->task_sources.changed_signal = signals [TASK_SOURCES_CHANGED];
sources->priv->task_sources.timeout_id = 0;
sources->priv->gconf_client = gconf_client_get_default ();
}
static void
calendar_sources_finalize_source_data (CalendarSources *sources,
CalendarSourceData *source_data)
{
if (source_data->loaded)
{
GSList *l;
if (source_data->selected_sources_dir)
{
gconf_client_remove_dir (sources->priv->gconf_client,
source_data->selected_sources_dir,
NULL);
g_free (source_data->selected_sources_dir);
source_data->selected_sources_dir = NULL;
}
if (source_data->selected_sources_listener)
{
gconf_client_notify_remove (sources->priv->gconf_client,
source_data->selected_sources_listener);
source_data->selected_sources_listener = 0;
}
for (l = source_data->clients; l; l = l->next)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
G_CALLBACK (backend_died_cb),
source_data);
g_object_unref (l->data);
}
g_slist_free (source_data->clients);
source_data->clients = NULL;
if (source_data->esource_list)
{
g_signal_handlers_disconnect_by_func (source_data->esource_list,
G_CALLBACK (calendar_sources_esource_list_changed),
source_data);
g_object_unref (source_data->esource_list);
}
source_data->esource_list = NULL;
for (l = source_data->selected_sources; l; l = l->next)
g_free (l->data);
g_slist_free (source_data->selected_sources);
source_data->selected_sources = NULL;
if (source_data->timeout_id != 0)
{
g_source_remove (source_data->timeout_id);
source_data->timeout_id = 0;
}
source_data->loaded = FALSE;
}
}
static void
calendar_sources_finalize (GObject *object)
{
CalendarSources *sources = CALENDAR_SOURCES (object);
calendar_sources_finalize_source_data (sources, &sources->priv->appointment_sources);
calendar_sources_finalize_source_data (sources, &sources->priv->task_sources);
if (sources->priv->gconf_client)
g_object_unref (sources->priv->gconf_client);
sources->priv->gconf_client = NULL;
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
CalendarSources *
calendar_sources_get (void)
{
gpointer singleton_location = &calendar_sources_singleton;
if (calendar_sources_singleton)
return g_object_ref (calendar_sources_singleton);
calendar_sources_singleton = g_object_new (CALENDAR_TYPE_SOURCES, NULL);
g_object_add_weak_pointer (G_OBJECT (calendar_sources_singleton),
singleton_location);
return calendar_sources_singleton;
}
static gboolean
is_source_selected (ESource *esource,
GSList *selected_sources)
{
const char *uid;
GSList *l;
uid = e_source_peek_uid (esource);
for (l = selected_sources; l; l = l->next)
{
const char *source = l->data;
if (!strcmp (source, uid))
return TRUE;
}
return FALSE;
}
static char *
auth_func_cb (ECal *ecal,
const char *prompt,
const char *key,
gpointer user_data)
{
ESource *source;
const gchar *auth_domain;
const gchar *component_name;
source = e_cal_get_source (ecal);
auth_domain = e_source_get_property (source, "auth-domain");
component_name = auth_domain ? auth_domain : "Calendar";
return e_passwords_get_password (component_name, key);
}
/* The clients are just created here but not loaded */
static ECal *
get_ecal_from_source (ESource *esource,
ECalSourceType source_type,
GSList *existing_clients)
{
ECal *retval;
if (existing_clients)
{
GSList *l;
for (l = existing_clients; l; l = l->next)
{
ECal *client = E_CAL (l->data);
if (e_source_equal (esource, e_cal_get_source (client)))
{
dprintf (" load_esource: found existing source ... returning that\n");
return g_object_ref (client);
}
}
}
retval = e_cal_new (esource, source_type);
if (!retval)
{
g_warning ("Could not load source '%s' from '%s'\n",
e_source_peek_name (esource),
e_source_peek_relative_uri (esource));
return NULL;
}
e_cal_set_auth_func (retval, auth_func_cb, NULL);
return retval;
}
/* - Order doesn't matter
* - Can just compare object pointers since we
* re-use client connections
*/
static gboolean
compare_ecal_lists (GSList *a,
GSList *b)
{
GSList *l;
if (g_slist_length (a) != g_slist_length (b))
return FALSE;
for (l = a; l; l = l->next)
{
if (!g_slist_find (b, l->data))
return FALSE;
}
return TRUE;
}
static inline void
debug_dump_selected_sources (GSList *selected_sources)
{
#ifdef CALENDAR_ENABLE_DEBUG
GSList *l;
dprintf ("Selected sources:\n");
for (l = selected_sources; l; l = l->next)
{
char *source = l->data;
dprintf (" %s\n", source);
}
dprintf ("\n");
#endif
}
static inline void
debug_dump_ecal_list (GSList *ecal_list)
{
#ifdef CALENDAR_ENABLE_DEBUG
GSList *l;
dprintf ("Loaded clients:\n");
for (l = ecal_list; l; l = l->next)
{
ECal *client = l->data;
ESource *source = e_cal_get_source (client);
dprintf (" %s %s %s\n",
e_source_peek_uid (source),
e_source_peek_name (source),
e_cal_get_uri (client));
}
#endif
}
static void
calendar_sources_load_esource_list (CalendarSourceData *source_data);
static gboolean
backend_restart (gpointer data)
{
CalendarSourceData *source_data = data;
calendar_sources_load_esource_list (source_data);
source_data->timeout_id = 0;
return FALSE;
}
static void
backend_died_cb (ECal *client, CalendarSourceData *source_data)
{
const char *uristr;
source_data->clients = g_slist_remove (source_data->clients, client);
if (g_slist_length (source_data->clients) < 1)
{
g_slist_free (source_data->clients);
source_data->clients = NULL;
}
uristr = e_cal_get_uri (client);
g_warning ("The calendar backend for %s has crashed.", uristr);
if (source_data->timeout_id != 0)
{
g_source_remove (source_data->timeout_id);
source_data->timeout_id = 0;
}
source_data->timeout_id = g_timeout_add_seconds (2, backend_restart,
source_data);
}
static void
calendar_sources_load_esource_list (CalendarSourceData *source_data)
{
GSList *clients = NULL;
GSList *groups, *l;
gboolean emit_signal = FALSE;
g_return_if_fail (source_data->esource_list != NULL);
debug_dump_selected_sources (source_data->selected_sources);
dprintf ("Source groups:\n");
groups = e_source_list_peek_groups (source_data->esource_list);
for (l = groups; l; l = l->next)
{
GSList *esources, *s;
dprintf (" %s\n", e_source_group_peek_uid (l->data));
dprintf (" sources:\n");
esources = e_source_group_peek_sources (l->data);
for (s = esources; s; s = s->next)
{
ESource *esource = E_SOURCE (s->data);
ECal *client;
dprintf (" type = '%s' uid = '%s', name = '%s', relative uri = '%s': \n",
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task",
e_source_peek_uid (esource),
e_source_peek_name (esource),
e_source_peek_relative_uri (esource));
if (is_source_selected (esource, source_data->selected_sources) &&
(client = get_ecal_from_source (esource, source_data->source_type, source_data->clients)))
{
clients = g_slist_prepend (clients, client);
}
}
}
dprintf ("\n");
if (source_data->loaded &&
!compare_ecal_lists (source_data->clients, clients))
emit_signal = TRUE;
for (l = source_data->clients; l; l = l->next)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (l->data),
G_CALLBACK (backend_died_cb),
source_data);
g_object_unref (l->data);
}
g_slist_free (source_data->clients);
source_data->clients = g_slist_reverse (clients);
/* connect to backend_died after we disconnected the previous signal
* handlers. If we do it before, we'll lose some handlers (for clients that
* were already there before) */
for (l = source_data->clients; l; l = l->next)
{
g_signal_connect (G_OBJECT (l->data), "backend_died",
G_CALLBACK (backend_died_cb), source_data);
}
if (emit_signal)
{
dprintf ("Emitting %s-sources-changed signal\n",
source_data->source_type == E_CAL_SOURCE_TYPE_EVENT ? "appointment" : "task");
g_signal_emit (source_data->sources, source_data->changed_signal, 0);
}
debug_dump_ecal_list (source_data->clients);
}
static void
calendar_sources_esource_list_changed (ESourceList *source_list,
CalendarSourceData *source_data)
{
dprintf ("ESourceList changed, reloading\n");
calendar_sources_load_esource_list (source_data);
}
static void
calendar_sources_selected_sources_notify (GConfClient *client,
guint cnx_id,
GConfEntry *entry,
CalendarSourceData *source_data)
{
GSList *l;
if (!entry->value ||
entry->value->type != GCONF_VALUE_LIST ||
gconf_value_get_list_type (entry->value) != GCONF_VALUE_STRING)
return;
dprintf ("Selected sources key (%s) changed, reloading\n", entry->key);
for (l = source_data->selected_sources; l; l = l->next)
g_free (l->data);
source_data->selected_sources = NULL;
for (l = gconf_value_get_list (entry->value); l; l = l->next)
{
const char *source = gconf_value_get_string (l->data);
source_data->selected_sources =
g_slist_prepend (source_data->selected_sources,
g_strdup (source));
}
source_data->selected_sources =
g_slist_reverse (source_data->selected_sources);
calendar_sources_load_esource_list (source_data);
}
static void
calendar_sources_load_sources (CalendarSources *sources,
CalendarSourceData *source_data,
const char *sources_key,
const char *selected_sources_key,
const char *selected_sources_dir)
{
GConfClient *gconf_client;
GError *error;
dprintf ("---------------------------\n");
dprintf ("Loading sources:\n");
dprintf (" sources_key: %s\n", sources_key);
dprintf (" selected_sources_key: %s\n", selected_sources_key);
dprintf (" selected_sources_dir: %s\n", selected_sources_dir);
gconf_client = sources->priv->gconf_client;
error = NULL;
source_data->selected_sources = gconf_client_get_list (gconf_client,
selected_sources_key,
GCONF_VALUE_STRING,
&error);
if (error)
{
g_warning ("Failed to get selected sources from '%s': %s\n",
selected_sources_key,
error->message);
g_error_free (error);
return;
}
gconf_client_add_dir (gconf_client,
selected_sources_dir,
GCONF_CLIENT_PRELOAD_NONE,
NULL);
source_data->selected_sources_dir = g_strdup (selected_sources_dir);
source_data->selected_sources_listener =
gconf_client_notify_add (gconf_client,
selected_sources_dir,
(GConfClientNotifyFunc) calendar_sources_selected_sources_notify,
source_data, NULL, NULL);
source_data->esource_list = e_source_list_new_for_gconf (gconf_client, sources_key);
g_signal_connect (source_data->esource_list, "changed",
G_CALLBACK (calendar_sources_esource_list_changed),
source_data);
calendar_sources_load_esource_list (source_data);
source_data->loaded = TRUE;
dprintf ("---------------------------\n");
}
GSList *
calendar_sources_get_appointment_sources (CalendarSources *sources)
{
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
if (!sources->priv->appointment_sources.loaded)
{
calendar_sources_load_sources (sources,
&sources->priv->appointment_sources,
CALENDAR_SOURCES_APPOINTMENT_SOURCES_KEY,
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_KEY,
CALENDAR_SOURCES_SELECTED_APPOINTMENT_SOURCES_DIR);
}
return sources->priv->appointment_sources.clients;
}
GSList *
calendar_sources_get_task_sources (CalendarSources *sources)
{
g_return_val_if_fail (CALENDAR_IS_SOURCES (sources), NULL);
if (!sources->priv->task_sources.loaded)
{
calendar_sources_load_sources (sources,
&sources->priv->task_sources,
CALENDAR_SOURCES_TASK_SOURCES_KEY,
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_KEY,
CALENDAR_SOURCES_SELECTED_TASK_SOURCES_DIR);
}
return sources->priv->task_sources.clients;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2004 Free Software Foundation, Inc.
*
* This program is free software; 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.
*
* This program 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors:
* Mark McLoughlin <mark@skynet.ie>
* William Jon McCann <mccann@jhu.edu>
* Martin Grimme <martin@pycage.de>
* Christian Kellner <gicmo@xatom.net>
*/
#ifndef __CALENDAR_SOURCES_H__
#define __CALENDAR_SOURCES_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define CALENDAR_TYPE_SOURCES (calendar_sources_get_type ())
#define CALENDAR_SOURCES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CALENDAR_TYPE_SOURCES, CalendarSources))
#define CALENDAR_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
#define CALENDAR_IS_SOURCES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CALENDAR_TYPE_SOURCES))
#define CALENDAR_IS_SOURCES_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CALENDAR_TYPE_SOURCES))
#define CALENDAR_SOURCES_GET_CLASS(o)(G_TYPE_INSTANCE_GET_CLASS ((o), CALENDAR_TYPE_SOURCES, CalendarSourcesClass))
typedef struct _CalendarSources CalendarSources;
typedef struct _CalendarSourcesClass CalendarSourcesClass;
typedef struct _CalendarSourcesPrivate CalendarSourcesPrivate;
struct _CalendarSources
{
GObject parent;
CalendarSourcesPrivate *priv;
};
struct _CalendarSourcesClass
{
GObjectClass parent_class;
void (* appointment_sources_changed) (CalendarSources *sources);
void (* task_sources_changed) (CalendarSources *sources);
};
GType calendar_sources_get_type (void) G_GNUC_CONST;
CalendarSources *calendar_sources_get (void);
GSList *calendar_sources_get_appointment_sources (CalendarSources *sources);
GSList *calendar_sources_get_task_sources (CalendarSources *sources);
G_END_DECLS
#endif /* __CALENDAR_SOURCES_H__ */

View File

@ -1020,13 +1020,10 @@ on_get_unix_user_finished (DBusGProxy *proxy,
DBusGProxyCall *call, DBusGProxyCall *call,
GdmUserManagerNewSession *new_session) GdmUserManagerNewSession *new_session)
{ {
GdmUserManager *manager;
GError *error; GError *error;
guint uid; guint uid;
gboolean res; gboolean res;
manager = new_session->manager;
g_assert (new_session->get_unix_user_call == call); g_assert (new_session->get_unix_user_call == call);
error = NULL; error = NULL;
@ -1550,11 +1547,9 @@ static void
get_accounts_proxy (GdmUserManager *manager) get_accounts_proxy (GdmUserManager *manager)
{ {
DBusGProxy *proxy; DBusGProxy *proxy;
GError *error;
g_assert (manager->priv->accounts_proxy == NULL); g_assert (manager->priv->accounts_proxy == NULL);
error = NULL;
proxy = dbus_g_proxy_new_for_name (manager->priv->connection, proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
ACCOUNTS_NAME, ACCOUNTS_NAME,
ACCOUNTS_PATH, ACCOUNTS_PATH,
@ -2554,8 +2549,6 @@ reload_shells (GdmUserManager *manager)
static void static void
load_users_manually (GdmUserManager *manager) load_users_manually (GdmUserManager *manager)
{ {
gboolean res;
manager->priv->shells = g_hash_table_new_full (g_str_hash, manager->priv->shells = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
@ -2564,7 +2557,7 @@ load_users_manually (GdmUserManager *manager)
load_sessions (manager); load_sessions (manager);
res = load_ck_history (manager); load_ck_history (manager);
schedule_reload_passwd (manager); schedule_reload_passwd (manager);
} }
@ -2605,10 +2598,8 @@ load_seat_incrementally (GdmUserManager *manager)
} }
if (manager->priv->seat.state == GDM_USER_MANAGER_SEAT_STATE_LOADED) { if (manager->priv->seat.state == GDM_USER_MANAGER_SEAT_STATE_LOADED) {
gboolean res;
load_sessions (manager); load_sessions (manager);
res = load_ck_history (manager); load_ck_history (manager);
} }
maybe_set_is_loaded (manager); maybe_set_is_loaded (manager);
@ -3059,15 +3050,6 @@ gdm_user_manager_finalize (GObject *object)
G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object); G_OBJECT_CLASS (gdm_user_manager_parent_class)->finalize (object);
} }
static void
gdm_user_muted_debug_log_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer data)
{
/* Intentionally empty to discard message */
}
/** /**
* gdm_user_manager_ref_default: * gdm_user_manager_ref_default:
* *
@ -3086,11 +3068,6 @@ gdm_user_manager_ref_default (void)
user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL); user_manager_object = g_object_new (GDM_TYPE_USER_MANAGER, NULL);
g_object_add_weak_pointer (user_manager_object, g_object_add_weak_pointer (user_manager_object,
(gpointer *) &user_manager_object); (gpointer *) &user_manager_object);
/* We don't normally care about user manager messages in the shell,
* so mute them */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
gdm_user_muted_debug_log_handler, NULL);
} }
return GDM_USER_MANAGER (user_manager_object); return GDM_USER_MANAGER (user_manager_object);

View File

@ -151,10 +151,6 @@ gdm_user_set_property (GObject *object,
const GValue *value, const GValue *value,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GdmUser *user;
user = GDM_USER (object);
switch (prop_id) { switch (prop_id) {
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

View File

@ -1,24 +0,0 @@
#!/bin/sh
if [ -f "$0.in" ]
then
scriptDir="`dirname $0`"
uiDir="$scriptDir/../data"
jsDir="$scriptDir/../js"
schemaDir="$scriptDir/../data"
else
uiDir="@pkgdatadir@"
jsDir="@pkgdatadir@/js"
schemaDir="@datadir@/glib-2.0/schemas"
fi
progName="`basename $0`"
localeDir="@localedir@"
uiFile="$uiDir/clock-preferences.ui"
export GJS_PATH="$jsDir"
export GSETTINGS_SCHEMA_DIR="$schemaDir"
@GJS_CONSOLE@ --js-version 1.8 -c "const ClockPreferences = imports.prefs.clockPreferences;
ClockPreferences.main({ progName: '$progName',
uiFile: '$uiFile',
localeDir: '$localeDir' });"

View File

@ -52,6 +52,7 @@
#include "shell-perf-log.h" #include "shell-perf-log.h"
#include "shell-wm-private.h" #include "shell-wm-private.h"
#include "st.h" #include "st.h"
#include "shell-a11y.h"
static void gnome_shell_plugin_dispose (GObject *object); static void gnome_shell_plugin_dispose (GObject *object);
static void gnome_shell_plugin_finalize (GObject *object); static void gnome_shell_plugin_finalize (GObject *object);
@ -113,6 +114,8 @@ struct _GnomeShellPlugin
int glx_error_base; int glx_error_base;
int glx_event_base; int glx_event_base;
guint have_swap_event : 1; guint have_swap_event : 1;
ShellGlobal *global;
}; };
struct _GnomeShellPluginClass struct _GnomeShellPluginClass
@ -299,11 +302,104 @@ add_statistics (GnomeShellPlugin *shell_plugin)
NULL, NULL); NULL, NULL);
} }
/* This is an IBus workaround. The flow of events with IBus is that every time
* it gets gets a key event, it:
*
* Sends it to the daemon via D-Bus asynchronously
* When it gets an reply, synthesizes a new GdkEvent and puts it into the
* GDK event queue with gdk_event_put(), including
* IBUS_FORWARD_MASK = 1 << 25 in the state to prevent a loop.
*
* (Normally, IBus uses the GTK+ key snooper mechanism to get the key
* events early, but since our key events aren't visible to GTK+ key snoopers,
* IBus will instead get the events via the standard
* GtkIMContext.filter_keypress() mechanism.)
*
* There are a number of potential problems here; probably the worst
* problem is that IBus doesn't forward the timestamp with the event
* so that every key event that gets delivered ends up with
* GDK_CURRENT_TIME. This creates some very subtle bugs; for example
* if you have IBus running and a keystroke is used to trigger
* launching an application, focus stealing prevention won't work
* right. http://code.google.com/p/ibus/issues/detail?id=1184
*
* In any case, our normal flow of key events is:
*
* GDK filter function => clutter_x11_handle_event => clutter actor
*
* So, if we see a key event that gets delivered via the GDK event handler
* function - then we know it must be one of these synthesized events, and
* we should push it back to clutter.
*
* To summarize, the full key event flow with IBus is:
*
* GDK filter function
* => Mutter
* => gnome_shell_plugin_xevent_filter()
* => clutter_x11_handle_event()
* => clutter event delivery to actor
* => gtk_im_context_filter_event()
* => sent to IBus daemon
* => response received from IBus daemon
* => gdk_event_put()
* => GDK event handler
* => <this function>
* => clutter_event_put()
* => clutter event delivery to actor
*
* Anything else we see here we just pass on to the normal GDK event handler
* gtk_main_do_event().
*/
static void static void
gvc_muted_debug_log_handler (const char *log_domain, gnome_shell_gdk_event_handler (GdkEvent *event_gdk,
GLogLevelFlags log_level, gpointer data)
const char *message, {
gpointer data) if (event_gdk->type == GDK_KEY_PRESS || event_gdk->type == GDK_KEY_RELEASE)
{
ClutterActor *stage;
Window stage_xwindow;
stage = clutter_stage_get_default ();
stage_xwindow = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
if (GDK_WINDOW_XID (event_gdk->key.window) == stage_xwindow)
{
ClutterDeviceManager *device_manager = clutter_device_manager_get_default ();
ClutterInputDevice *keyboard = clutter_device_manager_get_core_device (device_manager,
CLUTTER_KEYBOARD_DEVICE);
ClutterEvent *event_clutter = clutter_event_new ((event_gdk->type == GDK_KEY_RELEASE) ?
CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
event_clutter->key.time = event_gdk->key.time;
event_clutter->key.flags = CLUTTER_EVENT_NONE;
event_clutter->key.stage = CLUTTER_STAGE (stage);
event_clutter->key.source = NULL;
/* This depends on ClutterModifierType and GdkModifierType being
* identical, which they are currently. (They both match the X
* modifier state in the low 16-bits and have the same extensions.) */
event_clutter->key.modifier_state = event_gdk->key.state;
event_clutter->key.keyval = event_gdk->key.keyval;
event_clutter->key.hardware_keycode = event_gdk->key.hardware_keycode;
event_clutter->key.unicode_value = gdk_keyval_to_unicode (event_clutter->key.keyval);
event_clutter->key.device = keyboard;
clutter_event_put (event_clutter);
clutter_event_free (event_clutter);
return;
}
}
gtk_main_do_event (event_gdk);
}
static void
muted_log_handler (const char *log_domain,
GLogLevelFlags log_level,
const char *message,
gpointer data)
{ {
/* Intentionally empty to discard message */ /* Intentionally empty to discard message */
} }
@ -320,12 +416,13 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
int status; int status;
const char *shell_js; const char *shell_js;
char **search_path; char **search_path;
ShellGlobal *global;
const char *glx_extensions; const char *glx_extensions;
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
shell_a11y_init ();
settings = gtk_settings_get_default (); settings = gtk_settings_get_default ();
g_object_connect (settings, g_object_connect (settings,
"signal::notify::gtk-xft-dpi", "signal::notify::gtk-xft-dpi",
@ -339,6 +436,8 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
NULL); NULL);
update_font_options (settings); update_font_options (settings);
gdk_event_handler_set (gnome_shell_gdk_event_handler, plugin, NULL);
screen = meta_plugin_get_screen (plugin); screen = meta_plugin_get_screen (plugin);
display = meta_screen_get_display (screen); display = meta_screen_get_display (screen);
@ -374,15 +473,19 @@ gnome_shell_plugin_start (MetaPlugin *plugin)
NULL); NULL);
g_strfreev(search_path); g_strfreev(search_path);
/* Disable the gnome-volume-control debug */ /* Disable debug spew from various libraries */
g_log_set_handler ("Gvc", G_LOG_LEVEL_DEBUG, g_log_set_handler ("Gvc", G_LOG_LEVEL_DEBUG,
gvc_muted_debug_log_handler, NULL); muted_log_handler, NULL);
g_log_set_handler ("GdmUser", G_LOG_LEVEL_DEBUG,
muted_log_handler, NULL);
g_log_set_handler ("libgnome-bluetooth", G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_MESSAGE,
muted_log_handler, NULL);
/* Initialize the global object here. */ /* Initialize the global object here. */
global = shell_global_get (); shell_plugin->global = shell_global_get ();
_shell_global_set_plugin (global, META_PLUGIN(shell_plugin)); _shell_global_set_plugin (shell_plugin->global, META_PLUGIN(shell_plugin));
_shell_global_set_gjs_context (global, shell_plugin->gjs_context); _shell_global_set_gjs_context (shell_plugin->global, shell_plugin->gjs_context);
add_statistics (shell_plugin); add_statistics (shell_plugin);
@ -511,9 +614,9 @@ static gboolean
gnome_shell_plugin_xevent_filter (MetaPlugin *plugin, gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev) XEvent *xev)
{ {
#ifdef GLX_INTEL_swap_event
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
GnomeShellPlugin *shell_plugin = GNOME_SHELL_PLUGIN (plugin);
#ifdef GLX_INTEL_swap_event
if (shell_plugin->have_swap_event && if (shell_plugin->have_swap_event &&
xev->type == (shell_plugin->glx_event_base + GLX_BufferSwapComplete)) xev->type == (shell_plugin->glx_event_base + GLX_BufferSwapComplete))
{ {
@ -545,6 +648,12 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
&& xev->xcrossing.window == clutter_x11_get_stage_window (CLUTTER_STAGE (clutter_stage_get_default ()))) && xev->xcrossing.window == clutter_x11_get_stage_window (CLUTTER_STAGE (clutter_stage_get_default ())))
return TRUE; return TRUE;
/*
* Pass the event to shell-global
*/
if (_shell_global_check_xdnd_event (shell_plugin->global, xev))
return TRUE;
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE; return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
} }

View File

@ -152,7 +152,7 @@ def start_dconf_await_service():
# dconf is linked without libtool, so unlike other GNOME modules, # dconf is linked without libtool, so unlike other GNOME modules,
# won't have an embedded rpath for its library directory. # won't have an embedded rpath for its library directory.
env = dict(os.environ) env = dict(os.environ)
if 'LD_LIBRARY_PATH' in env: if 'LD_LIBRARY_PATH' in env and env['LD_LIBRARY_PATH']:
ld_library_path = '@libdir@:' + env['LD_LIBRARY_PATH'] ld_library_path = '@libdir@:' + env['LD_LIBRARY_PATH']
else: else:
ld_library_path = '@libdir@' ld_library_path = '@libdir@'
@ -219,12 +219,23 @@ def start_shell(perf_output=None):
js_dir = os.path.join('@pkgdatadir@', 'js') js_dir = os.path.join('@pkgdatadir@', 'js')
# Set up environment # Set up environment
# About the value of NO_GAIL and NO_AT_BRIDGE: If a11y is enabled,
# gtk_init() will normally load gail and at-bridge. But we don't
# want at-bridge to be loaded until after clutter is initialized
# (which mutter does after initializing gtk) and we don't want
# gail to be loaded at all. So set these flags. shell_a11y_init()
# will clear them so they don't get passed to gnome-shell's
# children.
env = dict(os.environ) env = dict(os.environ)
env.update({'GNOME_SHELL_JS' : js_dir, env.update({'GNOME_SHELL_JS' : js_dir,
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''), 'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
'XDG_CONFIG_DIRS' : '@sysconfdir@/xdg:' + (os.environ.get('XDG_CONFIG_DIRS') or '/etc/xdg'), 'XDG_CONFIG_DIRS' : '@sysconfdir@/xdg:' + (os.environ.get('XDG_CONFIG_DIRS') or '/etc/xdg'),
'XDG_DATA_DIRS' : '@datadir@:' + (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share'), 'XDG_DATA_DIRS' : '@datadir@:' + (os.environ.get('XDG_DATA_DIRS') or '/usr/local/share:/usr/share'),
'GNOME_DISABLE_CRASH_DIALOG' : '1'}) 'GNOME_DISABLE_CRASH_DIALOG' : '1',
'NO_GAIL' : '1',
'NO_AT_BRIDGE' : '1'})
if running_from_source_tree: if running_from_source_tree:
env.update({'GNOME_SHELL_DATADIR' : data_dir, env.update({'GNOME_SHELL_DATADIR' : data_dir,
@ -246,7 +257,7 @@ def start_shell(perf_output=None):
if pkgconfig.returncode == 0: if pkgconfig.returncode == 0:
mozjs_libdir = re.sub('-(sdk|devel)', '', mozjs_sdkdir) mozjs_libdir = re.sub('-(sdk|devel)', '', mozjs_sdkdir)
if os.path.exists(mozjs_libdir + '/libmozjs.so'): if os.path.exists(mozjs_libdir + '/libmozjs.so'):
if 'LD_LIBRARY_PATH' in env: if 'LD_LIBRARY_PATH' in env and env['LD_LIBRARY_PATH']:
ld_library_path = env['LD_LIBRARY_PATH'] + ':' + mozjs_libdir ld_library_path = env['LD_LIBRARY_PATH'] + ':' + mozjs_libdir
else: else:
ld_library_path = mozjs_libdir ld_library_path = mozjs_libdir
@ -672,7 +683,8 @@ use an extension title clicktofocus@janedoe.example.com.'''
os.makedirs(extension_path) os.makedirs(extension_path)
meta = { 'name': name, meta = { 'name': name,
'description': description, 'description': description,
'uuid': uuid } 'uuid': uuid,
'shell-version': ['@VERSION@'] }
f = open(os.path.join(extension_path, 'metadata.json'), 'w') f = open(os.path.join(extension_path, 'metadata.json'), 'w')
try: try:
json.dump(meta, f) json.dump(meta, f)

View File

@ -1,19 +0,0 @@
#ifndef __GTK_COMPAT_H__
#define __GTK_COMPAT_H__
#include <gtk/gtk.h>
/* Provide a compatibility layer for accessor functions introduced
* in GTK+ 2.20 which we need to build with GSEAL_ENABLE.
* That way it is still possible to build with GTK+ 2.18 when not
* using GSEAL_ENABLE
*/
#if !GTK_CHECK_VERSION(2, 20, 0)
#define gtk_widget_get_realized(w) GTK_WIDGET_REALIZED (w)
#define gtk_widget_get_mapped(w) GTK_WIDGET_MAPPED (w)
#endif /* GTK_CHECK_VERSION(2, 20, 0) */
#endif /* __GTK_COMPAT_H__ */

View File

@ -59,13 +59,10 @@ update_settings (GvcMixerEventRole *role,
gpointer *op) gpointer *op)
{ {
pa_operation *o; pa_operation *o;
guint index;
const GvcChannelMap *map; const GvcChannelMap *map;
pa_context *context; pa_context *context;
pa_ext_stream_restore_info info; pa_ext_stream_restore_info info;
index = gvc_mixer_stream_get_index (GVC_MIXER_STREAM (role));
map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role)); map = gvc_mixer_stream_get_channel_map (GVC_MIXER_STREAM(role));
info.volume = *gvc_channel_map_get_cvolume(map); info.volume = *gvc_channel_map_get_cvolume(map);
@ -165,12 +162,9 @@ gvc_mixer_event_role_constructor (GType type,
GObjectConstructParam *construct_params) GObjectConstructParam *construct_params)
{ {
GObject *object; GObject *object;
GvcMixerEventRole *self;
object = G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->constructor (type, n_construct_properties, construct_params); object = G_OBJECT_CLASS (gvc_mixer_event_role_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_EVENT_ROLE (object);
return object; return object;
} }

View File

@ -55,12 +55,10 @@ gvc_mixer_sink_input_push_volume (GvcMixerStream *stream, gpointer *op)
const GvcChannelMap *map; const GvcChannelMap *map;
pa_context *context; pa_context *context;
const pa_cvolume *cv; const pa_cvolume *cv;
guint num_channels;
index = gvc_mixer_stream_get_index (stream); index = gvc_mixer_stream_get_index (stream);
map = gvc_mixer_stream_get_channel_map (stream); map = gvc_mixer_stream_get_channel_map (stream);
num_channels = gvc_channel_map_get_num_channels (map);
cv = gvc_channel_map_get_cvolume(map); cv = gvc_channel_map_get_cvolume(map);
@ -115,12 +113,9 @@ gvc_mixer_sink_input_constructor (GType type,
GObjectConstructParam *construct_params) GObjectConstructParam *construct_params)
{ {
GObject *object; GObject *object;
GvcMixerSinkInput *self;
object = G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->constructor (type, n_construct_properties, construct_params); object = G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_SINK_INPUT (object);
return object; return object;
} }
@ -149,13 +144,9 @@ gvc_mixer_sink_input_init (GvcMixerSinkInput *sink_input)
static void static void
gvc_mixer_sink_input_dispose (GObject *object) gvc_mixer_sink_input_dispose (GObject *object)
{ {
GvcMixerSinkInput *mixer_sink_input;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object)); g_return_if_fail (GVC_IS_MIXER_SINK_INPUT (object));
mixer_sink_input = GVC_MIXER_SINK_INPUT (object);
G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->dispose (object); G_OBJECT_CLASS (gvc_mixer_sink_input_parent_class)->dispose (object);
} }

View File

@ -145,12 +145,9 @@ gvc_mixer_sink_constructor (GType type,
GObjectConstructParam *construct_params) GObjectConstructParam *construct_params)
{ {
GObject *object; GObject *object;
GvcMixerSink *self;
object = G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->constructor (type, n_construct_properties, construct_params); object = G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_SINK (object);
return object; return object;
} }
@ -180,13 +177,9 @@ gvc_mixer_sink_init (GvcMixerSink *sink)
static void static void
gvc_mixer_sink_dispose (GObject *object) gvc_mixer_sink_dispose (GObject *object)
{ {
GvcMixerSink *mixer_sink;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SINK (object)); g_return_if_fail (GVC_IS_MIXER_SINK (object));
mixer_sink = GVC_MIXER_SINK (object);
G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object); G_OBJECT_CLASS (gvc_mixer_sink_parent_class)->dispose (object);
} }

View File

@ -66,12 +66,9 @@ gvc_mixer_source_output_constructor (GType type,
GObjectConstructParam *construct_params) GObjectConstructParam *construct_params)
{ {
GObject *object; GObject *object;
GvcMixerSourceOutput *self;
object = G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->constructor (type, n_construct_properties, construct_params); object = G_OBJECT_CLASS (gvc_mixer_source_output_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_SOURCE_OUTPUT (object);
return object; return object;
} }

View File

@ -145,12 +145,9 @@ gvc_mixer_source_constructor (GType type,
GObjectConstructParam *construct_params) GObjectConstructParam *construct_params)
{ {
GObject *object; GObject *object;
GvcMixerSource *self;
object = G_OBJECT_CLASS (gvc_mixer_source_parent_class)->constructor (type, n_construct_properties, construct_params); object = G_OBJECT_CLASS (gvc_mixer_source_parent_class)->constructor (type, n_construct_properties, construct_params);
self = GVC_MIXER_SOURCE (object);
return object; return object;
} }
@ -180,13 +177,9 @@ gvc_mixer_source_init (GvcMixerSource *source)
static void static void
gvc_mixer_source_dispose (GObject *object) gvc_mixer_source_dispose (GObject *object)
{ {
GvcMixerSource *mixer_source;
g_return_if_fail (object != NULL); g_return_if_fail (object != NULL);
g_return_if_fail (GVC_IS_MIXER_SOURCE (object)); g_return_if_fail (GVC_IS_MIXER_SOURCE (object));
mixer_source = GVC_MIXER_SOURCE (object);
G_OBJECT_CLASS (gvc_mixer_source_parent_class)->dispose (object); G_OBJECT_CLASS (gvc_mixer_source_parent_class)->dispose (object);
} }

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