Compare commits

..

82 Commits

Author SHA1 Message Date
471006ba67 Bump version to 2.27.3 2009-09-15 18:03:36 -04:00
98bd590a5d [runDialog] Add 'debugexit' command
There are few uses for being able to exit the shell directly; my
current one is that the gtype debug infrastructure is implemented
as an atexit() handler.
2009-09-15 17:47:57 -04:00
9d88a13d3c Updated Galician Translation 2009-09-15 23:06:46 +02:00
159690b2d3 Enable Alt-f2 in overview
This isn't a long-term solution; what we really want is for Alt-F2 to
just be an application search with a hack to detect shell commands,
but in the short term this allows us to run the magic 'lg' command
from the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=595116
2009-09-15 16:20:19 -04:00
8a2bfd0e55 Change keyboard handling API to handle nested modal calls
Rename beginModal/endModal to pushModal/popModal.  All of the current callers
just want to ensure that we're in a modal state; they don't actually need to
fail if we already are.

These functions also now take the Clutter keyboard focus, while recording
the previous focus.

https://bugzilla.gnome.org/show_bug.cgi?id=595116
2009-09-15 16:15:16 -04:00
2ddc7cf00f Only enable internal commands if developer_tools is true
'r' is a bit too accidentally-hittable for outside of developer usage.
However it will still be enabled when developer_tools is true.

https://bugzilla.gnome.org/show_bug.cgi?id=595116
2009-09-15 16:14:36 -04:00
04f10ceb4e Add a developer_tools boolean defaulting to true
This will be use to enable various internal tools which should only
be exposed to developers/testers.

https://bugzilla.gnome.org/show_bug.cgi?id=595116
2009-09-15 16:12:11 -04:00
ceefc5eea4 Convert remaining uses of "let me = this;" to Lang.bind
https://bugzilla.gnome.org/show_bug.cgi?id=595293
2009-09-15 13:11:23 -04:00
9feda69888 When in window filtering mode, reset filter before showing window
When we had a filtered set of windows, and want to exit the overview
into a particular window, what we do is re-show all the old windows
first, but don't reset the scaling on them.  This will involve
some overlapping, but that's not a big deal because we'll immediately
get overlap anyways in the normal case zooming the windows back.

https://bugzilla.gnome.org/show_bug.cgi?id=594699
2009-09-14 15:41:19 -04:00
33f9895d71 Don't proxy methods through overview; add a getWorkspacesForWindow()
Duplicating the methods was unnecessary.  Also, we want a getWorkspacesForWindow()
method as preparation for multi-monitor work.

https://bugzilla.gnome.org/show_bug.cgi?id=594699
2009-09-14 15:41:12 -04:00
2812c21322 Allow popup menu to be persistent, and support direct window selection
When the user click+hold+release over the icon, the effect we want
is for the menu to stick around.

Also, allow the user to mouse over the actual windows and select
them directly.  If the user mouses over a window, reflect that in
the menu.

https://bugzilla.gnome.org/show_bug.cgi?id=594699
2009-09-14 15:37:29 -04:00
7ac9fb2dd0 Make popdown,popup methods idempotent; remove 'popdown' for 'cancelled'
Callers will generally expect _popup and _popdown to be a no-op if
the menu is already in that state; make it so.

Also change the 'popdown' signal to be 'cancelled'; this is
clearer and allows us to avoid having activate also call popdown.

https://bugzilla.gnome.org/show_bug.cgi?id=594699
2009-09-14 15:37:26 -04:00
05c99241d6 [Overview] Make content area eat mouse events during animations
There are ton of different kinds of mouse even handlers in the overview;
WindowClone has several mouse-enter/leave handlers, we still have a variety
of classes not ported to ButtonBox and so incorrectly handling double-click,
etc.

Since we at present don't have anything in the overview area for which
it makes sense to interact with during the animation, create a transparent
event-eating box which we raise to the top during the animation.

https://bugzilla.gnome.org/show_bug.cgi?id=594074
2009-09-14 15:31:49 -04:00
9fb8dad80c Added British English translation 2009-09-13 16:24:19 +01:00
004ad86e9d Updated Spanish translation 2009-09-12 14:41:15 +02:00
02c65fab8d Don't show section headers for sections with no results and don't show page
controls if there is only one page of results

This makes the search results display more streamlined.

Make sure that we move the selection to a different section if we are going
from displaying a single section to displaying all and the section that
used to be displayed alone doesn't have any results.
2009-09-11 19:30:11 -04:00
dfe16f4af6 Revert "[AppWell] Allow popup menu to be persistent, and support direct window selection"
This reverts commit 6e31e59b57.
2009-09-11 18:58:30 -04:00
e52cb3c213 [ShellAppMonitor] Handle Iceweasel tripping Firefox window title detection
We have compatibility code which detects from the window title what
an application is.  However, the code didn't handle the case where
we discovered by title, but didn't have the expected .desktop file
installed.
2009-09-11 18:57:44 -04:00
6e31e59b57 [AppWell] Allow popup menu to be persistent, and support direct window selection
When the user click+hold+release over the icon, the effect we want
is for the menu to stick around.

Also, allow the user to mouse over the actual windows and select
them directly.  If the user mouses over a window, reflect that in
the menu.
2009-09-11 18:57:44 -04:00
458778bcfd Add a separate section of search results that shows system preferences
System preferences should not be mixed in with applications in search results.
2009-09-11 17:48:02 -04:00
d8cabbee0b More global-ization 2009-09-11 17:23:42 -04:00
3029a4086b Restructure the search results code to be able to support any number of sections
We will be adding more search results sections, so we should store the intended
order of the search results sections and their properties in an array of data
structures.

This information allows us to have generic code for creating the search results
sections, moving the selection between them and transitioning between showing
all sections and a single section.
2009-09-11 16:42:54 -04:00
5598de6543 Updated French translation 2009-09-11 21:41:27 +02:00
913aeae166 Actually update well menu filtering for review messages
My updates got lost due to accidentally being on a rebase branch.
2009-09-09 17:28:52 -04:00
dddad9e1b5 [AppDisplay] In search/browse, show existing window instead of always launching
This brings search in line with the AppWell behavior which is definitely
right.  For browse we probably want more options.
2009-09-09 16:49:26 -04:00
4bfa68d209 [AppWell] Fix previous commit
Somehow missed changing a call when updating for review comments.
2009-09-09 16:49:07 -04:00
42e3a93c20 More gracefully handle a situation where starting shell failed
If start_shell() threw an exception before, we'd overwrite it with
an exception in the finally() clause.  Handle this and just print a message
and let the exception propagate.
2009-09-09 15:49:31 -04:00
05812ef7f9 [AppWell] Enable lightboxing immediately on popup
Rather than starting lightboxing only when the mouse enters the
menu, start it when an application filter is set.

Also delete a stale function in WindowClone from previous work.

http://bugzilla.gnome.org/show_bug.cgi?id=594555
2009-09-09 11:40:09 -04:00
a0df412deb Extend (+) button sensitivity to corner of screen, for Fittsability
https://bugzilla.gnome.org/show_bug.cgi?id=591984
2009-09-09 11:31:50 -04:00
678a88dbdb Remove some "let global ..."s that snuck back in as part of old patches 2009-09-09 09:42:00 -04:00
5e944c9a3b Move the add workspace button out of the Workspaces object, into Overview
http://bugzilla.gnome.org/show_bug.cgi?id=594049
2009-09-09 09:36:59 -04:00
b28b60b47b Updated Polish translation 2009-09-09 03:06:16 +02:00
16caa74386 Updated Polish translation 2009-09-09 02:57:37 +02:00
470c65d046 [AppWell] Make control-click create a new window
Implement this for now by just re-launching the application, which
visually will normally create a new window.

http://bugzilla.gnome.org/show_bug.cgi?id=594565
2009-09-08 18:48:51 -04:00
ef6ea078dd [AppWell] Position menu components on integral coordinates
This avoids fuzz.

http://bugzilla.gnome.org/show_bug.cgi?id=594553
2009-09-08 18:48:17 -04:00
37ee16b34d Use clutter_event_get_* instead of ShellGlobal
Before Clutter gained accessors for event information, we had
shell_global_ functions.  Now that Clutter has them, use them and
delete the ShellGlobal code.

http://bugzilla.gnome.org/show_bug.cgi?id=594561
2009-09-08 17:58:13 -04:00
5880b3b0ed [ShellButtonBox] Add event to activate signal
This allows access to things such as keyboard modifier state and
event time cleanly.

http://bugzilla.gnome.org/show_bug.cgi?id=594565
2009-09-08 17:58:13 -04:00
80a5f78eb2 [AppWell] Unify drag and drop behavior between Running versus Inactive
This fixes a regression where drag and drop didn't work for inactive
items correctly.

http://bugzilla.gnome.org/show_bug.cgi?id=594542
2009-09-08 17:58:13 -04:00
4b727ef40d Scroll wheel should zoom windows in the overview
Allow using the scroll wheel to zoom in on windows in the overview.

Original patch from JP St. Pierre.
http://bugzilla.gnome.org/show_bug.cgi?id=591849
2009-09-08 17:37:24 -04:00
d0d79c5b3e Make "global" global.
Rather than doing "let global = Shell.Global.get()" everywhere we
need it, just create a global variable called "global".

http://bugzilla.gnome.org/show_bug.cgi?id=594546
2009-09-08 16:21:15 -04:00
0882da0a71 Add error handling to the runDialog
Show the errors to the user instead of silently logging them to the terminal,
also rework positioning to get rid of magic numbers.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>

http://bugzilla.gnome.org/show_bug.cgi?id=593840
2009-09-08 14:35:23 -04:00
25410a730e Bug 591763 - Add application window menu
When we have multiple windows for an application, implement the following
behavior:

* On click + immediate release, go to the most recently used
* On click, hold for 0.6s, pop up a menu with windows, filtering
  the window list to just those windows.
  Mouse over on the window list highlights the moused-over window.

Implement this by splitting well item into InactiveWellItem
and RunningWellItem, sharing a base class BaseWellItem.
2009-09-08 14:31:44 -04:00
22c445cffc Add ShellMenu
An object with methods and signals useful for implementing popup menus.
2009-09-08 14:31:43 -04:00
42bf91fdc4 Distribute app-well-glow.png
Add app-well-glow.png to data/Makefile.am
2009-09-07 20:43:57 +02:00
7f88e02a26 Convert on_tree_changed to a gboolean returning false.
This fixes commit 0a29cf6195 and
g_timer_add_full running in an endless loop.

http://bugzilla.gnome.org/show_bug.cgi?id=592608
2009-09-07 11:13:38 -04:00
d540af847a Updated Italian translation 2009-09-06 18:32:44 +02:00
2f78907aeb Bump version to 2.27.2 2009-09-04 20:14:57 -04:00
d471541495 Bump gobject-introspectio nrequirement to 0.6.5
gobject-introspection 0.6.5 is needed for Gio.VolumeMonitor usage.
2009-09-04 20:13:04 -04:00
fa5fb6b8a8 Bug 594184 - Fix up glow positioning logic
We were allowing the glow allocation to go too far to the right;
clean up the logic.
2009-09-04 20:03:56 -04:00
0a29cf6195 Compress notifications of menu changes with a timeout.
GMenu currently gives us a separate notification on the entire
menu tree for each node in the tree that might potentially have
changed. (See http://bugzilla.gnome.org/show_bug.cgi?id=172046.)
Compress these with a timeout to avoid doing a lot of extra work.

http://bugzilla.gnome.org/show_bug.cgi?id=592608
2009-09-04 19:24:47 -04:00
b7b4c54ab5 Make checking if an item is under the pointer asynchonous again
Checking if an item is under the pointer by calling stage.get_actor_at_pos()
synchronously will trigger a too-early allocation of the stage. Use an idle
at Meta.PRIORITY_BEFORE_REDRAW. (Before 553503d it was using a 5 msec timeout,
553503d made it synchronous.)

http://bugzilla.gnome.org/show_bug.cgi?id=592608
2009-09-04 19:12:07 -04:00
52abf266c0 Redo AppWell glow to be based on a based on a .png instead of cairo
Instead of drawing an ellipse, use a hand-drawn .png file which
looks a bit less regular and blends better.
2009-09-04 17:42:10 -04:00
11872cfb79 Add README and DOAP file
README: Add a short README with basic information.

gnome-shell.doap: Add project information in DOAP format expected
  for GNOME projects.

http://bugzilla.gnome.org/show_bug.cgi?id=591564
2009-09-04 15:23:13 -04:00
21309aa28f Updated Danish translation 2009-09-04 01:26:01 +02:00
38d21c8edf Remove some vestigial code 2009-09-03 09:50:39 -04:00
090908439b Add volumes support to places
Display the mounted volumes in the places section of the overlay.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>
2009-09-02 15:04:24 -04:00
0a17a28608 Add shell_button_box_fake_release
The application menu code wants to do a popup after a given timeout
while holding.  We can implement that by adding a function to
manually break the grab held by the button box.

Freeze+thaw around the hover and pressed property notification on leave
since handlers may want to depend on the pressed state on a hover
transition.
2009-09-02 15:01:33 -04:00
926643b025 Add shell_texture_cache_pixbufs_equal
Mutter is currently creating separate pixbufs for window icons;
use this to analyze them.
2009-09-02 14:54:49 -04:00
1a834f7d8b Add API to programmatically initiate a drag
For some use cases we have other behavior on mouse press and want
to manually control when a drag starts.  Split out the drag initiation
code into startDrag.
2009-09-02 14:34:57 -04:00
3e54087e42 Add Tweener.slowDownFactor, initialize from $GNOME_SHELL_SLOWDOWN_FACTOR
This allows for easier debugging of glitchy animations
2009-09-02 09:15:37 -04:00
304b377dae Added Punjabi (Gurmukhi)Translation 2009-09-02 05:28:51 +05:30
ac4bcee050 Merge headers when a single section of search results is displayed
There is no need to show two headers when we are only displaying a single
section of search results, so we merge the section header with the main
header in that case.

Show a back button on the left of the main header to get back to the results
for all sections.

Remove this._showTooltip flag from SearchSectionHeader because we no longer
show this type of header when we want to suppress the tooltip.

Add this._appSearchResultsOnlyShown and this._docSearchResultsOnlyShown
flags to track when a single section is shown more cleanly.
2009-09-01 19:06:20 -04:00
553503dace Remove the timeout for checking if an item is drawn under the pointer
We no longer need the timeout for checking if an item is drawn under
the pointer because we display search results in the main pane and there is
no lowering/raising of other overview actors going on as the results are
being displayed.
2009-09-01 16:29:14 -04:00
90381ceea2 Improve key navigation for search results
Select an item by default when the search results are displayed.

Enable moving from one section of search results to another with key navigation.

Reset the selection when the search is updated or a new page is displayed
or the transition between viewing multiple sections and viewing just one is made.
2009-09-01 16:24:47 -04:00
687814b6c6 Update build-setup.sh for gconf, gio python usage
Add pygobject and gnome-python-gconf dependencies to
gnome-shell-build-setup.sh package lists for Fedora and Ubuntu/Debian.

http://bugzilla.gnome.org/show_bug.cgi?id=593458
2009-09-01 09:02:46 -04:00
6153094057 Updated Swedish translation 2009-09-01 00:31:48 +02:00
0245a0cd0e Do not display windows with skip-taskbar hint in overview.
This fixes the bug where the empathy buddy list is always visible on the
last workspace it was shown on, even if it was closed.
2009-08-31 21:35:23 +02:00
bcc3dc0711 Consolidate window tracking filters between app monitor and overview.
The windows we considered for both the app monitor and the overview
workspaces were the same, but the code was duplicated once in C, once
in Javascript.
2009-08-31 21:35:23 +02:00
3d499219da Use AM_PATH_PYTHON to find Python >= 2.5
On OpenSolaris /usr/bin/python is 2.4; use AM_PATH_PYTHON to find
a newer Python. (The PYTHON environment variable can also be set
before running configure to override the search.)

http://bugzilla.gnome.org/show_bug.cgi?id=578196
2009-08-31 13:42:06 -04:00
94b26888cf Build tweaks
Add .AUTOPARALELL which is my GNU-make fix for projects to specify
that the build is parallel-safe, and to automatically parallelize.

Add a missing dependency on built sources, and specify --libtool
to be safe.
2009-08-30 18:08:19 -04:00
156fdf1fa3 Update Catalan translation 2009-08-30 19:26:39 +02:00
2a3f9e8f83 Updated Czech translation 2009-08-30 17:37:51 +02:00
849ce371ff Updated Spanish translation 2009-08-30 11:17:50 +02:00
a76ac5501c Add Simplified Chinese translation. 2009-08-30 09:15:34 +08:00
5803aa7e65 Simplify Button class by using ShellButtonBox
Make Button class purely about adding visuals, and use ShellButtonBox
for behavior. API equivalences:

  shell.button => shell.actor [for consistency]

  staysPressed parameter to constructor => replaced by manually setting
   the 'active' property of button.actor as appropriate

  pressIn/release => button.actor.active = true/false

  enter-event/leave-event signals => button.actor notify::hover

Along the way, this fixes a bug with the user status menu where it was
not getting set to active because the button was getting a leave
(triggered by the menu popping up and grabbing the pointer) before for
button release, which disabled the staysPressed behavior.

Reported by Michael Meeks
http://bugzilla.gnome.org/show_bug.cgi?id=593471
2009-08-29 15:20:19 -04:00
0fd6bc5172 ShellButtonBox: only listen to button 1 and single clicks
Only mouse button 1 is supposed to activate button controls; other
mouse buttons should do nothing unless there is a context menu.

Checking the click count is important, since double-clicks will
otherwise look like unpaired button presses.

http://bugzilla.gnome.org/show_bug.cgi?id=593504
2009-08-29 15:20:18 -04:00
0e3cea41e0 ShellButtonBox: Use default handlers, not self-connections
There's seldom a good justification for connecting to signals on
yourself rather than using the default handler slots in the class.

But in particular using the default handler slots means that
an application can connect to ::button-press-event and get in
before the default handling, to implement a button that does
something on press.

http://bugzilla.gnome.org/show_bug.cgi?id=593503
2009-08-29 15:20:18 -04:00
45c600cd25 Add an active property to ShellButtonBox
Add an 'active' property to ShellButtonBox. This allows ShellButtonBox
to be used as a "toggle button". It's up the application to connect
it to the ::activate signal; there's no default handling of this.

(It's seldom that the only time you want to toggle a toggle button
through the user interface, so you need some connection to the backend
data store in any case. Removing the default handling all-together
prevents weird interactions.)

When we have built-in styling for ShellButtonBox the 'active' state
would be one of the elements that would be affect the styling.

http://bugzilla.gnome.org/show_bug.cgi?id=593502
2009-08-29 15:20:18 -04:00
7fb8e2d0ef Bug 592507 - Javascript exception when ~/.gtk-bookmarks is missing
Check the file exists before trying to access it and simply return if it
is not available.
2009-08-29 14:26:26 +01:00
2d5d54f3cd Update Dutch translation 2009-08-29 15:11:34 +02:00
949359db5d Added Danish translation 2009-08-29 10:25:03 +02:00
5bd2695863 Added Da to list of laguages 2009-08-29 10:23:43 +02:00
58 changed files with 3757 additions and 1198 deletions

20
README
View File

@ -0,0 +1,20 @@
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
like switching to windows and launching applications. GNOME Shell takes
advantage of the capabilities of modern graphics hardware and introduces
innovative user interface concepts to provide a visually attractive and
easy to use experience.
For more information about GNOME Shell, including instructions on how
to build GNOME Shell from source and how to get involved with the project,
see:
http://live.gnome.org/GnomeShell
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
License
=======
GNOME Shell is distributed under the terms of the GNU General Public License,
version 2 or later. See the COPYING file for details.

View File

@ -1,4 +1,4 @@
AC_INIT(gnome-shell, 2.27.1)
AC_INIT(gnome-shell, 2.27.3)
AC_CONFIG_AUX_DIR(config)
@ -28,6 +28,10 @@ AM_GLIB_GNU_GETTEXT
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
AM_GCONF_SOURCE_2
# Get a value to substitute into gnome-shell.in
AM_PATH_PYTHON([2.5])
AC_SUBST(PYTHON)
# We need at least this, since gst_plugin_register_static() was added
# in 0.10.16, but nothing older than 0.10.21 has been tested.
GSTREAMER_MIN_VERSION=0.10.16
@ -51,7 +55,7 @@ PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugin
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
gobject-introspection-1.0 >= 0.6.4)
gobject-introspection-1.0 >= 0.6.5)
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)

View File

@ -16,6 +16,8 @@ imagedir = $(pkgdatadir)/images
dist_image_DATA = \
add-workspace.svg \
app-well-glow.png \
back.svg \
close.svg \
close-black.svg \
info.svg \

BIN
data/app-well-glow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

7
data/back.svg Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.0" id="Foreground" x="0px" y="0px" width="12" height="16" viewBox="0 0 12 16" enable-background="new 0 0 29 18" xml:space="preserve" sodipodi:version="0.32" inkscape:version="0.46+devel" sodipodi:docname="back.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata id="metadata16"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><defs id="defs14"><inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 9 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="29 : 9 : 1" inkscape:persp3d-origin="14.5 : 6 : 1" id="perspective18"/></defs><sodipodi:namedview inkscape:window-height="728" inkscape:window-width="1103" inkscape:pageshadow="2" inkscape:pageopacity="1" guidetolerance="10.0" gridtolerance="10.0" objecttolerance="10.0" borderopacity="1.0" bordercolor="#666666" pagecolor="#000000" id="base" showgrid="true" inkscape:zoom="27.260185" inkscape:cx="12.592456" inkscape:cy="8.2696842" inkscape:window-x="145" inkscape:window-y="38" inkscape:current-layer="Foreground" inkscape:snap-global="true" showguides="false"><inkscape:grid type="xygrid" id="grid2391" empspacing="5" visible="true" enabled="true" snapvisiblegridlinesonly="true"/></sodipodi:namedview>
<path style="fill: rgb(255, 255, 255); fill-opacity: 1; stroke: none;" d="M 10,2 10,14 2,8 10,2 z" id="path43"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,6 +1,21 @@
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/desktop/gnome/shell/development_tools</key>
<applyto>/desktop/gnome/shell/development_tools</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Enable internal tools useful for developers and testers from Alt-F2</short>
<long>
Allows access to internal debugging and monitoring tools using
the Alt-F2 dialog.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>

53
gnome-shell.doap Normal file
View File

@ -0,0 +1,53 @@
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:gnome="http://api.gnome.org/doap-extensions#"
xmlns="http://usefulinc.com/ns/doap#">
<name xml:lang="en">GNOME Shell</name>
<shortdesc xml:lang="en">Next generation GNOME desktop shell</shortdesc>
<!--
<homepage rdf:resource="http://live.gnome.org/GnomeShell" />
-->
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<maintainer>
<foaf:Person>
<foaf:name>William Jon McCann</foaf:name>
<foaf:mbox rdf:resource="mailto:jmccann@redhat.com" />
<gnome:userid>mccann</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Owen Taylor</foaf:name>
<foaf:mbox rdf:resource="mailto:otaylor@redhat.com" />
<gnome:userid>otaylor</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Colin Walters</foaf:name>
<foaf:mbox rdf:resource="mailto:walters@verbum.org" />
<gnome:userid>cwalters</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Dan Winship</foaf:name>
<foaf:mbox rdf:resource="mailto:danw@gnome.org" />
<gnome:userid>danw</gnome:userid>
</foaf:Person>
</maintainer>
<maintainer>
<foaf:Person>
<foaf:name>Marina Zhurakhinskaya</foaf:name>
<foaf:mbox rdf:resource="mailto:marinaz@redhat.com" />
<gnome:userid>marinaz</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View File

@ -36,8 +36,6 @@ function AltTabPopup() {
AltTabPopup.prototype = {
_init : function() {
let global = Shell.Global.get();
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
corner_radius: POPUP_GRID_SPACING,
padding: POPUP_GRID_SPACING,
@ -140,8 +138,6 @@ AltTabPopup.prototype = {
},
show : function(initialSelection) {
let global = Shell.Global.get();
global.window_group.add_actor(this._overlay);
this._overlay.raise_top();
this._overlay.show();
@ -234,8 +230,6 @@ AltTabPopup.prototype = {
},
_adjust_overlay : function() {
let global = Shell.Global.get();
if (this._selected && this._selected.icon_rect) {
// We want to highlight a specific rectangle within the
// task bar, so rearrange the pieces of the overlay to

View File

@ -26,6 +26,27 @@ const WELL_DEFAULT_COLUMNS = 4;
const WELL_ITEM_HSPACING = 0;
const WELL_ITEM_VSPACING = 4;
const WELL_MENU_POPUP_TIMEOUT_MS = 600;
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const WELL_MENU_BACKGROUND_COLOR = new Clutter.Color();
WELL_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
const WELL_MENU_FONT = 'Sans 14px';
const WELL_MENU_COLOR = new Clutter.Color();
WELL_MENU_COLOR.from_pixel(0xffffffff);
const WELL_MENU_SELECTED_COLOR = new Clutter.Color();
WELL_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
const WELL_MENU_BORDER_COLOR = new Clutter.Color();
WELL_MENU_BORDER_COLOR.from_pixel(0x787878ff);
const WELL_MENU_SEPARATOR_COLOR = new Clutter.Color();
WELL_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
const WELL_MENU_BORDER_WIDTH = 1;
const WELL_MENU_ARROW_SIZE = 12;
const WELL_MENU_CORNER_RADIUS = 4;
const WELL_MENU_PADDING = 4;
const MENU_ICON_SIZE = 24;
const MENU_SPACING = 15;
@ -57,7 +78,13 @@ AppDisplayItem.prototype = {
// Opens an application represented by this display item.
launch : function() {
this._appInfo.launch();
let windows = Shell.AppMonitor.get_default().get_windows_for_app(this._appInfo.get_id());
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
} else {
this._appInfo.launch();
}
},
//// Protected method overrides ////
@ -161,21 +188,25 @@ MenuItem.prototype = {
}
Signals.addSignalMethods(MenuItem.prototype);
/* This class represents a display containing a collection of application items.
* The applications are sorted based on their popularity by default, and based on
* their name if some search filter is applied.
*
* showPrefs - a boolean indicating if this AppDisplay should contain preference
* applets, rather than applications
*/
function AppDisplay() {
this._init();
function AppDisplay(showPrefs) {
this._init(showPrefs);
}
AppDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function() {
_init : function(showPrefs) {
GenericDisplay.GenericDisplay.prototype._init.call(this);
this._showPrefs = showPrefs;
this._menus = [];
this._menuDisplays = [];
@ -327,36 +358,37 @@ AppDisplay.prototype = {
// Gets information about all applications by calling Gio.app_info_get_all().
_refreshCache : function() {
let me = this;
if (!this._appsStale)
return;
this._allItems = {};
this._appCategories = {};
// Loop over the toplevel menu items, load the set of desktop file ids
// associated with each one, skipping empty menus
let allMenus = this._appSystem.get_menus();
this._menus = [];
for (let i = 0; i < allMenus.length; i++) {
let menu = allMenus[i];
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
if (!hasVisibleApps) {
continue;
}
this._menus.push(menu);
for (let j = 0; j < menuApps.length; j++) {
let app = menuApps[j];
if (this._showPrefs) {
// Get the desktop file ids for settings/preferences.
// These are used for search results, but not in the app menus.
let settings = this._appSystem.get_all_settings();
for (let i = 0; i < settings.length; i++) {
let app = settings[i];
this._addApp(app);
}
}
// Now grab the desktop file ids for settings/preferences.
// These show up in search, but not with the rest of apps.
let settings = this._appSystem.get_all_settings();
for (let i = 0; i < settings.length; i++) {
let app = settings[i];
this._addApp(app);
} else {
// Loop over the toplevel menu items, load the set of desktop file ids
// associated with each one, skipping empty menus
let allMenus = this._appSystem.get_menus();
this._menus = [];
for (let i = 0; i < allMenus.length; i++) {
let menu = allMenus[i];
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
if (!hasVisibleApps) {
continue;
}
this._menus.push(menu);
for (let j = 0; j < menuApps.length; j++) {
let app = menuApps[j];
this._addApp(app);
}
}
}
this._appsStale = false;
@ -448,35 +480,286 @@ AppDisplay.prototype = {
Signals.addSignalMethods(AppDisplay.prototype);
function WellDisplayItem(appInfo, isFavorite) {
function WellMenu(source) {
this._init(source);
}
WellMenu.prototype = {
_init: function(source) {
this._source = source;
// Whether or not we successfully picked a window
this.didActivateWindow = false;
this.actor = new Shell.GenericContainer({ reactive: true });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
border_color: WELL_MENU_BORDER_COLOR,
border: WELL_MENU_BORDER_WIDTH,
background_color: WELL_MENU_BACKGROUND_COLOR,
padding: 4,
corner_radius: WELL_MENU_CORNER_RADIUS,
width: Main.overview._dash.actor.width * 0.75 });
this._windowContainer.connect('unselected', Lang.bind(this, this._onWindowUnselected));
this._windowContainer.connect('selected', Lang.bind(this, this._onWindowSelected));
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
this._windowContainer.connect('activate', Lang.bind(this, this._onWindowActivate));
this.actor.add_actor(this._windowContainer);
// Stay popped up on release over application icon
this._windowContainer.set_persistent_source(this._source.actor);
// Intercept events while the menu has the pointer grab to do window-related effects
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
this._arrow = new Shell.DrawingArea();
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
Shell.draw_box_pointer(texture, WELL_MENU_BORDER_COLOR, WELL_MENU_BACKGROUND_COLOR);
}));
this.actor.add_actor(this._arrow);
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
if (!source.actor.mapped)
this._windowContainer.popdown();
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
global.stage.add_actor(this.actor);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
alloc.min_size = min + WELL_MENU_ARROW_SIZE;
alloc.natural_size = natural + WELL_MENU_ARROW_SIZE;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
alloc.min_size = min;
alloc.natural_size = natural;
},
_allocate: function(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
childBox.x1 = 0;
childBox.x2 = WELL_MENU_ARROW_SIZE;
childBox.y1 = Math.floor((height / 2) - (WELL_MENU_ARROW_SIZE / 2));
childBox.y2 = childBox.y1 + WELL_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
/* overlap by one pixel to hide the border */
childBox.x1 = WELL_MENU_ARROW_SIZE - 1;
childBox.x2 = width;
childBox.y1 = 0;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
},
_redisplay: function() {
this._windowContainer.remove_all();
this.didActivateWindow = false;
let windows = this._source.windows;
this._windowContainer.show();
let iconsDiffer = false;
let texCache = Shell.TextureCache.get_default();
let firstIcon = windows[0].mini_icon;
for (let i = 1; i < windows.length; i++) {
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
iconsDiffer = true;
break;
}
}
let activeWorkspace = global.screen.get_active_workspace();
let currentWorkspaceWindows = windows.filter(function (w) {
return w.get_workspace() == activeWorkspace;
});
let otherWorkspaceWindows = windows.filter(function (w) {
return w.get_workspace() != activeWorkspace;
});
this._appendWindows(currentWorkspaceWindows, iconsDiffer);
if (currentWorkspaceWindows.length > 0 && otherWorkspaceWindows.length > 0) {
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
box.append(new Clutter.Rectangle({ height: 1,
color: WELL_MENU_SEPARATOR_COLOR }),
Big.BoxPackFlags.EXPAND);
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
}
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
},
_appendWindows: function (windows, iconsDiffer) {
for (let i = 0; i < windows.length; i++) {
let metaWindow = windows[i];
/* Use padding here rather than spacing in the box above so that
* we have a larger reactive area.
*/
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: 4,
padding_bottom: 4,
spacing: 4,
reactive: true });
box._window = metaWindow;
let vCenter;
if (iconsDiffer) {
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
vCenter.append(icon, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
}
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let label = new Clutter.Text({ text: metaWindow.title,
font_name: WELL_MENU_FONT,
ellipsize: Pango.EllipsizeMode.END,
color: WELL_MENU_COLOR });
vCenter.append(label, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
}
},
popup: function() {
let [stageX, stageY] = this._source.actor.get_transformed_position();
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
this._redisplay();
this._windowContainer.popup(0, Clutter.get_current_event_time());
this.emit('popup', true);
let x = Math.floor(stageX + stageWidth);
let y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
this.actor.set_position(x, y);
this.actor.show();
},
_findWindowCloneForActor: function (actor) {
if (actor._delegate instanceof Workspaces.WindowClone)
return actor._delegate;
return null;
},
// This function is called while the menu has a pointer grab; what we want
// to do is see if the mouse was released over a window clone actor
_onMenuButtonRelease: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this.didActivateWindow = true;
Main.overview.activateWindow(clone.metaWindow, event.get_time());
}
},
_setHighlightWindow: function (metaWindow) {
let children = this._windowContainer.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
let menuMetaWindow = child._window;
if (metaWindow != null && menuMetaWindow == metaWindow) {
child.background_color = WELL_MENU_SELECTED_COLOR;
} else {
child.background_color = TRANSPARENT_COLOR;
}
}
this.emit('highlight-window', metaWindow);
},
// Called while menu has a pointer grab
_onMenuEnter: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this._setHighlightWindow(clone.metaWindow);
}
},
// Called while menu has a pointer grab
_onMenuLeave: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this._setHighlightWindow(null);
}
},
_onWindowUnselected: function (actor, child) {
this._setHighlightWindow(null);
},
_onWindowSelected: function (actor, child) {
this._setHighlightWindow(child._window);
},
_onWindowActivate: function (actor, child) {
let metaWindow = child._window;
this.didActivateWindow = true;
Main.overview.activateWindow(metaWindow, Clutter.get_current_event_time());
this.emit('popup', false);
this.actor.hide();
},
_onWindowSelectionCancelled: function () {
this.emit('highlight-window', null);
this.emit('popup', false);
this.actor.hide();
}
}
Signals.addSignalMethods(WellMenu.prototype);
function BaseWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
WellDisplayItem.prototype = {
__proto__ : AppIcon.AppIcon.prototype,
_init : function(appInfo, isFavorite) {
AppIcon.AppIcon.prototype._init.call(this, appInfo);
BaseWellItem.prototype = {
_init: function(appInfo, isFavorite) {
this.appInfo = appInfo;
this.isFavorite = isFavorite;
this.icon = new AppIcon.AppIcon(appInfo);
this.windows = this.icon.windows;
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
border: WELL_MENU_BORDER_WIDTH,
corner_radius: WELL_MENU_CORNER_RADIUS,
reactive: true });
this.icon.actor._delegate = this;
this._draggable = DND.makeDraggable(this.icon.actor, true);
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
this._handleActivate();
// Do these as anonymous functions to avoid conflict with handlers in subclasses
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
this._dragStartY = stageY;
return false;
}));
let draggable = DND.makeDraggable(this.actor);
},
_handleActivate: function () {
if (this._windows.length == 0) {
this.appInfo.launch();
Main.overview.hide();
} else {
/* Pick the first window and activate it;
* In the future, we want to have a menu dropdown here. */
let first = this._windows[0];
Main.overview.activateWindow(first, Clutter.get_current_event_time());
}
this.actor.connect('notify::hover', Lang.bind(this, function () {
let hover = this.actor.hover;
if (!hover) {
if (this.actor.pressed && this._dragStartX != null) {
this.actor.fake_release();
this._draggable.startDrag(this.icon.actor, this._dragStartX, this._dragStartY,
Clutter.get_current_event_time());
} else {
this._dragStartX = null;
this._dragStartY = null;
}
}
}));
this.actor.append(this.icon.actor, Big.BoxPackFlags.NONE);
},
shellWorkspaceLaunch : function() {
@ -492,17 +775,140 @@ WellDisplayItem.prototype = {
},
getDragActor: function(stageX, stageY) {
return this.appInfo.create_icon_texture(this._icon.height);
return this.icon.getDragActor(stageX, stageY);
},
// Returns the original icon that is being used as a source for the cloned texture
// that represents the item as it is being dragged.
getDragActorSource: function() {
return this._icon;
return this.icon.getDragActorSource();
}
}
function RunningWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
RunningWellItem.prototype = {
__proto__: BaseWellItem.prototype,
_init: function(appInfo, isFavorite) {
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
this._menuTimeoutId = 0;
this._menu = null;
this._dragStartX = 0;
this._dragStartY = 0;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._onActivate));
},
setWidth: function(width) {
this._nameBox.width = width + GLOW_PADDING * 2;
_onActivate: function (actor, event) {
let modifiers = event.get_state();
if (this._menuTimeoutId > 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
this.appInfo.launch();
} else {
this.activateMostRecentWindow();
}
},
activateMostRecentWindow: function () {
// The _get_windows_for_app sorts them for us
let mostRecentWindow = this.windows[0];
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
},
_onHoverChanged: function() {
let hover = this.actor.hover;
if (!hover && this._menuTimeoutId > 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
},
_onButtonPress: function(actor, event) {
if (this._menuTimeoutId > 0)
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = Mainloop.timeout_add(WELL_MENU_POPUP_TIMEOUT_MS,
Lang.bind(this, this._popupMenu));
return false;
},
_popupMenu: function() {
this._menuTimeoutId = 0;
this.actor.fake_release();
if (this._menu == null) {
this._menu = new WellMenu(this);
this._menu.connect('highlight-window', Lang.bind(this, function (menu, metaWindow) {
Main.overview.getWorkspacesForWindow(metaWindow).setHighlightWindow(metaWindow);
}));
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
let id;
// If we successfully picked a window, don't reset the workspace
// state, since picking a window already did that.
if (!isPoppedUp && menu.didActivateWindow)
return;
if (isPoppedUp)
id = this.appInfo.get_id();
else
id = null;
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(id);
}));
}
this._menu.popup();
return false;
}
}
function InactiveWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
InactiveWellItem.prototype = {
__proto__: BaseWellItem.prototype,
_init : function(appInfo, isFavorite) {
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
this.actor.connect('notify::pressed', Lang.bind(this, this._onPressedChanged));
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._onActivate));
},
_onPressedChanged: function() {
let pressed = this.actor.pressed;
if (pressed) {
this.actor.border_color = WELL_MENU_BORDER_COLOR;
} else {
this.actor.border_color = TRANSPARENT_COLOR;
}
},
_onHoverChanged: function() {
let hover = this.actor.hover;
},
_onActivate: function() {
if (this.windows.length == 0) {
this.appInfo.launch();
Main.overview.hide();
return true;
}
return false;
}
};
@ -755,22 +1161,25 @@ AppWell.prototype = {
this._displays = displays;
},
_addApps: function(apps) {
_addApps: function(apps, isFavorite) {
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
let display = new WellDisplayItem(app, this.isFavorite);
let windows = this._appMonitor.get_windows_for_app(app.get_id());
let display;
if (windows.length > 0)
display = new RunningWellItem(app, isFavorite);
else
display = new InactiveWellItem(app, isFavorite);
this._grid.actor.add_actor(display.actor);
}
},
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
let global = Shell.Global.get();
let appSystem = Shell.AppSystem.get_default();
let app = null;
if (source instanceof WellDisplayItem) {
if (source instanceof BaseWellItem) {
app = source.appInfo;
} else if (source instanceof AppDisplayItem) {
app = appSystem.lookup_cached_app(source.getId());

View File

@ -2,6 +2,7 @@
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
@ -11,7 +12,8 @@ const Main = imports.ui.main;
const GLOW_COLOR = new Clutter.Color();
GLOW_COLOR.from_pixel(0x4f6ba4ff);
const GLOW_PADDING = 5;
const GLOW_PADDING_HORIZONTAL = 3;
const GLOW_PADDING_VERTICAL = 3;
const APP_ICON_SIZE = 48;
@ -22,27 +24,31 @@ function AppIcon(appInfo) {
AppIcon.prototype = {
_init : function(appInfo) {
this.appInfo = appInfo;
this.windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
for (let i = 0; i < this.windows.length; i++) {
this.windows[i].connect('notify::user-time', Lang.bind(this, this._resortWindows));
}
this._resortWindows();
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
corner_radius: 2,
border: 0,
padding: 1,
border_color: GenericDisplay.ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR,
reactive: true });
this.actor._delegate = this;
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER });
this._icon = appInfo.create_icon_texture(APP_ICON_SIZE);
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this.icon = appInfo.create_icon_texture(APP_ICON_SIZE);
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER });
let nameBox = new Shell.GenericContainer();
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
this._nameBox = nameBox;
this._name = new Clutter.Text({ color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
@ -50,34 +56,78 @@ AppIcon.prototype = {
line_alignment: Pango.Alignment.CENTER,
ellipsize: Pango.EllipsizeMode.END,
text: appInfo.get_name() });
nameBox.append(this._name, Big.BoxPackFlags.NONE);
if (this._windows.length > 0) {
let glow = new Shell.DrawingArea({});
glow.connect('redraw', Lang.bind(this, function (e, tex) {
Shell.draw_app_highlight(tex,
this._windows.length,
GLOW_COLOR.red / 255,
GLOW_COLOR.green / 255,
GLOW_COLOR.blue / 255,
GLOW_COLOR.alpha / 255);
}));
this._name.connect('notify::allocation', Lang.bind(this, function () {
let x = this._name.x;
let y = this._name.y;
let width = this._name.width;
let height = this._name.height;
// If we're smaller than the allocated box width, pad out the glow a bit
// to make it more visible
if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
width += GLOW_PADDING * 2;
x -= GLOW_PADDING;
}
glow.set_size(width, height);
glow.set_position(x, y);
}));
nameBox.add_actor(glow);
glow.lower(this._name);
nameBox.add_actor(this._name);
this._glowBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
let glowPath = GLib.filename_to_uri(global.imagedir + 'app-well-glow.png', '');
for (let i = 0; i < this._windows.length && i < 3; i++) {
let glow = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
glowPath, -1, -1);
glow.keep_aspect_ratio = false;
this._glowBox.append(glow, Big.BoxPackFlags.EXPAND);
}
this._nameBox.add_actor(this._glowBox);
this._glowBox.lower(this._name);
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
},
_nameBoxGetPreferredWidth: function (nameBox, forHeight, alloc) {
let [min, natural] = this._name.get_preferred_width(forHeight);
alloc.min_size = min + GLOW_PADDING_HORIZONTAL * 2;
alloc.natural_size = natural + GLOW_PADDING_HORIZONTAL * 2;
},
_nameBoxGetPreferredHeight: function (nameBox, forWidth, alloc) {
let [min, natural] = this._name.get_preferred_height(forWidth);
alloc.min_size = min + GLOW_PADDING_VERTICAL * 2;
alloc.natural_size = natural + GLOW_PADDING_VERTICAL * 2;
},
_nameBoxAllocate: function (nameBox, box, flags) {
let childBox = new Clutter.ActorBox();
let [minWidth, naturalWidth] = this._name.get_preferred_width(-1);
let [minHeight, naturalHeight] = this._name.get_preferred_height(-1);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let targetWidth = availWidth;
let xPadding = 0;
if (naturalWidth < availWidth) {
xPadding = Math.floor((availWidth - naturalWidth) / 2);
}
childBox.x1 = xPadding;
childBox.x2 = availWidth - xPadding;
childBox.y1 = GLOW_PADDING_VERTICAL;
childBox.y2 = availHeight - GLOW_PADDING_VERTICAL;
this._name.allocate(childBox, flags);
// Now the glow
if (this._glowBox != null) {
let glowPaddingHoriz = Math.max(0, xPadding - GLOW_PADDING_HORIZONTAL);
glowPaddingHoriz = Math.max(GLOW_PADDING_HORIZONTAL, glowPaddingHoriz);
childBox.x1 = glowPaddingHoriz;
childBox.x2 = availWidth - glowPaddingHoriz;
childBox.y1 = 0;
childBox.y2 = availHeight;
this._glowBox.allocate(childBox, flags);
}
},
_resortWindows: function() {
this.windows.sort(function (a, b) {
let timeA = a.get_user_time();
let timeB = b.get_user_time();
if (timeA == timeB)
return 0;
else if (timeA > timeB)
return -1;
return 1;
});
},
getDragActor: function() {
return this.appInfo.create_icon_texture(APP_ICON_SIZE);
},
getDragActorSource: function() {
return this.icon;
}
};

View File

@ -22,14 +22,12 @@ const DEFAULT_FONT = 'Sans Bold 16px';
// Padding on the left and right side of the button.
const SIDE_PADDING = 14;
function Button(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
this._init(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font);
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
}
Button.prototype = {
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
let me = this;
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
this._buttonColor = buttonColor
if (buttonColor == null)
this._buttonColor = DEFAULT_BUTTON_COLOR;
@ -42,27 +40,20 @@ Button.prototype = {
if (textColor == null)
this._textColor = DEFAULT_TEXT_COLOR;
this._staysPressed = staysPressed
if (staysPressed == null)
this._staysPressed = false;
this._font = font;
if (font == null)
this._font = DEFAULT_FONT;
// if this._staysPressed is true, this._active will be true past the first release of a button, until a subsequent one (the button
// is unpressed) or until release() is called explicitly
this._active = false;
this._isBetweenPressAndRelease = false;
this._mouseIsOverButton = false;
this.button = new Big.Box({ reactive: true,
corner_radius: 5,
padding_left: SIDE_PADDING,
padding_right: SIDE_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER
});
this.actor = new Shell.ButtonBox({ reactive: true,
corner_radius: 5,
padding_left: SIDE_PADDING,
padding_right: SIDE_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER
});
if (typeof widgetOrText == 'string') {
this._widget = new Clutter.Text({ font_name: this._font,
color: this._textColor,
@ -71,61 +62,20 @@ Button.prototype = {
this._widget = widgetOrText;
}
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
this.button.connect('button-press-event',
function(o, event) {
me._isBetweenPressAndRelease = true;
me.button.backgroundColor = me._pressedButtonColor;
return false;
});
this.button.connect('button-release-event',
function(o, event) {
me._isBetweenPressAndRelease = false;
if (!me._staysPressed || me._active) {
me.release();
} else {
me._active = true;
}
return false;
});
this.button.connect('enter-event',
function(o, event) {
me._mouseIsOverButton = true;
if (!me._active) {
me.button.backgroundColor = me._buttonColor;
}
me.emit('enter-event');
return false;
});
this.button.connect('leave-event',
function(o, event) {
me._isBetweenPressAndRelease = false;
me._mouseIsOverButton = false;
if (!me._active) {
me.button.backgroundColor = null;
}
me.emit('leave-event');
return false;
});
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
},
pressIn : function() {
if (!this._isBetweenPressAndRelease && this._staysPressed) {
this._active = true;
this.button.backgroundColor = this._pressedButtonColor;
}
},
release : function() {
if (!this._isBetweenPressAndRelease && this._staysPressed) {
this._active = false;
if (this._mouseIsOverButton) {
this.button.backgroundColor = this._buttonColor;
} else {
this.button.backgroundColor = null;
}
}
_updateColors : function() {
if (this.actor.active || this.actor.pressed)
this.actor.backgroundColor = this._pressedButtonColor;
else if (this.actor.hover)
this.actor.backgroundColor = this._buttonColor;
else
this.actor.backgroundColor = null;
}
};
@ -156,16 +106,15 @@ iconButton.prototype = {
this.actor.set_opacity(0);
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
this._shouldHide = false;
// Nothing to do if the cursor has come back from a child of the parent actor
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
if (actor.get_children().indexOf(event.get_related()) != -1)
return;
this._fadeIn();
}));
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
// Nothing to do if the cursor has merely entered a child of the parent actor
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
if (actor.get_children().indexOf(event.get_related()) != -1)
return;
// Remember that we should not be visible to hide the button if forceShow is unset

View File

@ -18,8 +18,6 @@ function Chrome() {
Chrome.prototype = {
_init: function() {
let global = Shell.Global.get();
// The group itself has zero size so it doesn't interfere with DND
this.actor = new Clutter.Group({ width: 0, height: 0 });
global.stage.add_actor(this.actor);
@ -238,7 +236,6 @@ Chrome.prototype = {
},
_windowsRestacked: function() {
let global = Shell.Global.get();
let windows = global.get_windows();
// The chrome layer should be visible unless there is a window
@ -280,7 +277,6 @@ Chrome.prototype = {
},
_updateRegions: function() {
let global = Shell.Global.get();
let rects = [], struts = [], i;
delete this._updateRegionIdle;

View File

@ -70,6 +70,34 @@ const PANE_BORDER_WIDTH = 2;
const PANE_BACKGROUND_COLOR = new Clutter.Color();
PANE_BACKGROUND_COLOR.from_pixel(0x000000f4);
const APPS = "apps";
const PREFS = "prefs";
const DOCS = "docs";
/*
* Returns the index in an array of a given length that is obtained
* if the provided index is incremented by an increment and the array
* is wrapped in if necessary.
*
* index: prior index, expects 0 <= index < length
* increment: the change in index, expects abs(increment) <= length
* length: the length of the array
*/
function _getIndexWrapped(index, increment, length) {
return (index + increment + length) % length;
}
function _createDisplay(displayType) {
if (displayType == APPS)
return new AppDisplay.AppDisplay();
else if (displayType == PREFS)
return new AppDisplay.AppDisplay(true);
else if (displayType == DOCS)
return new DocDisplay.DocDisplay();
return null;
}
function Pane() {
this._init();
}
@ -92,7 +120,6 @@ Pane.prototype = {
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 6 });
let global = Shell.Global.get();
let closeIconUri = "file://" + global.imagedir + "close.svg";
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
closeIconUri,
@ -146,12 +173,12 @@ Pane.prototype = {
}
Signals.addSignalMethods(Pane.prototype);
function ResultArea(displayClass, enableNavigation) {
this._init(displayClass, enableNavigation);
function ResultArea(displayType, enableNavigation) {
this._init(displayType, enableNavigation);
}
ResultArea.prototype = {
_init : function(displayClass, enableNavigation) {
_init : function(displayType, enableNavigation) {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
this.resultsContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_PADDING
@ -160,7 +187,7 @@ ResultArea.prototype = {
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
this.display = new displayClass();
this.display = _createDisplay(displayType);
this.navArea = this.display.getNavigationArea();
if (enableNavigation && this.navArea)
@ -217,10 +244,10 @@ ResultPane.prototype = {
this._dash = dash;
},
// Create an instance of displayClass and pack it into this pane's
// content area. Return the displayClass instance.
packResults: function(displayClass, enableNavigation) {
let resultArea = new ResultArea(displayClass, enableNavigation);
// Create a display of displayType and pack it into this pane's
// content area. Return the display.
packResults: function(displayType, enableNavigation) {
let resultArea = new ResultArea(displayType, enableNavigation);
createPaneForDetails(this._dash, resultArea.display);
@ -288,7 +315,6 @@ SearchEntry.prototype = {
padding_right: 4 });
box.append(this._iconBox, Big.BoxPackFlags.END);
let global = Shell.Global.get();
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
magnifierUri, 18, 18);
@ -393,6 +419,30 @@ MoreLink.prototype = {
Signals.addSignalMethods(MoreLink.prototype);
function BackLink() {
this._init();
}
BackLink.prototype = {
_init : function () {
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_right: DEFAULT_PADDING,
padding_left: DEFAULT_PADDING,
reactive: true,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
border_right: SECTION_BORDER,
border_color: SECTION_BORDER_COLOR });
let backIconUri = "file://" + global.imagedir + "back.svg";
let backIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
backIconUri,
12,
16);
this.actor.append(backIcon, Big.BoxPackFlags.NONE);
}
}
function SectionHeader(title, suppressBrowse) {
this._init(title, suppressBrowse);
}
@ -416,6 +466,14 @@ SectionHeader.prototype = {
backgroundGradient.set_size(width, height);
}));
this.backLink = new BackLink();
this._innerBox.append(this.backLink.actor, Big.BoxPackFlags.NONE);
this.backLink.actor.hide();
this.backLink.actor.connect('activate', Lang.bind(this, function (actor) {
this.emit('back-link-activated');
}));
let textBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: DEFAULT_PADDING,
padding_bottom: DEFAULT_PADDING });
@ -424,15 +482,42 @@ SectionHeader.prototype = {
text: title });
textBox.append(this.text, Big.BoxPackFlags.NONE);
this.countText = new Clutter.Text({ color: TEXT_COLOR,
font_name: 'Sans Bold 14px' });
textBox.append(this.countText, Big.BoxPackFlags.END);
this.countText.hide();
this._innerBox.append(textBox, Big.BoxPackFlags.EXPAND);
if (!suppressBrowse) {
this.moreLink = new MoreLink();
this._innerBox.append(this.moreLink.actor, Big.BoxPackFlags.END);
}
},
setTitle : function(title) {
this.text.text = title;
},
setBackLinkVisible : function(visible) {
if (visible)
this.backLink.actor.show();
else
this.backLink.actor.hide();
},
setCountText : function(countText) {
if (countText == "") {
this.countText.hide();
} else {
this.countText.show();
this.countText.text = countText;
}
}
}
Signals.addSignalMethods(SectionHeader.prototype);
function SearchSectionHeader(title, onClick) {
this._init(title, onClick);
}
@ -457,37 +542,22 @@ SearchSectionHeader.prototype = {
box.append(this.countText, Big.BoxPackFlags.END);
this.tooltip.hide();
this._showTooltip = true;
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
TEXT_COLOR, false, null);
button.button.height = box.height;
button.button.padding_left = DEFAULT_PADDING;
button.button.padding_right = DEFAULT_PADDING;
TEXT_COLOR);
button.actor.height = box.height;
button.actor.padding_left = DEFAULT_PADDING;
button.actor.padding_right = DEFAULT_PADDING;
button.button.connect('button-release-event', onClick);
button.connect('enter-event', Lang.bind(this, this._onButtonEntered));
button.connect('leave-event', Lang.bind(this, this._onButtonLeft));
this.actor = button.button;
button.actor.connect('activate', onClick);
button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip));
this.actor = button.actor;
},
_onButtonEntered : function() {
if (this._showTooltip)
_updateTooltip : function(actor) {
if (actor.hover)
this.tooltip.show();
},
_onButtonLeft : function() {
this.tooltip.hide();
},
setShowTooltip : function(showTooltip) {
this._showTooltip = showTooltip;
// Because we only show tooltip on mouse-over,
// we should not just show it here if showTooltip is
// set to true, but in the future we could check if
// the mouse happens to be over the header and show it
// in that case.
if (!this._showTooltip)
else
this.tooltip.hide();
}
}
@ -512,8 +582,6 @@ function Dash() {
Dash.prototype = {
_init : function() {
let global = Shell.Global.get();
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them
// are not passed to the transparent background underneath them. This background is used for the workspaces area when
// the additional dash panes are being shown and it handles clicks by closing the additional panes, so that the user
@ -567,29 +635,62 @@ Dash.prototype = {
this._searchTimeoutId = 0;
let text = this._searchEntry.getText();
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
this._appSearchResultArea.display.setSearch(text);
this._docSearchResultArea.display.setSearch(text);
this._appSearchHeader.countText.text = this._appSearchResultArea.display.getMatchedItemsCount() + "";
this._docSearchHeader.countText.text = this._docSearchResultArea.display.getMatchedItemsCount() + "";
let selectionSet = false;
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
section.resultArea.display.setSearch(text);
let itemCount = section.resultArea.display.getMatchedItemsCount();
let itemCountText = itemCount + "";
section.header.countText.text = itemCountText;
if (this._searchResultsSingleShownSection == section.type) {
this._searchResultsSection.header.setCountText(itemCountText);
if (itemCount == 0) {
section.resultArea.actor.hide();
} else {
section.resultArea.actor.show();
}
} else if (this._searchResultsSingleShownSection == null) {
// Don't show the section if it has no results
if (itemCount == 0) {
section.header.actor.hide();
section.resultArea.actor.hide();
} else {
section.header.actor.show();
section.resultArea.actor.show();
}
}
// Refresh the selection when a new search is applied.
section.resultArea.display.unsetSelected();
if (!selectionSet && section.resultArea.display.hasItems() &&
(this._searchResultsSingleShownSection == null || this._searchResultsSingleShownSection == section.type)) {
section.resultArea.display.selectFirstItem();
selectionSet = true;
}
}
return false;
}));
}));
this._searchEntry.entry.connect('activate', Lang.bind(this, function (se) {
// only one of the displays will have an item selected, so it's ok to
// call activateSelected() on all of them
this._appSearchResultArea.display.activateSelected();
this._docSearchResultArea.display.activateSelected();
// Only one of the displays will have an item selected, so it's ok to
// call activateSelected() on all of them.
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
section.resultArea.display.activateSelected();
}
return true;
}));
this._searchEntry.entry.connect('key-press-event', Lang.bind(this, function (se, e) {
let text = this._searchEntry.getText();
let symbol = Shell.get_event_key_symbol(e);
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
// Escape will keep clearing things back to the desktop.
// If we are showing a particular section of search, go back to all sections.
if (this._getOnlyAppSearchShown() || this._getOnlyDocSearchShown())
if (this._searchResultsSingleShownSection != null)
this._showAllSearchSections();
// If we have an active search, we remove it.
else if (this._searchActive)
@ -608,22 +709,40 @@ Dash.prototype = {
// too, but there doesn't seem to be any flickering if we first select
// something in one display, but then unset the selection, and move
// it to the other display, so it's ok to do that.
if (this._docSearchResultArea.display.hasSelected())
this._docSearchResultArea.display.selectUp();
else if (this._appSearchResultArea.display.hasItems())
this._appSearchResultArea.display.selectUp();
else
this._docSearchResultArea.display.selectUp();
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectUp()) {
if (this._searchResultsSingleShownSection != section.type) {
// We need to move the selection to the next section above this section that has items,
// wrapping around at the bottom, if necessary.
let newSectionIndex = this._findAnotherSectionWithItems(i, -1);
if (newSectionIndex >= 0) {
this._searchSections[newSectionIndex].resultArea.display.selectLastItem();
section.resultArea.display.unsetSelected();
}
}
break;
}
}
return true;
} else if (symbol == Clutter.Down) {
if (!this._searchActive)
return true;
if (this._docSearchResultArea.display.hasSelected())
this._docSearchResultArea.display.selectDown();
else if (this._appSearchResultArea.display.hasItems())
this._appSearchResultArea.display.selectDown();
else
this._docSearchResultArea.display.selectDown();
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
if (section.resultArea.display.hasSelected() && !section.resultArea.display.selectDown()) {
if (this._searchResultsSingleShownSection != section.type) {
// We need to move the selection to the next section below this section that has items,
// wrapping around at the top, if necessary.
let newSectionIndex = this._findAnotherSectionWithItems(i, 1);
if (newSectionIndex >= 0) {
this._searchSections[newSectionIndex].resultArea.display.selectFirstItem();
section.resultArea.display.unsetSelected();
}
}
break;
}
}
return true;
}
return false;
@ -639,7 +758,7 @@ Dash.prototype = {
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
if (this._moreAppsPane == null) {
this._moreAppsPane = new ResultPane(this);
this._moreAppsPane.packResults(AppDisplay.AppDisplay, true);
this._moreAppsPane.packResults(APPS, true);
this._addPane(this._moreAppsPane);
link.setPane(this._moreAppsPane);
}
@ -667,7 +786,7 @@ Dash.prototype = {
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
if (this._moreDocsPane == null) {
this._moreDocsPane = new ResultPane(this);
this._moreDocsPane.packResults(DocDisplay.DocDisplay, true);
this._moreDocsPane.packResults(DOCS, true);
this._addPane(this._moreDocsPane);
link.setPane(this._moreDocsPane);
}
@ -679,36 +798,49 @@ Dash.prototype = {
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
this._appSearchHeader = new SearchSectionHeader(_("APPLICATIONS"),
Lang.bind(this,
function () {
this._toggleOnlyAppSearchShown();
return true;
}));
this._searchResultsSection.content.append(this._appSearchHeader.actor, Big.BoxPackFlags.NONE);
this._appSearchResultArea = new ResultArea(AppDisplay.AppDisplay, false);
this._appSearchResultArea.controlBox.hide();
this._searchResultsSection.content.append(this._appSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
createPaneForDetails(this, this._appSearchResultArea.display);
this._searchResultsSingleShownSection = null;
this._docSearchHeader = new SearchSectionHeader(_("RECENT DOCUMENTS"),
Lang.bind(this,
function () {
this._toggleOnlyDocSearchShown();
return true;
}));
this._searchResultsSection.content.append(this._docSearchHeader.actor, Big.BoxPackFlags.NONE);
this._docSearchResultArea = new ResultArea(DocDisplay.DocDisplay, false);
this._docSearchResultArea.controlBox.hide();
this._searchResultsSection.content.append(this._docSearchResultArea.actor, Big.BoxPackFlags.EXPAND);
createPaneForDetails(this, this._docSearchResultArea.display);
this._searchResultsSection.header.connect('back-link-activated', Lang.bind(this, function () {
this._showAllSearchSections();
}));
this._searchSections = [
{ type: APPS,
title: _("APPLICATIONS"),
header: null,
resultArea: null
},
{ type: PREFS,
title: _("PREFERENCES"),
header: null,
resultArea: null
},
{ type: DOCS,
title: _("RECENT DOCUMENTS"),
header: null,
resultArea: null
}
];
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
section.header = new SearchSectionHeader(section.title,
Lang.bind(this,
function () {
this._showSingleSearchSection(section.type);
}));
this._searchResultsSection.content.append(section.header.actor, Big.BoxPackFlags.NONE);
section.resultArea = new ResultArea(section.type, false);
section.resultArea.controlBox.hide();
this._searchResultsSection.content.append(section.resultArea.actor, Big.BoxPackFlags.EXPAND);
createPaneForDetails(this, section.resultArea.display);
}
this.sectionArea.append(this._searchResultsSection.actor, Big.BoxPackFlags.EXPAND);
this._searchResultsSection.actor.hide();
},
show: function() {
let global = Shell.Global.get();
global.stage.set_key_focus(this._searchEntry.entry);
},
@ -753,67 +885,79 @@ Dash.prototype = {
}
},
_toggleOnlyAppSearchShown: function() {
if (this._getOnlyAppSearchShown()) {
this._setDocSearchShown(true);
} else {
this._setDocSearchShown(false);
_showSingleSearchSection: function(type) {
// We currently don't allow going from showing one section to showing another section.
if (this._searchResultsSingleShownSection != null) {
throw new Error("We were already showing a single search section: '" + this._searchResultsSingleShownSection
+ "' when _showSingleSearchSection() was called for '" + type + "'");
}
},
_toggleOnlyDocSearchShown: function() {
if (this._getOnlyDocSearchShown()) {
this._setAppSearchShown(true);
} else {
this._setAppSearchShown(false);
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
if (section.type == type) {
// This will be the only section shown.
section.resultArea.display.selectFirstItem();
section.resultArea.controlBox.show();
let itemCount = section.resultArea.display.getMatchedItemsCount();
let itemCountText = itemCount + "";
section.header.actor.hide();
this._searchResultsSection.header.setTitle(section.title);
this._searchResultsSection.header.setBackLinkVisible(true);
this._searchResultsSection.header.setCountText(itemCountText);
} else {
// We need to hide this section.
section.header.actor.hide();
section.resultArea.actor.hide();
section.resultArea.display.unsetSelected();
}
}
},
// TODO: the following two functions currently rely on us showing the
// section header even if there are no results in that section. We'll need
// to change the check if we update that behavior. We'll also need to change
// the check if we add more sections to search results.
_getOnlyAppSearchShown: function() {
return this._searchActive && !this._docSearchHeader.actor.visible;
},
_getOnlyDocSearchShown: function() {
return this._searchActive && !this._appSearchHeader.actor.visible;
},
_setAppSearchShown: function(show) {
if (show) {
this._appSearchHeader.actor.show();
this._appSearchResultArea.actor.show();
this._docSearchResultArea.display.displayPage(0);
this._docSearchResultArea.controlBox.hide();
this._docSearchHeader.setShowTooltip(true);
} else {
this._appSearchHeader.actor.hide();
this._appSearchResultArea.actor.hide();
this._docSearchResultArea.controlBox.show();
this._docSearchHeader.setShowTooltip(false);
}
},
_setDocSearchShown: function(show) {
if (show) {
this._docSearchHeader.actor.show();
this._docSearchResultArea.actor.show();
this._appSearchResultArea.display.displayPage(0);
this._appSearchResultArea.controlBox.hide();
this._appSearchHeader.setShowTooltip(true);
} else {
this._docSearchHeader.actor.hide();
this._docSearchResultArea.actor.hide();
this._appSearchResultArea.controlBox.show();
this._appSearchHeader.setShowTooltip(false);
}
this._searchResultsSingleShownSection = type;
},
_showAllSearchSections: function() {
this._setAppSearchShown(true);
this._setDocSearchShown(true);
if (this._searchResultsSingleShownSection != null) {
let selectionSet = false;
for (var i = 0; i < this._searchSections.length; i++) {
let section = this._searchSections[i];
if (section.type == this._searchResultsSingleShownSection) {
// This will no longer be the only section shown.
section.resultArea.display.displayPage(0);
section.resultArea.controlBox.hide();
let itemCount = section.resultArea.display.getMatchedItemsCount();
if (itemCount != 0) {
section.header.actor.show();
section.resultArea.display.selectFirstItem();
selectionSet = true;
}
this._searchResultsSection.header.setTitle(_("SEARCH RESULTS"));
this._searchResultsSection.header.setBackLinkVisible(false);
this._searchResultsSection.header.setCountText("");
} else {
// We need to restore this section.
let itemCount = section.resultArea.display.getMatchedItemsCount();
if (itemCount != 0) {
section.header.actor.show();
section.resultArea.actor.show();
// This ensures that some other section will have the selection if the
// single section that was being displayed did not have any items.
if (!selectionSet) {
section.resultArea.display.selectFirstItem();
selectionSet = true;
}
}
}
}
this._searchResultsSingleShownSection = null;
}
},
_findAnotherSectionWithItems: function(index, increment) {
let pos = _getIndexWrapped(index, increment, this._searchSections.length);
while (pos != index) {
if (this._searchSections[pos].resultArea.display.hasItems())
return pos;
pos = _getIndexWrapped(pos, increment, this._searchSections.length);
}
return -1;
}
};
Signals.addSignalMethods(Dash.prototype);

View File

@ -8,15 +8,17 @@ const Tweener = imports.ui.tweener;
const SNAP_BACK_ANIMATION_TIME = 0.25;
function _Draggable(actor) {
this._init(actor);
function _Draggable(actor, manualMode) {
this._init(actor, manualMode);
}
_Draggable.prototype = {
_init : function(actor) {
_init : function(actor, manualMode) {
this.actor = actor;
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
if (!manualMode)
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this._haveSourceGrab = false;
},
_onButtonPress : function (actor, event) {
@ -25,6 +27,7 @@ _Draggable.prototype = {
if (Tweener.getTweenCount(actor))
return false;
this._haveSourceGrab = true;
this._grabActor(actor);
let [stageX, stageY] = event.get_coords();
@ -66,6 +69,80 @@ _Draggable.prototype = {
return false;
},
/**
* startDrag:
* @actor: Origin actor for drag and drop
* @stageX: X coordinate of event
* @stageY: Y coordinate of event
* @time: Event timestamp
*
* Directly initiate a drag and drop operation from the given actor.
* This function is useful to call if you've specified manualMode
* for the draggable.
*/
startDrag: function (actor, stageX, stageY, time) {
this.emit('drag-begin', time);
this._dragStartX = stageX;
this._dragStartY = stageY;
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
// Drag actor does not always have to be the same as actor. For example drag actor
// can be an image that's part of the actor. So to perform "snap back" correctly we need
// to know what was the drag actor source.
if (this.actor._delegate.getDragActorSource) {
this._dragActorSource = this.actor._delegate.getDragActorSource();
// If the user dragged from the source, then position
// the dragActor over it. Otherwise, center it
// around the pointer
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
let x, y;
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
stageY > sourceY && stageY <= sourceY + sourceHeight) {
x = sourceX;
y = sourceY;
} else {
x = stageX - this._dragActor.width / 2;
y = stageY - this._dragActor.height / 2;
}
this._dragActor.set_position(x, y);
} else {
this._dragActorSource = this.actor;
}
this._dragOrigParent = undefined;
if (this._haveSourceGrab) {
this._haveSourceGrab = false;
this._ungrabActor(actor);
}
this._grabActor(this._dragActor);
this._dragOffsetX = this._dragActor.x - this._dragStartX;
this._dragOffsetY = this._dragActor.y - this._dragStartY;
} else {
this._dragActor = actor;
this._dragActorSource = undefined;
this._dragOrigParent = actor.get_parent();
this._dragOrigX = this._dragActor.x;
this._dragOrigY = this._dragActor.y;
this._dragOrigScale = this._dragActor.scale_x;
let [actorStageX, actorStageY] = actor.get_transformed_position();
this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY;
// Set the actor's scale such that it will keep the same
// transformed size when it's reparented to the stage
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
actor.set_scale(scaledWidth / actor.width,
scaledHeight / actor.height);
}
this._dragActor.reparent(actor.get_stage());
this._dragActor.raise_top();
},
_onMotion : function (actor, event) {
let [stageX, stageY] = event.get_coords();
@ -75,55 +152,7 @@ _Draggable.prototype = {
if (!this._dragActor &&
(Math.abs(stageX - this._dragStartX) > threshold ||
Math.abs(stageY - this._dragStartY) > threshold)) {
this.emit('drag-begin', event.get_time());
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
// Drag actor does not always have to be the same as actor. For example drag actor
// can be an image that's part of the actor. So to perform "snap back" correctly we need
// to know what was the drag actor source.
if (this.actor._delegate.getDragActorSource) {
this._dragActorSource = this.actor._delegate.getDragActorSource();
// If the user dragged from the source, then position
// the dragActor over it. Otherwise, center it
// around the pointer
let [sourceX, sourceY] = this._dragActorSource.get_transformed_position();
let [sourceWidth, sourceHeight] = this._dragActorSource.get_transformed_size();
if (stageX > sourceX && stageX <= sourceX + sourceWidth &&
stageY > sourceY && stageY <= sourceY + sourceHeight)
this._dragActor.set_position(sourceX, sourceY);
else
this._dragActor.set_position(stageX - this._dragActor.width / 2, stageY - this._dragActor.height / 2);
} else {
this._dragActorSource = this.actor;
}
this._dragOrigParent = undefined;
this._ungrabActor(actor);
this._grabActor(this._dragActor);
this._dragOffsetX = this._dragActor.x - this._dragStartX;
this._dragOffsetY = this._dragActor.y - this._dragStartY;
} else {
this._dragActor = actor;
this._dragActorSource = undefined;
this._dragOrigParent = actor.get_parent();
this._dragOrigX = this._dragActor.x;
this._dragOrigY = this._dragActor.y;
this._dragOrigScale = this._dragActor.scale_x;
let [actorStageX, actorStageY] = actor.get_transformed_position();
this._dragOffsetX = actorStageX - this._dragStartX;
this._dragOffsetY = actorStageY - this._dragStartY;
// Set the actor's scale such that it will keep the same
// transformed size when it's reparented to the stage
let [scaledWidth, scaledHeight] = actor.get_transformed_size();
actor.set_scale(scaledWidth / actor.width,
scaledHeight / actor.height);
}
this._dragActor.reparent(actor.get_stage());
this._dragActor.raise_top();
this.startDrag(actor, stageX, stageY, event.get_time());
}
// If we are dragging, update the position
@ -149,7 +178,7 @@ _Draggable.prototype = {
event.get_time());
}
target = target.get_parent();
}
}
}
return true;
@ -225,6 +254,13 @@ _Draggable.prototype = {
Signals.addSignalMethods(_Draggable.prototype);
function makeDraggable(actor) {
return new _Draggable(actor);
/**
* makeDraggable:
* @actor: Source actor
* @manualMode: If given, do not automatically start drag and drop on click
*
* Create an object which controls drag and drop for the given actor.
*/
function makeDraggable(actor, manualMode) {
return new _Draggable(actor, manualMode);
}

View File

@ -102,7 +102,7 @@ DocDisplayItem.prototype = {
_resetTimeDisplay: function(currentSecs) {
let lastSecs = this._docInfo.timestamp;
let timeDelta = currentSecs - lastSecs;
let [text, nextUpdate] = Shell.Global.get().format_time_relative_pretty(timeDelta);
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
this._timeoutTime = currentSecs + nextUpdate;
this._setDescriptionText(text);
}
@ -120,8 +120,6 @@ DocDisplay.prototype = {
_init : function() {
GenericDisplay.GenericDisplay.prototype._init.call(this);
let me = 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
@ -132,14 +130,14 @@ DocDisplay.prototype = {
this._docManager = DocInfo.getDocManager();
this._docsStale = true;
this._docManager.connect('changed', function(mgr, userData) {
me._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.
me._redisplay(false);
});
this._redisplay(false);
}));
this.connect('destroy', Lang.bind(this, function (o) {
if (this._updateTimeoutId > 0)

View File

@ -7,6 +7,7 @@ const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
@ -87,7 +88,6 @@ GenericDisplayItem.prototype = {
spacing: DEFAULT_PADDING });
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
let global = Shell.Global.get();
let infoIconUri = "file://" + global.imagedir + "info.svg";
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
infoIconUri,
@ -426,7 +426,11 @@ GenericDisplay.prototype = {
// Returns true if the display has any displayed items.
hasItems: function() {
return this._list.displayedCount > 0;
// 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._matchedItems.length > 0;
},
getMatchedItemsCount: function() {
@ -457,6 +461,10 @@ GenericDisplay.prototype = {
// Displays the page specified by the pageNumber argument.
displayPage: function(pageNumber) {
// Cleanup from the previous selection, but don't unset this._selectedIndex
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}
this._list.page = pageNumber;
},
@ -487,24 +495,23 @@ GenericDisplay.prototype = {
this.selectFirstItem();
}
// We currently redisplay matching items and raise the sideshow as part of two different callbacks.
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
Mainloop.timeout_add(5,
Lang.bind(this,
function() {
// Check if the pointer is over one of the items and display the information button if it is.
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let global = Shell.Global.get();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor);
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}));
// Check if the pointer is over one of the items and display the information button if it is.
// We want to do this between finishing our changes to the display and the point where
// the display is redrawn.
Mainloop.idle_add(Lang.bind(this,
function() {
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor);
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}),
Meta.PRIORITY_BEFORE_REDRAW);
},
// Creates a display item based on the information associated with itemId
@ -698,9 +705,11 @@ GenericDisplay.prototype = {
*/
_updateDisplayControl: function(resetDisplayControl) {
if (resetDisplayControl) {
this._selectedIndex = -1;
this.displayControl.remove_all();
let nPages = this._list.n_pages;
// Don't show the page indicator if there is only one page.
if (nPages == 1)
return;
let pageNumber = this._list.page;
for (let i = 0; i < nPages; i++) {
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
@ -730,6 +739,9 @@ GenericDisplay.prototype = {
}
}
}
if (this.hasSelected()) {
this.selectFirstItem();
}
},
// Returns a display item based on its index in the ordering of the
@ -754,17 +766,8 @@ GenericDisplay.prototype = {
// Selects (e.g. highlights) a display item at the provided index,
// updates this.selectedItemDetails actor, and emits 'selected' signal.
_selectIndex: function(index) {
if (index >= this._list.displayedCount)
return
// If the item is already selected, all we do is toggling the details pane.
if (this._selectedIndex == index && index >= 0) {
this.emit('details', index);
return;
}
// Cleanup from the previous item
if (this._selectedIndex >= 0) {
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}

View File

@ -35,7 +35,6 @@ var commandHeader = "const Clutter = imports.gi.Clutter; " +
"const Tweener = imports.ui.tweener; " +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
"const global = Shell.Global.get(); " +
"const stage = global.stage; " +
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
/* Special lookingGlass functions */
@ -249,7 +248,6 @@ function Inspector() {
Inspector.prototype = {
_init: function() {
let global = Shell.Global.get();
let width = 150;
let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
border: 1,
@ -274,7 +272,6 @@ Inspector.prototype = {
}));
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
let global = Shell.Global.get();
Clutter.ungrab_pointer(eventHandler);
let [stageX, stageY] = event.get_coords();
@ -288,7 +285,6 @@ Inspector.prototype = {
}));
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
let global = Shell.Global.get();
let [stageX, stageY] = event.get_coords();
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
stageX,
@ -312,8 +308,6 @@ function LookingGlass() {
LookingGlass.prototype = {
_init : function() {
let global = Shell.Global.get();
this._idleHistorySaveId = 0;
let historyPath = global.configdir + "/lookingglass-history.txt";
this._historyFile = Gio.file_new_for_path(historyPath);
@ -392,7 +386,7 @@ LookingGlass.prototype = {
activatable: true,
singleLineMode: true,
text: ''});
/* kind of a hack */
/* unmapping the edit box will un-focus it, undo that */
notebook.connect('selection', Lang.bind(this, function (nb, child) {
if (child == this._evalBox)
global.stage.set_key_focus(this._entry);
@ -423,7 +417,7 @@ LookingGlass.prototype = {
return true;
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = Shell.get_event_key_symbol(e);
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
@ -524,8 +518,7 @@ LookingGlass.prototype = {
},
_resizeTo: function(actor) {
let stage = Shell.Global.get().stage;
let stageWidth = stage.width;
let stage = global.stage;
let myWidth = stage.width * 0.7;
let myHeight = stage.height * 0.7;
let [srcX, srcY] = actor.get_transformed_position();
@ -555,10 +548,7 @@ LookingGlass.prototype = {
Tweener.removeTweens(this.actor);
if (!Main.beginModal())
return;
let global = Shell.Global.get();
Main.pushModal(this.actor);
global.stage.set_key_focus(this._entry);
Tweener.addTween(this.actor, { time: 0.5,
@ -575,7 +565,7 @@ LookingGlass.prototype = {
this._open = false;
Tweener.removeTweens(this.actor);
Main.endModal();
Main.popModal(this.actor);
Tweener.addTween(this.actor, { time: 0.5,
transition: "easeOutQuad",

View File

@ -30,10 +30,14 @@ let runDialog = null;
let lookingGlass = null;
let wm = null;
let recorder = null;
let inModal = false;
let modalCount = 0;
let modalActorFocusStack = [];
function start() {
let global = Shell.Global.get();
// Add a binding for "global" in the global JS namespace; (gjs
// keeps the web browser convention of having that namespace be
// called "window".)
window.global = Shell.Global.get();
Gio.DesktopAppInfo.set_desktop_env("GNOME");
@ -64,10 +68,7 @@ function start() {
global.connect('panel-run-dialog', function(panel) {
// Make sure not more than one run dialog is shown.
if (runDialog == null) {
runDialog = new RunDialog.RunDialog();
}
runDialog.open();
getRunDialog().open();
});
overview = new Overview.Overview();
@ -102,7 +103,6 @@ function start() {
}
function _relayout() {
let global = Shell.Global.get();
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
overview.relayout();
}
@ -114,8 +114,6 @@ function _relayout() {
// is called.)
function _removeUnusedWorkspaces() {
let global = Shell.Global.get();
let windows = global.get_windows();
let maxWorkspace = 0;
for (let i = 0; i < windows.length; i++) {
@ -149,13 +147,13 @@ function _removeUnusedWorkspaces() {
// should be asking Mutter to resolve the key into an action and then
// base our handling based on the action.
function _globalKeyPressHandler(actor, event) {
if (!inModal)
if (modalCount == 0)
return false;
let type = event.type();
if (type == Clutter.EventType.KEY_PRESS) {
let symbol = Shell.get_event_key_symbol (event);
let symbol = event.get_key_symbol();
if (symbol == Clutter.Print) {
// We want to be able to take screenshots of the shell at all times
let gconf = Shell.GConf.get_default();
@ -169,7 +167,7 @@ function _globalKeyPressHandler(actor, event) {
return true;
}
} else if (type == Clutter.EventType.KEY_RELEASE) {
let symbol = Shell.get_event_key_symbol (event);
let symbol = event.get_key_symbol();
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.
@ -177,35 +175,96 @@ function _globalKeyPressHandler(actor, event) {
overview.hide();
return true;
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
getRunDialog().open();
}
}
return false;
}
// Used to go into a mode where all keyboard and mouse input goes to
// the stage. Returns true if we successfully grabbed the keyboard and
// went modal, false otherwise
function beginModal() {
let global = Shell.Global.get();
let timestamp = global.screen.get_display().get_current_time();
if (!global.begin_modal(timestamp))
return false;
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
inModal = true;
return true;
function _findModal(actor) {
for (let i = 0; i < modalActorFocusStack.length; i++) {
let [stackActor, stackFocus] = modalActorFocusStack[i];
if (stackActor == actor) {
return i;
}
}
return -1;
}
function endModal() {
let global = Shell.Global.get();
/**
* pushModal:
* @actor: #ClutterActor which will be given keyboard focus
*
* Ensure we are in a mode where all keyboard and mouse input goes to
* the stage. Multiple calls to this function act in a stacking fashion;
* the effect will be undone when an equal number of popModal() invocations
* have been made.
*
* Next, record the current Clutter keyboard focus on a stack. If the modal stack
* returns to this actor, reset the focus to the actor which was focused
* at the time pushModal() was invoked.
*/
function pushModal(actor) {
let timestamp = global.screen.get_display().get_current_time();
modalCount += 1;
actor.connect('destroy', function() {
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack.splice(index, 1);
});
let curFocus = global.stage.get_key_focus();
if (curFocus != null) {
curFocus.connect('destroy', function() {
let index = _findModal(actor);
if (index >= 0)
modalActorFocusStack[index][1] = null;
});
}
modalActorFocusStack.push([actor, curFocus]);
if (modalCount > 1)
return;
if (!global.begin_modal(timestamp)) {
log("pushModal: invocation of begin_modal failed");
return;
}
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
}
/**
* popModal:
* @actor: #ClutterActor passed to original invocation of pushModal().
*
* Reverse the effect of pushModal(). If this invocation is undoing
* the topmost invocation, then the focus will be restored to the
* previous focus at the time when pushModal() was invoked.
*/
function popModal(actor) {
let timestamp = global.screen.get_display().get_current_time();
modalCount -= 1;
let focusIndex = _findModal(actor);
if (focusIndex >= 0) {
if (focusIndex == modalActorFocusStack.length - 1) {
let [stackActor, stackFocus] = modalActorFocusStack[focusIndex];
global.stage.set_key_focus(stackFocus);
} else {
// Remove from the middle, shift the focus chain up
for (let i = focusIndex; i < modalActorFocusStack.length - 1; i++) {
modalActorFocusStack[i + 1][1] = modalActorFocusStack[i][1];
}
}
modalActorFocusStack.splice(focusIndex, 1);
}
if (modalCount > 0)
return;
global.end_modal(timestamp);
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
inModal = false;
}
function createLookingGlass() {
@ -216,8 +275,14 @@ function createLookingGlass() {
return lookingGlass;
}
function getRunDialog() {
if (runDialog == null) {
runDialog = new RunDialog.RunDialog();
}
return runDialog;
}
function createAppLaunchContext() {
let global = Shell.Global.get();
let screen = global.screen;
let display = screen.get_display();

View File

@ -73,6 +73,7 @@ const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
let addRemoveButtonSize = null;
function Overview() {
this._init();
@ -80,10 +81,6 @@ function Overview() {
Overview.prototype = {
_init : function() {
let me = this;
let global = Shell.Global.get();
this._group = new Clutter.Group();
this._group._delegate = this;
@ -95,7 +92,15 @@ Overview.prototype = {
this._activeDisplayPane = null;
// Used to catch any clicks when we have an active pane; see the comments
// During transitions, we raise this to the top to avoid having the overview
// area be reactive; it causes too many issues such as double clicks on
// Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Rectangle({ opacity: 0,
reactive: true });
this._group.add_actor(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
// Similar to the cover pane but used for dialogs ("panes"); see the comments
// in addPane below.
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
reactive: true });
@ -127,12 +132,12 @@ Overview.prototype = {
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._coverPane.lower_bottom();
this._workspaces = null;
},
_recalculateGridSizes: function () {
let global = Shell.Global.get();
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
// We divide the screen into an imaginary grid which helps us determine the layout of
@ -147,12 +152,14 @@ Overview.prototype = {
},
relayout: function () {
let global = Shell.Global.get();
let screenHeight = global.screen_height;
let screenWidth = global.screen_width;
let contentHeight = screenHeight - Panel.PANEL_HEIGHT;
let contentY = Panel.PANEL_HEIGHT;
let contentHeight = screenHeight - contentY;
this._coverPane.set_position(0, contentY);
this._coverPane.set_size(screenWidth, contentHeight);
let workspaceColumnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
let workspaceRowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
@ -167,22 +174,21 @@ Overview.prototype = {
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
let dashY = Panel.PANEL_HEIGHT;
this._dash.actor.set_position(0, dashY);
this._dash.actor.set_size(displayGridColumnWidth, screenHeight - dashY);
this._dash.searchArea.height = this._workspacesY - dashY;
this._dash.actor.set_position(0, contentY);
this._dash.actor.set_size(displayGridColumnWidth, contentHeight);
this._dash.searchArea.height = this._workspacesY - contentY;
this._dash.sectionArea.height = this._workspacesHeight;
// place the 'Add Workspace' button in the bottom row of the grid
this._addButtonSize = Math.floor(displayGridRowHeight * 3/5);
this._addButtonX = this._workspacesX + this._workspacesWidth - this._addButtonSize;
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
this._backOver.set_position(0, Panel.PANEL_HEIGHT);
this._backOver.set_position(0, contentY);
this._backOver.set_size(global.screen_width, contentHeight);
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
Panel.PANEL_HEIGHT);
contentY);
// Dynamic width
this._paneContainer.height = contentHeight;
@ -232,7 +238,7 @@ Overview.prototype = {
// This allows the user to place the item on any workspace.
handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem
|| source instanceof AppDisplay.WellDisplayItem) {
|| source instanceof AppDisplay.BaseWellItem) {
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
return true;
@ -271,20 +277,16 @@ Overview.prototype = {
show : function() {
if (this.visible)
return;
if (!Main.beginModal())
return;
Main.pushModal(this._dash.actor);
this.visible = true;
this.animationInProgress = true;
let global = Shell.Global.get();
this._dash.show();
/* TODO: make this stuff dynamic */
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
this._workspacesX, this._workspacesY,
this._addButtonSize, this._addButtonX, this._addButtonY);
this._workspacesX, this._workspacesY);
this._group.add_actor(this._workspaces.actor);
// The workspaces actor is as big as the screen, so we have to raise the dash above it
@ -292,6 +294,12 @@ Overview.prototype = {
// be as big as the screen.
this._dash.actor.raise(this._workspaces.actor);
// Create (+) button
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
this._group.add_actor(this._addButton.actor);
this._addButton.actor.raise(this._workspaces.actor);
// All the the actors in the window group are completely obscured,
// hiding the group holding them while the Overview is displayed greatly
// increases performance of the Overview especially when there are many
@ -327,15 +335,14 @@ Overview.prototype = {
time: ANIMATION_TIME
});
this._coverPane.raise_top();
this.emit('showing');
},
hide : function() {
hide: function() {
if (!this.visible || this._hideInProgress)
return;
let global = Shell.Global.get();
this.animationInProgress = true;
this._hideInProgress = true;
if (this._activeDisplayPane != null)
@ -365,6 +372,7 @@ Overview.prototype = {
time: ANIMATION_TIME
});
this._coverPane.raise_top();
this.emit('hiding');
},
@ -375,6 +383,18 @@ Overview.prototype = {
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;
},
/**
* activateWindow:
* @metaWindow: A #MetaWindow
@ -387,7 +407,6 @@ Overview.prototype = {
*/
activateWindow: function (metaWindow, time) {
this._workspaces.activateWindowFromOverview(metaWindow, time);
this.hide();
},
//// Private methods ////
@ -397,13 +416,12 @@ Overview.prototype = {
return;
this.animationInProgress = false;
this._coverPane.lower_bottom();
this.emit('shown');
},
_hideDone: function() {
let global = Shell.Global.get();
global.window_group.show();
this._workspaces.destroy();
@ -416,8 +434,47 @@ Overview.prototype = {
this.animationInProgress = false;
this._hideInProgress = false;
Main.endModal();
this._coverPane.lower_bottom();
Main.popModal(this._dash.actor);
this.emit('hidden');
},
_addNewWorkspace: function() {
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
},
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
this._addNewWorkspace();
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
}
};
Signals.addSignalMethods(Overview.prototype);
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
}
AddWorkspaceButton.prototype = {
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
this.actor = new Clutter.Group({ x: buttonX,
y: buttonY,
width: global.screen_width - buttonX,
height: global.screen_height - buttonY,
reactive: true });
this.actor._delegate = this;
this._acceptDropCallback = acceptDropCallback;
let plus = new Clutter.Texture({ x: 0,
y: 0,
width: buttonSize,
height: buttonSize });
plus.set_from_file(global.imagedir + 'add-workspace.svg');
this.actor.add_actor(plus);
},
// Draggable target interface
acceptDrop: function(source, actor, x, y, time) {
return this._acceptDropCallback(source, actor, x, y, time);
}
};

View File

@ -66,7 +66,7 @@ function AppPanelMenu() {
AppPanelMenu.prototype = {
_init: function() {
this._metaDisplay = Shell.Global.get().screen.get_display();
this._metaDisplay = global.screen.get_display();
this._focusedApp = null;
this._activeSequence = null;
@ -168,8 +168,6 @@ function Panel() {
Panel.prototype = {
_init : function() {
let global = Shell.Global.get();
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
});
@ -269,10 +267,10 @@ Panel.prototype = {
/* left side */
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR, true, DEFAULT_FONT);
this.button.button.height = PANEL_HEIGHT;
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
this.button.actor.height = PANEL_HEIGHT;
this._leftBox.append(this.button.button, Big.BoxPackFlags.NONE);
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
// We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding
@ -374,43 +372,46 @@ Panel.prototype = {
let statusbutton = new Button.Button(statusbox,
PANEL_BUTTON_COLOR,
PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR,
true);
statusbutton.button.height = PANEL_HEIGHT;
statusbutton.button.connect('button-press-event', function (b, e) {
statusmenu.toggle(e);
return false;
PANEL_FOREGROUND_COLOR);
statusbutton.actor.height = PANEL_HEIGHT;
statusbutton.actor.connect('button-press-event', function (b, e) {
if (e.get_button() == 1 && e.get_click_count() == 1) {
statusmenu.toggle(e);
// The statusmenu might not pop up if it couldn't get a pointer grab
if (statusmenu.is_active())
statusbutton.actor.active = true;
return true;
} else {
return false;
}
});
// If popping up the menu failed (because there was already a grab in
// effect from Mutter or another app), then we'll never get a ::deactivated
// signal because the menu was never activated, so we need to unhighlight
// separately when the user releases the mouse button.
//
// We depend on connection ordering; this needs to be called after Button's
// ::button-release-event handler; that will set the active flag for this
// stays-pressed button, then we unset the active flag by calling release().
statusbutton.button.connect('button-release-event', function (b, e) {
if (!statusmenu.is_active())
statusbutton.release();
return false;
});
this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
// We get a deactivated event when the popup disappears
this._statusmenu.connect('deactivated', function (sm) {
statusbutton.release();
statusbutton.actor.active = false;
});
// TODO: decide what to do with the rest of the panel in the Overview mode (make it fade-out, become non-reactive, etc.)
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
// to switch to.
this.button.button.connect('button-press-event',
Lang.bind(Main.overview, Main.overview.toggle));
this.button.actor.connect('button-press-event', function(b, e) {
if (e.get_button() == 1 && e.get_click_count() == 1) {
Main.overview.toggle();
return true;
} else {
return false;
}
});
// In addition to pressing the button, the Overview can be entered and exited by other means, such as
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
// and to be released when it is exited regardless of how it was triggered.
Main.overview.connect('showing', Lang.bind(this.button, this.button.pressIn));
Main.overview.connect('hiding', Lang.bind(this.button, this.button.release));
Main.overview.connect('showing', Lang.bind(this, function() {
this.button.actor.active = true;
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
this.button.actor.active = false;
}));
Main.chrome.addActor(this.actor);
Main.chrome.setVisibleInOverview(this.actor, true);
@ -471,14 +472,14 @@ Panel.prototype = {
},
_onHotCornerLeft : function(actor, event) {
if (Shell.get_event_related(event) != this._hotCornerEnvirons) {
if (event.get_related() != this._hotCornerEnvirons) {
this._hotCornerEntered = false;
}
return false;
},
_onHotCornerEnvironsLeft : function(actor, event) {
if (Shell.get_event_related(event) != this._hotCorner) {
if (event.get_related() != this._hotCorner) {
this._hotCornerEntered = false;
}
return false;

View File

@ -80,6 +80,9 @@ Places.prototype = {
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
@ -98,6 +101,23 @@ Places.prototype = {
this._menuBox.append(home.actor, Big.BoxPackFlags.NONE);
/*
* Show devices, code more or less ported from nautilus-places-sidebar.c
*/
this._menuBox.append(this._devBox, Big.BoxPackFlags.NONE);
this._volumeMonitor = Gio.VolumeMonitor.get();
this._volumeMonitor.connect('volume-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-removed',Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('volume-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-added', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-removed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('mount-changed', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-connected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-disconnected', Lang.bind(this, this._updateDevices));
this._volumeMonitor.connect('drive-changed', Lang.bind(this, this._updateDevices));
this._updateDevices();
let networkApp = null;
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
@ -151,6 +171,9 @@ Places.prototype = {
this._dirsBox.remove_all();
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
return;
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
if (!success)
@ -194,6 +217,62 @@ Places.prototype = {
});
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
}
},
_updateDevices: function() {
this._devBox.remove_all();
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for(let j = 0; j < volumes.length; j++) {
let mount = volumes[j].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
}
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
continue;
let mount = volumes[i].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
continue;
if(mounts[i].get_volume())
continue;
this._addMount(mounts[i]);
}
},
_addMount: function(mount) {
let mountLabel = mount.get_name();
let mountIcon = mount.get_icon();
let root = mount.get_root();
let mountUri = root.get_uri();
let devItem = new PlaceDisplay(mountLabel,
function() {
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
});
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
}
};
Signals.addSignalMethods(Places.prototype);

View File

@ -5,6 +5,7 @@ const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
@ -21,8 +22,10 @@ BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
const BOX_TEXT_COLOR = new Clutter.Color();
BOX_TEXT_COLOR.from_pixel(0xffffffff);
const BOX_WIDTH = 320;
const BOX_HEIGHT = 56;
const DIALOG_WIDTH = 320;
const DIALOG_PADDING = 6;
const ICON_SIZE = 24;
const ICON_BOX_SIZE = 36;
function RunDialog() {
this._init();
@ -30,25 +33,31 @@ function RunDialog() {
RunDialog.prototype = {
_init : function() {
let global = Shell.Global.get();
this._isOpen = false;
let gconf = Shell.GConf.get_default();
gconf.connect('changed', Lang.bind(this, function (gconf, key) {
if (key == 'development_tools')
this._enableInternalCommands = gconf.get_bool('development_tools');
}));
this._enableInternalCommands = gconf.get_boolean('development_tools');
this._internalCommands = { 'lg':
Lang.bind(this, function() {
// Run in an idle to avoid recursive key grab problems
Mainloop.idle_add(function() { Main.createLookingGlass().open(); });
Main.createLookingGlass().open();
}),
'r': Lang.bind(this, function() {
let global = Shell.Global.get();
global.reexec_self();
}),
// Developer brain backwards compatibility
'restart': Lang.bind(this, function() {
let global = Shell.Global.get();
global.reexec_self();
}),
'debugexit': Lang.bind(this, function() {
Meta.exit(Meta.ExitCode.ERROR);
})
};
@ -64,45 +73,77 @@ RunDialog.prototype = {
reactive: true });
this._group.add_actor(this._overlay);
let boxGroup = new Clutter.Group();
boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
(global.screen_height - BOX_HEIGHT) / 2);
this._group.add_actor(boxGroup);
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
width: global.screen_width,
height: global.screen_height });
let box = new Big.Box({ background_color: BOX_BACKGROUND_COLOR,
corner_radius: 4,
reactive: false,
width: BOX_WIDTH,
height: BOX_HEIGHT
});
boxGroup.add_actor(box);
this._group.add_actor(boxH);
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
boxH.append(boxV, Big.BoxPackFlags.NONE);
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
background_color: BOX_BACKGROUND_COLOR,
corner_radius: 4,
reactive: false,
padding: DIALOG_PADDING,
width: DIALOG_WIDTH });
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans',
text: _("Please enter a command:") });
label.set_position(6, 6);
boxGroup.add_actor(label);
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '20px Sans Bold',
editable: true,
activatable: true,
singleLineMode: true,
text: '',
width: BOX_WIDTH - 12,
height: BOX_HEIGHT - 12 });
// TODO: Implement relative positioning using Tidy.
this._entry.set_position(6, 30);
boxGroup.add_actor(this._entry);
singleLineMode: true });
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
this._errorBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: DIALOG_PADDING });
dialogBox.append(this._errorBox, Big.BoxPackFlags.EXPAND);
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER,
x_align: Big.BoxAlignment.CENTER,
width: ICON_BOX_SIZE,
height: ICON_BOX_SIZE });
this._errorBox.append(iconBox, Big.BoxPackFlags.NONE);
this._commandError = false;
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
this._errorMessage = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans Bold',
line_wrap: true });
this._errorBox.append(this._errorMessage, Big.BoxPackFlags.EXPAND);
this._errorBox.hide();
this._entry.connect('activate', Lang.bind(this, function (o, e) {
this._run(o.get_text());
this.close();
return false;
if (!this._commandError)
this.close();
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = Shell.get_event_key_symbol(e);
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
@ -112,17 +153,31 @@ RunDialog.prototype = {
},
_run : function(command) {
let f = this._internalCommands[command];
let f;
if (this._enableInternalCommands)
f = this._internalCommands[command];
else
f = null;
if (f) {
f();
} else if (command) {
try {
this._commandError = false;
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
p.run();
} catch (e) {
// TODO: Give the user direct feedback.
log('Could not run command ' + command + ': ' + e);
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 '" + command + "' failed:\n" + m[1];
this._errorMessage.set_text(errorStr);
this._errorBox.show();
}
}
},
@ -131,13 +186,10 @@ RunDialog.prototype = {
if (this._isOpen) // Already shown
return;
if (!Main.beginModal())
return;
this._isOpen = true;
this._group.show();
let global = Shell.Global.get();
Main.pushModal(this._group);
global.stage.set_key_focus(this._entry);
},
@ -147,10 +199,13 @@ RunDialog.prototype = {
this._isOpen = false;
this._errorBox.hide();
this._commandError = false;
this._group.hide();
this._entry.text = '';
Main.endModal();
Main.popModal(this._group);
}
};
Signals.addSignalMethods(RunDialog.prototype);

View File

@ -21,21 +21,12 @@ const SIDEBAR_PADDING = 4;
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
// The maximum height of the sidebar would be extending from just
// below the panel to just above the taskbar. Since the taskbar is
// just a temporary hack and it would be too hard to do this the right
// way, we just hardcode its size.
const HARDCODED_TASKBAR_HEIGHT = 24;
const MAXIMUM_SIDEBAR_HEIGHT = Shell.Global.get().screen_height - Panel.PANEL_HEIGHT - HARDCODED_TASKBAR_HEIGHT;
function Sidebar() {
this._init();
}
Sidebar.prototype = {
_init : function() {
let global = Shell.Global.get();
// The top-left corner of the sidebar is fixed at:
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
// (The negative X is so that we don't see the rounded

View File

@ -1,6 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
@ -41,9 +42,17 @@ const Tweener = imports.tweener.tweener;
// calls any of these is almost certainly wrong anyway, because they
// affect the entire application.)
let slowDownFactor = 1.0;
// Called from Main.start
function init() {
let slowdownEnv = GLib.getenv("GNOME_SHELL_SLOWDOWN_FACTOR");
if (slowdownEnv) {
let factor = parseFloat(slowdownEnv);
if (!isNaN(factor) && factor > 0.0)
slowDownFactor = factor;
}
Tweener.setFrameTicker(new ClutterFrameTicker());
}
@ -208,11 +217,10 @@ ClutterFrameTicker.prototype = {
this._startTime = -1;
this._currentTime = -1;
let me = this;
this._timeline.connect('new-frame',
this._timeline.connect('new-frame', Lang.bind(this,
function(timeline, frame) {
me._onNewFrame(frame);
});
this._onNewFrame(frame);
}));
},
_onNewFrame : function(frame) {
@ -225,7 +233,7 @@ ClutterFrameTicker.prototype = {
this._startTime = this._timeline.get_elapsed_time();
// currentTime is in milliseconds
this._currentTime = this._timeline.get_elapsed_time() - this._startTime;
this._currentTime = (this._timeline.get_elapsed_time() - this._startTime) / slowDownFactor;
this.emit('prepare-frame');
},

View File

@ -163,7 +163,6 @@ ClockWidget.prototype = {
},
_updateCairo: function(time) {
let global = Shell.Global.get();
Shell.draw_clock(this.collapsedActor,
time.getHours() % 12,
time.getMinutes());

View File

@ -296,7 +296,7 @@ WidgetBox.prototype = {
this.state == Widget.STATE_POPPING_OUT)) {
// If moving into another actor within this._hbox, let the
// event be propagated
let into = Shell.get_event_related(event);
let into = event.get_related();
while (into) {
if (into == this._hbox)
return false;

View File

@ -1,9 +1,9 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const AltTab = imports.ui.altTab;
const Main = imports.ui.main;
@ -17,10 +17,8 @@ function WindowManager() {
WindowManager.prototype = {
_init : function() {
let me = this;
let shellwm = global.window_manager;
this._global = Shell.Global.get();
this._shellwm = this._global.window_manager;
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
@ -28,60 +26,20 @@ WindowManager.prototype = {
this._destroying = [];
this._switchData = null;
this._shellwm.connect('switch-workspace',
function(o, from, to, direction) {
let actors = me._shellwm.get_switch_workspace_actors();
me._switchWorkspace(actors, from, to, direction);
});
this._shellwm.connect('kill-switch-workspace',
function(o) {
me._switchWorkspaceDone();
});
this._shellwm.connect('minimize',
function(o, actor) {
me._minimizeWindow(actor);
});
this._shellwm.connect('kill-minimize',
function(o, actor) {
me._minimizeWindowDone(actor);
});
this._shellwm.connect('maximize',
function(o, actor, tx, ty, tw, th) {
me._maximizeWindow(actor, tx, ty, tw, th);
});
this._shellwm.connect('kill-maximize',
function(o, actor) {
me._maximizeWindowDone(actor);
});
this._shellwm.connect('unmaximize',
function(o, actor, tx, ty, tw, th) {
me._unmaximizeWindow(actor, tx, ty, tw, th);
});
this._shellwm.connect('kill-unmaximize',
function(o, actor) {
me._unmaximizeWindowDone(actor);
});
this._shellwm.connect('map',
function(o, actor) {
me._mapWindow(actor);
});
this._shellwm.connect('kill-map',
function(o, actor) {
me._mapWindowDone(actor);
});
this._shellwm.connect('destroy',
function(o, actor) {
me._destroyWindow(actor);
});
this._shellwm.connect('kill-destroy',
function(o, actor) {
me._destroyWindowDone(actor);
});
shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
shellwm.connect('kill-minimize', Lang.bind(this, this._minimizeWindowDone));
shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
shellwm.connect('kill-maximize', Lang.bind(this, this._maximizeWindowDone));
shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
shellwm.connect('kill-unmaximize', Lang.bind(this, this._unmaximizeWindowDone));
shellwm.connect('map', Lang.bind(this, this._mapWindow));
shellwm.connect('kill-map', Lang.bind(this, this._mapWindowDone));
shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
shellwm.connect('kill-destroy', Lang.bind(this, this._destroyWindowDone));
this._shellwm.connect('begin-alt-tab',
function(o, handler) {
me._beginAltTab(handler);
});
shellwm.connect('begin-alt-tab', Lang.bind(this, this._beginAltTab));
},
_shouldAnimate : function(actor) {
@ -101,9 +59,9 @@ WindowManager.prototype = {
return false;
},
_minimizeWindow : function(actor) {
_minimizeWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) {
this._shellwm.completed_minimize(actor);
shellwm.completed_minimize(actor);
return;
}
@ -121,49 +79,49 @@ WindowManager.prototype = {
transition: "easeOutQuad",
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [actor],
onCompleteParams: [shellwm, actor],
onOverwrite: this._minimizeWindowOverwritten,
onOverwriteScope: this,
onOverwriteParams: [actor]
onOverwriteParams: [shellwm, actor]
});
},
_minimizeWindowDone : function(actor) {
_minimizeWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_minimize(actor);
shellwm.completed_minimize(actor);
}
},
_minimizeWindowOverwritten : function(actor) {
_minimizeWindowOverwritten : function(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
this._shellwm.completed_minimize(actor);
shellwm.completed_minimize(actor);
}
},
_maximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
this._shellwm.completed_maximize(actor);
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
shellwm.completed_maximize(actor);
},
_maximizeWindowDone : function(actor) {
_maximizeWindowDone : function(shellwm, actor) {
},
_maximizeWindowOverwrite : function(actor) {
_maximizeWindowOverwrite : function(shellwm, actor) {
},
_unmaximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
this._shellwm.completed_unmaximize(actor);
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
shellwm.completed_unmaximize(actor);
},
_unmaximizeWindowDone : function(actor) {
_unmaximizeWindowDone : function(shellwm, actor) {
},
_mapWindow : function(actor) {
_mapWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) {
this._shellwm.completed_map(actor);
shellwm.completed_map(actor);
return;
}
@ -180,31 +138,31 @@ WindowManager.prototype = {
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [actor],
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [actor]
onOverwriteParams: [shellwm, actor]
});
},
_mapWindowDone : function(actor) {
_mapWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_map(actor);
shellwm.completed_map(actor);
}
},
_mapWindowOverwrite : function(actor) {
_mapWindowOverwrite : function(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
this._shellwm.completed_map(actor);
shellwm.completed_map(actor);
}
},
_destroyWindow : function(actor) {
_destroyWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) {
this._shellwm.completed_destroy(actor);
shellwm.completed_destroy(actor);
return;
}
@ -219,33 +177,35 @@ WindowManager.prototype = {
transition: "easeOutQuad",
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [actor],
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [actor]
onOverwriteParams: [shellwm, actor]
});
},
_destroyWindowDone : function(actor) {
_destroyWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
this._shellwm.completed_destroy(actor);
shellwm.completed_destroy(actor);
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
}
},
_destroyWindowOverwrite : function(actor) {
_destroyWindowOverwrite : function(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
this._shellwm.completed_destroy(actor);
shellwm.completed_destroy(actor);
}
},
_switchWorkspace : function(windows, from, to, direction) {
_switchWorkspace : function(shellwm, from, to, direction) {
if (!this._shouldAnimate()) {
this._shellwm.completed_switch_workspace();
shellwm.completed_switch_workspace();
return;
}
let windows = shellwm.get_switch_workspace_actors();
/* @direction is the direction that the "camera" moves, so the
* screen contents have to move one screen's worth in the
* opposite direction.
@ -255,20 +215,20 @@ WindowManager.prototype = {
if (direction == Meta.MotionDirection.UP ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.UP_RIGHT)
yDest = this._global.screen_height;
yDest = global.screen_height;
else if (direction == Meta.MotionDirection.DOWN ||
direction == Meta.MotionDirection.DOWN_LEFT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
yDest = -this._global.screen_height;
yDest = -global.screen_height;
if (direction == Meta.MotionDirection.LEFT ||
direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.DOWN_LEFT)
xDest = this._global.screen_width;
xDest = global.screen_width;
else if (direction == Meta.MotionDirection.RIGHT ||
direction == Meta.MotionDirection.UP_RIGHT ||
direction == Meta.MotionDirection.DOWN_RIGHT)
xDest = -this._global.screen_width;
xDest = -global.screen_width;
let switchData = {};
this._switchData = switchData;
@ -276,7 +236,7 @@ WindowManager.prototype = {
switchData.outGroup = new Clutter.Group();
switchData.windows = [];
let wgroup = this._global.window_group;
let wgroup = global.window_group;
wgroup.add_actor(switchData.inGroup);
wgroup.add_actor(switchData.outGroup);
@ -307,7 +267,8 @@ WindowManager.prototype = {
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._switchWorkspaceDone,
onCompleteScope: this
onCompleteScope: this,
onCompleteParams: [shellwm]
});
Tweener.addTween(switchData.inGroup,
{ x: 0,
@ -317,7 +278,7 @@ WindowManager.prototype = {
});
},
_switchWorkspaceDone : function() {
_switchWorkspaceDone : function(shellwm) {
let switchData = this._switchData;
if (!switchData)
return;
@ -336,10 +297,10 @@ WindowManager.prototype = {
switchData.inGroup.destroy();
switchData.outGroup.destroy();
this._shellwm.completed_switch_workspace();
shellwm.completed_switch_workspace();
},
_beginAltTab : function(handler) {
_beginAltTab : function(shellwm, handler) {
let popup = new AltTab.AltTabPopup();
handler.connect('window-added', function(handler, window) { popup.addWindow(window); });

View File

@ -25,6 +25,12 @@ const WINDOWCLONE_TITLE_COLOR = new Clutter.Color();
WINDOWCLONE_TITLE_COLOR.from_pixel(0xffffffff);
const FRAME_COLOR = new Clutter.Color();
FRAME_COLOR.from_pixel(0xffffffff);
const LIGHTBOX_COLOR = new Clutter.Color();
LIGHTBOX_COLOR.from_pixel(0x00000044);
const SCROLL_SCALE_AMOUNT = 100 / 5;
const ZOOM_OVERLAY_FADE_TIME = 0.15;
// Define a layout scheme for small window counts. For larger
// counts we fall back to an algorithm. We need more schemes here
@ -40,13 +46,53 @@ const POSITIONS = {
5: [[0.165, 0.25, 0.32], [0.495, 0.25, 0.32], [0.825, 0.25, 0.32], [0.25, 0.75, 0.32], [0.75, 0.75, 0.32]]
};
function _interpolate(start, end, step) {
return start + (end - start) * step;
}
function _clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}
// Spacing between workspaces. At the moment, the same spacing is used
// in both zoomed-in and zoomed-out views; this is slightly
// metaphor-breaking, but the alternatives are also weird.
const GRID_SPACING = 15;
const FRAME_SIZE = GRID_SPACING / 3;
let buttonSize = false;
function ScaledPoint(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
}
ScaledPoint.prototype = {
getPosition : function() {
return [this.x, this.y];
},
getScale : function() {
return [this.scaleX, this.scaleY];
},
setPosition : function(x, y) {
[this.x, this.y] = arguments;
},
setScale : function(scaleX, scaleY) {
[this.scaleX, this.scaleY] = arguments;
},
interpPosition : function(other, step) {
return [_interpolate(this.x, other.x, step),
_interpolate(this.y, other.y, step)];
},
interpScale : function(other, step) {
return [_interpolate(this.scaleX, other.scaleX, step),
_interpolate(this.scaleY, other.scaleY, step)];
}
};
function WindowClone(realWindow) {
this._init(realWindow);
@ -61,12 +107,18 @@ WindowClone.prototype = {
this.actor._delegate = this;
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
this.metaWindow._delegate = this;
this.origX = realWindow.x;
this.origY = realWindow.y;
this._title = null;
this.actor.connect('button-release-event',
Lang.bind(this, this._onButtonRelease));
this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll));
this.actor.connect('enter-event',
Lang.bind(this, this._onEnter));
this.actor.connect('leave-event',
@ -79,6 +131,18 @@ WindowClone.prototype = {
this._inDrag = false;
},
setVisibleWithChrome: function(visible) {
if (visible) {
this.actor.show();
if (this._title)
this._title.show();
} else {
this.actor.hide();
if (this._title)
this._title.hide();
}
},
destroy: function () {
this.actor.destroy();
if (this._title)
@ -104,12 +168,103 @@ WindowClone.prototype = {
return;
this._havePointer = false;
if (Tweener.isTweening(this.actor))
return;
actor.raise(this.stackAbove);
this._updateTitle();
if (this._zoomStep)
this._zoomEnd();
},
_onScroll : function (actor, event) {
let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.UP) {
if (this._zoomStep == undefined)
this._zoomStart();
if (this._zoomStep < 100) {
this._zoomStep += SCROLL_SCALE_AMOUNT;
this._zoomUpdate();
}
} else if (direction == Clutter.ScrollDirection.DOWN) {
if (this._zoomStep > 0) {
this._zoomStep -= SCROLL_SCALE_AMOUNT;
this._zoomStep = Math.max(0, this._zoomStep);
this._zoomUpdate();
}
if (this._zoomStep <= 0.0)
this._zoomEnd();
}
},
_zoomUpdate : function () {
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.interpPosition(this._zoomTarget, this._zoomStep / 100);
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.interpScale(this._zoomTarget, this._zoomStep / 100);
let [width, height] = this.actor.get_transformed_size();
this.actor.x = _clamp(this.actor.x, 0, global.screen_width - width);
this.actor.y = _clamp(this.actor.y, Panel.PANEL_HEIGHT, global.screen_height - height);
},
_zoomStart : function () {
this._zoomOverlay = new Clutter.Rectangle({ reactive: true,
color: LIGHTBOX_COLOR,
border_width: 0,
x: 0,
y: 0,
width: global.screen_width,
height: global.screen_height,
opacity: 0 });
this._zoomOverlay.show();
global.stage.add_actor(this._zoomOverlay);
Tweener.addTween(this._zoomOverlay,
{ opacity: 255,
time: ZOOM_OVERLAY_FADE_TIME,
transition: "easeOutQuad"
});
this._zoomLocalOrig = new ScaledPoint(this.actor.x, this.actor.y, this.actor.scale_x, this.actor.scale_y);
this._zoomGlobalOrig = new ScaledPoint();
let parent = this._origParent = this.actor.get_parent();
[width, height] = this.actor.get_transformed_size();
this._zoomGlobalOrig.setPosition.apply(this._zoomGlobalOrig, this.actor.get_transformed_position());
this._zoomGlobalOrig.setScale(width / this.actor.width, height / this.actor.height);
this._zoomOverlay.raise_top();
this._zoomOverlay.show();
this.actor.reparent(global.stage);
[this.actor.x, this.actor.y] = this._zoomGlobalOrig.getPosition();
[this.actor.scale_x, this.actor.scale_y] = this._zoomGlobalOrig.getScale();
this.actor.raise_top();
this._zoomTarget = new ScaledPoint(0, 0, 1.0, 1.0);
this._zoomTarget.setPosition(this.actor.x - (this.actor.width - width) / 2, this.actor.y - (this.actor.height - height) / 2);
this._zoomStep = 0;
this._hideEventId = Main.overview.connect('hiding', Lang.bind(this, function () { this._zoomEnd(); }));
this._zoomUpdate();
},
_zoomEnd : function () {
this.actor.reparent(this._origParent);
[this.actor.x, this.actor.y] = this._zoomLocalOrig.getPosition();
[this.actor.scale_x, this.actor.scale_y] = this._zoomLocalOrig.getScale();
this._adjustTitle();
this._zoomOverlay.destroy();
Main.overview.disconnect(this._hideEventId);
this._zoomLocalPosition = undefined;
this._zoomLocalScale = undefined;
this._zoomGlobalPosition = undefined;
this._zoomGlobalScale = undefined;
this._zoomTargetPosition = undefined;
this._zoomStep = undefined;
this._zoomOverlay = undefined;
},
_onButtonRelease : function (actor, event) {
@ -231,7 +386,6 @@ DesktopClone.prototype = {
this.actor = new Clutter.Clone({ source: window.get_texture(),
reactive: true });
} else {
let global = Shell.Global.get();
this.actor = new Clutter.Rectangle({ color: global.stage.color,
reactive: true,
width: global.screen_width,
@ -262,9 +416,6 @@ function Workspace(workspaceNum, parentActor) {
Workspace.prototype = {
_init : function(workspaceNum, parentActor) {
let me = this;
let global = Shell.Global.get();
this.workspaceNum = workspaceNum;
this._metaWorkspace = global.screen.get_workspace_by_index(workspaceNum);
@ -280,6 +431,14 @@ Workspace.prototype = {
this.actor.height = global.screen_height;
this.scale = 1.0;
this._lightbox = new Clutter.Rectangle({ color: LIGHTBOX_COLOR });
this.actor.connect('notify::allocation', Lang.bind(this, function () {
let [width, height] = this.actor.get_size();
this._lightbox.set_size(width, height);
}));
this.actor.add_actor(this._lightbox);
this._lightbox.hide();
let windows = global.get_windows().filter(this._isMyWindow, this);
// Find the desktop window
@ -311,6 +470,9 @@ Workspace.prototype = {
}
}
// A filter for what windows we display
this._showOnlyWindows = null;
// Track window changes
this._windowAddedId = this._metaWorkspace.connect('window-added',
Lang.bind(this, this._windowAdded));
@ -326,7 +488,6 @@ Workspace.prototype = {
},
updateRemovable : function() {
let global = Shell.Global.get();
let removable = (this._windows.length == 1 /* just desktop */ &&
this.workspaceNum != 0 &&
this.workspaceNum == global.screen.n_workspaces - 1);
@ -335,8 +496,8 @@ Workspace.prototype = {
if (this._removeButton)
return;
this._removeButton = new Clutter.Texture({ width: buttonSize,
height: buttonSize,
this._removeButton = new Clutter.Texture({ width: Overview.addRemoveButtonSize,
height: Overview.addRemoveButtonSize,
reactive: true
});
this._removeButton.set_from_file(global.imagedir + "remove-workspace.svg");
@ -381,11 +542,60 @@ Workspace.prototype = {
return -1;
},
/**
* lookupCloneForMetaWindow:
* @metaWindow: A #MetaWindow
*
* Given a #MetaWindow instance, find the WindowClone object
* which represents it in the workspaces display.
*/
lookupCloneForMetaWindow: function (metaWindow) {
let index = this._lookupIndex (metaWindow);
return index < 0 ? null : this._windows[index];
},
containsMetaWindow: function (metaWindow) {
return this._lookupIndex(metaWindow) >= 0;
},
setShowOnlyWindows: function(showOnlyWindows, reposition) {
this._showOnlyWindows = showOnlyWindows;
this._resetCloneVisibility();
if (reposition)
this.positionWindows(false);
},
/**
* setLightboxMode:
* @showLightbox: If true, dim background and allow highlighting a specific window
*
* This function also resets the highlighted window state.
*/
setLightboxMode: function (showLightbox) {
if (showLightbox) {
this.setHighlightWindow(null);
this._lightbox.show();
} else {
this._lightbox.hide();
}
},
/**
* setHighlightWindow:
* @metaWindow: A #MetaWindow
*
* Draw the user's attention to the given window @metaWindow.
*/
setHighlightWindow: function (metaWindow) {
for (let i = 0; i < this._windows.length; i++) {
this._windows[i].actor.lower(this._lightbox);
}
if (metaWindow != null) {
let clone = this.lookupCloneForMetaWindow(metaWindow);
clone.actor.raise(this._lightbox);
}
},
_adjustRemoveButton : function() {
this._removeButton.set_scale(1.0 / this.actor.scale_x,
1.0 / this.actor.scale_y);
@ -402,7 +612,6 @@ Workspace.prototype = {
// Mark the workspace selected/not-selected
setSelected : function(selected) {
let global = Shell.Global.get();
// Don't draw a frame if we only have one workspace
if (selected && global.screen.n_workspaces > 1) {
if (this._frame)
@ -434,18 +643,51 @@ Workspace.prototype = {
this._desktop.actor.height + 2 * FRAME_SIZE / this.actor.scale_y);
},
// Reposition all windows in their zoomed-to-Overview position. if workspaceZooming
// is true, then the workspace is moving at the same time and we need to take
// that into account
positionWindows : function(workspaceZooming) {
let global = Shell.Global.get();
_resetCloneVisibility: function () {
for (let i = 1; i < this._windows.length; i++) {
let clone = this._windows[i];
let icon = this._windowIcons[i];
clone.stackAbove = this._windows[i - 1].actor;
let [xCenter, yCenter, fraction] = this._computeWindowPosition(i);
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows)) {
clone.setVisibleWithChrome(false);
icon.hide();
} else {
clone.setVisibleWithChrome(true);
}
}
},
/**
* positionWindows:
* @workspaceZooming: If true, then the workspace is moving at the same time and we need to take that into account.
*/
positionWindows : function(workspaceZooming) {
let totalVisible = 0;
for (let i = 1; i < this._windows.length; i++) {
let clone = this._windows[i];
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
continue;
totalVisible += 1;
}
let previousWindow = this._windows[0];
let visibleIndex = 0;
for (let i = 1; i < this._windows.length; i++) {
let clone = this._windows[i];
let icon = this._windowIcons[i];
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
continue;
clone.stackAbove = previousWindow.actor;
previousWindow = clone;
visibleIndex += 1;
let [xCenter, yCenter, fraction] = this._computeWindowPosition(visibleIndex, totalVisible);
xCenter = xCenter * global.screen_width;
yCenter = yCenter * global.screen_height;
@ -508,6 +750,8 @@ Workspace.prototype = {
for (let i = 1; i < this._windows.length; i++) {
let clone = this._windows[i];
let icon = this._windowIcons[i];
if (this._showOnlyWindows != null && !(clone.metaWindow in this._showOnlyWindows))
continue;
this._fadeInWindowIcon(clone, icon);
}
},
@ -520,7 +764,6 @@ Workspace.prototype = {
},
_windowRemoved : function(metaWorkspace, metaWin) {
let global = Shell.Global.get();
let win = metaWin.get_compositor_private();
// find the position of the window in our list
@ -672,8 +915,6 @@ Workspace.prototype = {
// Animates the addition of a new (empty) workspace
slideIn : function(oldScale) {
let global = Shell.Global.get();
if (this.gridCol > this.gridRow) {
this.actor.set_position(global.screen_width, this.gridY);
this.actor.set_scale(oldScale, oldScale);
@ -695,7 +936,6 @@ Workspace.prototype = {
// Animates the removal of a workspace
slideOut : function(onComplete) {
let global = Shell.Global.get();
let destX = this.actor.x, destY = this.actor.y;
this._hideAllIcons();
@ -722,8 +962,6 @@ Workspace.prototype = {
},
destroy : function() {
let global = Shell.Global.get();
Tweener.removeTweens(this.actor);
this.actor.destroy();
this.actor = null;
@ -745,11 +983,8 @@ Workspace.prototype = {
// Tests if @win should be shown in the Overview
_isOverviewWindow : function (win) {
let wintype = win.get_window_type();
if (wintype == Meta.WindowType.DESKTOP ||
wintype == Meta.WindowType.DOCK)
return false;
return !win.is_override_redirect();
let appMon = Shell.AppMonitor.get_default()
return appMon.is_window_usage_tracked(win.get_meta_window());
},
_createWindowIcon: function(window) {
@ -797,10 +1032,10 @@ Workspace.prototype = {
return clone;
},
_computeWindowPosition : function(index) {
_computeWindowPosition : function(index, totalWindows) {
// ignore this._windows[0], which is the desktop
let windowIndex = index - 1;
let numberOfWindows = this._windows.length - 1;
let numberOfWindows = totalWindows;
if (numberOfWindows in POSITIONS)
return POSITIONS[numberOfWindows][windowIndex];
@ -823,7 +1058,6 @@ Workspace.prototype = {
},
_removeSelf : function(actor, event) {
let global = Shell.Global.get();
let screen = global.screen;
let workspace = screen.get_workspace_by_index(this.workspaceNum);
@ -833,8 +1067,6 @@ Workspace.prototype = {
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
let global = Shell.Global.get();
if (source instanceof WindowClone) {
let win = source.realWindow;
if (this._isMyWindow(win))
@ -865,25 +1097,25 @@ Workspace.prototype = {
Signals.addSignalMethods(Workspace.prototype);
function Workspaces(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
this._init(width, height, x, y, addButtonSize, addButtonX, addButtonY);
function Workspaces(width, height, x, y) {
this._init(width, height, x, y);
}
Workspaces.prototype = {
_init : function(width, height, x, y, addButtonSize, addButtonX, addButtonY) {
let global = Shell.Global.get();
_init : function(width, height, x, y) {
this.actor = new Clutter.Group();
let screenHeight = global.screen_height;
this._width = width;
this._height = height;
this._x = x;
this._y = y;
this._windowSelectionAppId = null;
this._workspaces = [];
this._highlightWindow = null;
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspace;
@ -896,17 +1128,7 @@ Workspaces.prototype = {
}
}
activeWorkspace.actor.raise_top();
this._positionWorkspaces(global, activeWorkspace);
// Save the button size as a global variable so we can us it to create
// matching button sizes for workspace remove buttons.
buttonSize = addButtonSize;
// Create (+) button
this.addButton = new AddWorkspaceButton(addButtonSize, addButtonX, addButtonY, Lang.bind(this, this._addWorkspaceAcceptDrop));
this.addButton.actor.connect('button-release-event', Lang.bind(this, this._appendNewWorkspace));
this.actor.add_actor(this.addButton.actor);
this.addButton.actor.lower_bottom();
this._positionWorkspaces();
let lastWorkspace = this._workspaces[this._workspaces.length - 1];
lastWorkspace.updateRemovable(true);
@ -930,6 +1152,14 @@ Workspaces.prototype = {
Lang.bind(this, this._activeWorkspaceChanged));
},
_lookupWorkspaceForMetaWindow: function (metaWindow) {
for (let i = 0; i < this._workspaces.length; i++) {
if (this._workspaces[i].containsMetaWindow(metaWindow))
return this._workspaces[i];
}
return null;
},
_lookupCloneForMetaWindow: function (metaWindow) {
for (let i = 0; i < this._workspaces.length; i++) {
let clone = this._workspaces[i].lookupCloneForMetaWindow(metaWindow);
@ -939,9 +1169,64 @@ Workspaces.prototype = {
return null;
},
// Should only be called from active Overview context
activateWindowFromOverview: function (metaWindow, time) {
let global = Shell.Global.get();
setHighlightWindow: function (metaWindow) {
// Looping over all workspaces is easier than keeping track of the last
// highlighted window while trying to handle the window or workspace possibly
// going away.
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].setHighlightWindow(null);
}
if (metaWindow != null) {
let workspace = this._lookupWorkspaceForMetaWindow(metaWindow);
workspace.setHighlightWindow(metaWindow);
}
},
_clearApplicationWindowSelection: function(reposition) {
if (this._windowSelectionAppId == null)
return;
this._windowSelectionAppId = null;
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].setLightboxMode(false);
this._workspaces[i].setShowOnlyWindows(null, reposition);
}
},
/**
* setApplicationWindowSelection:
* @appid: Application identifier string
*
* Enter a mode which shows only the windows owned by the
* given application, and allow highlighting of a specific
* window with setHighlightWindow().
*/
setApplicationWindowSelection: function (appId) {
if (appId == null) {
this._clearApplicationWindowSelection(true);
return;
}
if (appId == this._windowSelectionAppId)
return;
this._windowSelectionAppId = appId;
let appSys = Shell.AppMonitor.get_default();
let showOnlyWindows = {};
let windows = appSys.get_windows_for_app(appId);
for (let i = 0; i < windows.length; i++) {
showOnlyWindows[windows[i]] = 1;
}
for (let i = 0; i < this._workspaces.length; i++) {
this._workspaces[i].setLightboxMode(true);
this._workspaces[i].setShowOnlyWindows(showOnlyWindows, true);
}
},
_activateWindowInternal: function (metaWindow, time) {
let activeWorkspaceNum = global.screen.get_active_workspace_index();
let windowWorkspaceNum = metaWindow.get_workspace().index();
@ -956,12 +1241,27 @@ Workspaces.prototype = {
}
},
/**
* activateWindowFromOverview:
* @metaWindow: A #MetaWindow
* @time: Integer even timestamp
*
* This function exits the overview, switching to the given @metaWindow.
* If an application filter is in effect, it will be cleared.
*/
activateWindowFromOverview: function (metaWindow, time) {
if (this._windowSelectionAppId != null) {
this._clearApplicationWindowSelection(false);
}
this._activateWindowInternal(metaWindow, time);
Main.overview.hide();
},
hide : function() {
let global = Shell.Global.get();
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
this._positionWorkspaces(global, activeWorkspace);
this._positionWorkspaces();
activeWorkspace.actor.raise_top();
for (let w = 0; w < this._workspaces.length; w++)
@ -969,8 +1269,6 @@ Workspaces.prototype = {
},
destroy : function() {
let global = Shell.Global.get();
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].destroy();
this._workspaces = [];
@ -988,7 +1286,6 @@ Workspaces.prototype = {
// Get the grid position of the active workspace.
getActiveWorkspacePosition : function() {
let global = Shell.Global.get();
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let activeWorkspace = this._workspaces[activeWorkspaceIndex];
@ -1005,12 +1302,7 @@ Workspaces.prototype = {
// first row.)
//
// FIXME: need to make the metacity internal layout agree with this!
_positionWorkspaces : function(global, activeWorkspace) {
if (!activeWorkspace) {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
activeWorkspace = this._workspaces[activeWorkspaceIndex];
}
_positionWorkspaces : function() {
let gridWidth = Math.ceil(Math.sqrt(this._workspaces.length));
let gridHeight = Math.ceil(this._workspaces.length / gridWidth);
@ -1048,8 +1340,6 @@ Workspaces.prototype = {
},
_workspacesChanged : function() {
let global = Shell.Global.get();
let oldNumWorkspaces = this._workspaces.length;
let newNumWorkspaces = global.screen.n_workspaces;
@ -1082,7 +1372,7 @@ Workspaces.prototype = {
newLastWorkspace.updateRemovable();
// Figure out the new layout
this._positionWorkspaces(global);
this._positionWorkspaces();
let newScale = this._workspaces[0].scale;
let newGridWidth = Math.ceil(Math.sqrt(newNumWorkspaces));
let newGridHeight = Math.ceil(newNumWorkspaces / newGridWidth);
@ -1133,42 +1423,13 @@ Workspaces.prototype = {
this.actor.add_actor(workspace.actor);
},
_appendNewWorkspace : function() {
let global = Shell.Global.get();
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
},
// Creates a new workspace and drops the dropActor there
_addWorkspaceAcceptDrop : function(source, dropActor, x, y, time) {
this._appendNewWorkspace();
// Handles a drop onto the (+) button; assumes the new workspace
// has already been added
acceptNewWorkspaceDrop : function(source, dropActor, x, y, time) {
return this._workspaces[this._workspaces.length - 1].acceptDrop(source, dropActor, x, y, time);
}
};
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
}
AddWorkspaceButton.prototype = {
_init : function(buttonSize, buttonX, buttonY, acceptDropCallback) {
this.actor = new Clutter.Texture({ x: buttonX,
y: buttonY,
width: buttonSize,
height: buttonSize,
reactive: true });
this._acceptDropCallback = acceptDropCallback;
let global = Shell.Global.get();
this.actor._delegate = this;
this.actor.set_from_file(global.imagedir + 'add-workspace.svg');
},
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
return this._acceptDropCallback(source, actor, x, y, time);
}
};
// Create a SpecialPropertyModifier to let us move windows in a
// straight line on the screen even though their containing workspace
// is also moving.

View File

@ -1,6 +1,8 @@
ca
cs
da
de
en_GB
es
fr
ga
@ -10,7 +12,9 @@ it
ko
nb
nl
pa
pl
pt_BR
sv
tr
zh_CN

108
po/ca.po
View File

@ -7,88 +7,99 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-14 20:38+0200\n"
"PO-Revision-Date: 2009-08-14 23:59+0100\n"
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
"Last-Translator: Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language-Team: \n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Gestió de finestres i execució d'aplicacions"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Activitats"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Cerca aplicacions o documents"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Cerca..."
#: ../js/ui/dash.js:336
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Navega"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(mostra tot)"
#. **** Applications ****
#: ../js/ui/dash.js:472
#: ../js/ui/dash.js:545
#: ../js/ui/dash.js:633
#: ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "APLICACIONS"
#. **** Documents ****
#: ../js/ui/dash.js:477
#: ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTS RECENTS"
#. **** Places ****
#: ../js/ui/dash.js:563
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "LLOCS"
#: ../js/ui/runDialog.js:74
#. **** Documents ****
#: ../js/ui/dash.js:660
#: ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTS RECENTS"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "RESULTATS DE LA CERCA"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Introduïu una ordre:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Gestor"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."
#: ../src/shell-global.c:841
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Fa menys d'un minut"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Fa %d minut"
msgstr[1] "Fa %d minuts"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Fa %d hora"
msgstr[1] "Fa %d hores"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Fa %d dia"
msgstr[1] "Fa %d dies"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -107,7 +118,7 @@ msgstr "No es pot blocar la pantalla: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "No es pot establir temporalment l'estalviador de pantalles a pantalla negra: %s"
msgstr "No es pot establir temporalment l'estalvi de pantalla a pantalla negra: %s"
#: ../src/shell-status-menu.c:351
#, c-format
@ -145,3 +156,34 @@ msgstr "Surt..."
msgid "Shut Down..."
msgstr "Atura..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Carpeta d'inici"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Sistema de fitxers"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Cerca"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Cerca aplicacions o documents"
#~ msgid "Manager"
#~ msgstr "Gestor"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "L'objecte gestor d'usuaris que controla a aquest usuari."

119
po/cs.po
View File

@ -1,15 +1,15 @@
# Czech translation of gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# Copyright (C) 2009 the author(s) of gnome-shell.
# This file is distributed under the same license as the gnome-shell package.
# Andre Klapper <ak-47@gmx.net>, 2009.
#
# Petr Kovar <pknbe@volny.cz>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-15 15:25+0200\n"
"PO-Revision-Date: 2009-08-15 13:23+0000\n"
"Last-Translator: Andre Klapper <ak-47@gmx.net>\n"
"POT-Creation-Date: 2009-08-30 17:37+0200\n"
"PO-Revision-Date: 2009-08-30 17:33+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -18,95 +18,95 @@ msgstr ""
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr ""
msgstr "Prostředí GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
#, fuzzy
msgid "Window management and application launching"
msgstr "Správa oken"
msgstr "Správa oken a spouštění aplikací"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr ""
msgstr "Činnosti"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr ""
msgstr "%a, %H:%M"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr ""
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Najít..."
#: ../js/ui/dash.js:336
#, fuzzy
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Procházet"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(zobrazit vše)"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "APLIKACE"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "NEDÁVNÉ DOKUMENTY"
#. **** Places ****
#: ../js/ui/dash.js:563
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "MÍSTA"
#: ../js/ui/runDialog.js:74
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "NEDÁVNÉ DOKUMENTY"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "VÝSLEDKY HLEDÁNÍ"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr ""
msgstr "Zadejte prosím příkaz:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Správce"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."
#: ../src/shell-global.c:841
#, fuzzy
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Dříve než před minutou"
msgstr "Před méně než minutou"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuta nazpět"
msgstr[1] "%d minuty nazpět"
msgstr[2] "%d minut nazpět"
msgstr[0] "Před %d minutou"
msgstr[1] "Před %d minutami"
msgstr[2] "Před %d minutami"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d hodina nazpět"
msgstr[1] "%d hodiny nazpět"
msgstr[2] "%d hodin nazpět"
msgstr[0] "Před %d hodinou"
msgstr[1] "Před %d hodinami"
msgstr[2] "Před %d hodinami"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d den nazpět"
msgstr[1] "%d dny nazpět"
msgstr[2] "%d dnů nazpět"
msgstr[0] "Před %d dnem"
msgstr[1] "Před %d dny"
msgstr[2] "Před %d dny"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d týden nazpět"
msgstr[1] "%d týdny nazpět"
msgstr[2] "%d týdnů nazpět"
msgstr[0] "Před %d týdnem"
msgstr[1] "Před %d týdny"
msgstr[2] "Před %d týdny"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
@ -132,9 +132,8 @@ msgid "Account Information..."
msgstr "Informace o účtu..."
#: ../src/shell-status-menu.c:502
#, fuzzy
msgid "Sidebar"
msgstr "Boční panel"
msgstr "Postranní lišta"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
@ -179,6 +178,12 @@ msgstr "Hledat"
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, fuzzy, c-format
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Manager"
#~ msgstr "Správce"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "Objekt správce uživatele, kterým je tento uživatel ovládán."

188
po/da.po Normal file
View File

@ -0,0 +1,188 @@
# Danish translation of gnome-shell
# Copyright (C) 2009 gnome-shell
# This file is distributed under the same license as the gnome-shell package.
# Kris Thomsen <lakristho@gmail.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-04 01:26+0200\n"
"PO-Revision-Date: 2009-09-01 21:48+0200\n"
"Last-Translator: Kris Thomsen <lakristho@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Skal til GNOME"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Vinduehåndtering og åbning af programmer"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Find..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Gennemse"
#: ../js/ui/dash.js:511
msgid "(see all)"
msgstr "(se alle)"
#. **** Applications ****
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:725
msgid "PLACES"
msgstr "STEDER"
#. **** Documents ****
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
msgid "RECENT DOCUMENTS"
msgstr "SENESTE DOKUMENTER"
#. **** Search Results ****
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
msgid "SEARCH RESULTS"
msgstr "SØGERESULTATER"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Indtast en kommando:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Mindre end et minut siden"
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minut siden"
msgstr[1] "%d minutter siden"
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d time siden"
msgstr[1] "%d timer siden"
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag siden"
msgstr[1] "%d dage siden"
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d uge siden"
msgstr[1] "%d uger siden"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Ukendt"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan ikke låse skærm: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan ikke midlertidigt sætte pauseskærm til blank skærm: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan ikke logge ud: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Kontoinformation..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidebjælke"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systemindstillinger..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lås skærm"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Skift bruger"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Log ud..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Luk ned..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Hjemmemappe"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Filsystem"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Søg"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Find programmer eller dokumenter"
#~ msgid "Manager"
#~ msgstr "Håndtering"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "Brugerhåndteringsobjektet, denne bruger er styret af."

184
po/en_GB.po Normal file
View File

@ -0,0 +1,184 @@
# British English translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Philip Withnall <philip@tecnocode.co.uk>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-12 12:41+0000\n"
"PO-Revision-Date: 2009-09-12 12:41+0000\n"
"Last-Translator: Philip Withnall <philip@tecnocode.co.uk>\n"
"Language-Team: British English <en_GB@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Window management and application launching"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Activities"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Find…"
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Browse"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(see all)"
#. **** Applications ****
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
msgid "APPLICATIONS"
msgstr "APPLICATIONS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:773
msgid "PLACES"
msgstr "PLACES"
#. **** Documents ****
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
msgid "RECENT DOCUMENTS"
msgstr "RECENT DOCUMENTS"
#. **** Search Results ****
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
msgid "SEARCH RESULTS"
msgstr "SEARCH RESULTS"
#: ../js/ui/dash.js:814
msgid "PREFERENCES"
msgstr "PREFERENCES"
#: ../js/ui/runDialog.js:90
msgid "Please enter a command:"
msgstr "Please enter a command:"
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Less than a minute ago"
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minute ago"
msgstr[1] "%d minutes ago"
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d hour ago"
msgstr[1] "%d hours ago"
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d day ago"
msgstr[1] "%d days ago"
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d week ago"
msgstr[1] "%d weeks ago"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Unknown"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Can't lock screen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Can't temporarily set screensaver to blank screen: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Can't logout: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Account Information…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidebar"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "System Preferences…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lock Screen"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Switch User"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Log Out…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Shut Down…"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Home Folder"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "File System"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Search"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

View File

@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-08-21 22:23+0000\n"
"PO-Revision-Date: 2009-08-22 12:21+0200\n"
"POT-Creation-Date: 2009-09-11 21:48+0000\n"
"PO-Revision-Date: 2009-09-12 14:40+0200\n"
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
"Language-Team: Español <gnome-es-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Transfer-Encoding: UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../data/gnome-shell.desktop.in.in.h:1
@ -26,80 +26,83 @@ msgid "Window management and application launching"
msgstr "Gestión de ventanas e inicio de aplicaciones"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Encuentre aplicaciones o documentos"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Buscar…"
#: ../js/ui/dash.js:368
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Examine"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(ver todo)"
#. **** Applications ****
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
#: ../js/ui/dash.js:736 ../js/ui/dash.js:792
msgid "APPLICATIONS"
msgstr "APLICACIONES"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:576
#: ../js/ui/dash.js:756
msgid "PLACES"
msgstr "LUGARES"
#. **** Documents ****
#: ../js/ui/dash.js:583
#: ../js/ui/dash.js:763 ../js/ui/dash.js:802
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECIENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:602
#: ../js/ui/dash.js:782 ../js/ui/dash.js:907
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DE LA BÚSQUEDA"
#: ../js/ui/dash.js:615
#| msgid "RECENT DOCUMENTS"
msgid "DOCUMENTS"
msgstr "DOCUMENTOS"
#: ../js/ui/dash.js:797
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/runDialog.js:75
#: ../js/ui/runDialog.js:90
msgid "Please enter a command:"
msgstr "Introduzca un comando:"
#: ../src/shell-global.c:841
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Hace menos de un minuto"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Hace %d minuto"
msgstr[1] "Hace %d minutos"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Hace %d hora"
msgstr[1] "Hace %d horas"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Hace %d día"
msgstr[1] "Hace %d días"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -182,6 +185,13 @@ msgstr "Buscar"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Encuentre aplicaciones o documentos"
#~| msgid "RECENT DOCUMENTS"
#~ msgid "DOCUMENTS"
#~ msgstr "DOCUMENTOS"
#~ msgid "Manager"
#~ msgstr "Gestor"

177
po/fr.po
View File

@ -1,21 +1,182 @@
# French translations for gnome-shell package.
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Colin Walters <walters@verbum.org>, 2009.
#
# Mathieu Bridon <bochecha@fedoraproject.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-07-27 15:09-0400\n"
"PO-Revision-Date: 2009-07-27 15:23-0400\n"
"Last-Translator: Colin Walters <walters@verbum.org>\n"
"Language-Team: French\n"
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-09 21:30+0000\n"
"PO-Revision-Date: 2009-09-11 21:40+0200\n"
"Last-Translator: Mathieu Bridon <bochecha@fedoraproject.org>\n"
"Language-Team: GNOME French Team\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: ../js/ui/panel.js:74
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Gestion des fenêtres et lancement des applications"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Activités"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:255
msgid "Find..."
msgstr "Rechercher..."
#: ../js/ui/dash.js:372
msgid "Browse"
msgstr "Parcourir"
#: ../js/ui/dash.js:508
msgid "(see all)"
msgstr "(tout afficher)"
#. **** Applications ****
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
msgid "APPLICATIONS"
msgstr "APPLICATIONS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:720
msgid "PLACES"
msgstr "RACCOURCIS"
#. **** Documents ****
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTS RÉCENTS"
#. **** Search Results ****
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
msgid "SEARCH RESULTS"
msgstr "RÉSULTATS DE LA RECHERCHE"
#: ../js/ui/runDialog.js:90
msgid "Please enter a command:"
msgstr "Veuillez saisir une commande :"
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Il y a moins d'une minute"
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Il y a %d minute"
msgstr[1] "Il y a %d minutes"
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Il y a %d heure"
msgstr[1] "Il y a %d heures"
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Il y a %d jour"
msgstr[1] "Il y a %d jours"
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Il y a %d semaine"
msgstr[1] "Il y a %d semaines"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Inconnu"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Impossible de verrouiller l'écran : %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Impossible de régler temporairement l'écran de veille sur un écran vide : %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Impossible de fermer la session : %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informations personnelles..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barre latérale"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Préférences du système..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Verrouiller l'écran"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Changer d'utilisateur"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Fermer la session..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Éteindre..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Dossier personnel"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Système de fichiers"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Recherche"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s : %2$s"

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-22 16:39+0200\n"
"PO-Revision-Date: 2009-08-18 21:20+0100\n"
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
"Language-Team: Galician <gnome@mancomun.org>\n"
"MIME-Version: 1.0\n"
@ -25,80 +25,83 @@ msgid "Window management and application launching"
msgstr "Xestor de xanelas e lanzado de aplicativos"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Atopar aplicativos ou documentos"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Buscar..."
#: ../js/ui/dash.js:368
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Explorar"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(ver todos)"
#. **** Applications ****
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:576
#: ../js/ui/dash.js:773
msgid "PLACES"
msgstr "LUGARES"
#. **** Documents ****
#: ../js/ui/dash.js:583
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:602
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DA BÚSQUEDA"
#: ../js/ui/dash.js:814
msgid "PREFERENCES"
msgstr ""
#: ../js/ui/dash.js:615
#, fuzzy
msgid "DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#: ../js/ui/runDialog.js:75
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Insira unha orde:"
#: ../src/shell-global.c:841
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Menos de un minuto"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "fai %d minuto"
msgstr[1] "fai %d minutos"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "fai %d hora"
msgstr[1] "fai %d horas"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "fai %d día"
msgstr[1] "fai %d días"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -180,5 +183,12 @@ msgstr "Buscar"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Atopar aplicativos ou documentos"
#, fuzzy
#~ msgid "DOCUMENTS"
#~ msgstr "DOCUMENTOS RECENTES"
#~ msgid "Manager"
#~ msgstr "Xestor"

View File

@ -6,9 +6,10 @@
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-20 23:25+0200\n"
"PO-Revision-Date: 2009-08-20 23:26+0200\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
"Language-Team: Italian <tp@lists.linux.it>\n"
"MIME-Version: 1.0\n"
@ -25,72 +26,80 @@ msgid "Window management and application launching"
msgstr "Gestione finestre e avvio applicazioni"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Attività"
# (ndt) proviamo col k, se non funge, sappiamo il perché...
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %k.%M"
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
#: ../js/ui/dash.js:251
msgid "Find apps or documents"
msgstr "Trova programmi e documenti"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Trova..."
#: ../js/ui/dash.js:369
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Esplora"
#: ../js/ui/dash.js:511
msgid "(see all)"
msgstr "(vedi tutto)"
#. **** Applications ****
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
msgid "APPLICATIONS"
msgstr "Applicazioni"
#. **** Documents ****
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
msgid "RECENT DOCUMENTS"
msgstr "Documenti recenti"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:598
#: ../js/ui/dash.js:725
msgid "PLACES"
msgstr "Risorse"
#: ../js/ui/runDialog.js:75
#. **** Documents ****
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
msgid "RECENT DOCUMENTS"
msgstr "Documenti recenti"
#. **** Search Results ****
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
msgid "SEARCH RESULTS"
msgstr "Risultati ricerca"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Inserire un comando:"
#: ../src/shell-global.c:841
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Meno di un minuto fa"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuto fa"
msgstr[1] "%d minuti fa"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ora fa"
msgstr[1] "%d ore fa"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d giorno fa"
msgstr[1] "%d giorni fa"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -175,6 +184,10 @@ msgstr "Cerca"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
# (ndt) è da valutare se è troppo lunga, è in una casella di ricerca
#~ msgid "Find apps or documents"
#~ msgstr "Trova programmi e documenti"
# (ndt) no idea...
#~ msgid "Manager"
#~ msgstr "Manager"

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-24 22:30+0200\n"
"PO-Revision-Date: 2009-08-24 22:38+0200\n"
"POT-Creation-Date: 2009-08-29 14:37+0200\n"
"PO-Revision-Date: 2009-08-29 15:10+0200\n"
"Last-Translator: Sander Dijkhuis <sander.dijkhuis@gmail.com>\n"
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
"MIME-Version: 1.0\n"
@ -25,79 +25,79 @@ msgid "Window management and application launching"
msgstr "Vensterbeheer en toepassingen starten"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Activiteiten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:451
msgid "%a %l:%M %p"
msgstr "%a %k:%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Zoeken"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Zoeken"
#: ../js/ui/dash.js:368
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Bladeren"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(alles tonen)"
#. **** Applications ****
#: ../js/ui/dash.js:556 ../js/ui/dash.js:606
#: ../js/ui/dash.js:634 ../js/ui/dash.js:682
msgid "APPLICATIONS"
msgstr "TOEPASSINGEN"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:576
#: ../js/ui/dash.js:654
msgid "PLACES"
msgstr "LOCATIES"
#. **** Documents ****
#: ../js/ui/dash.js:583
#: ../js/ui/dash.js:661 ../js/ui/dash.js:694
msgid "RECENT DOCUMENTS"
msgstr "RECENTE DOCUMENTEN"
#. **** Search Results ****
#: ../js/ui/dash.js:602
#: ../js/ui/dash.js:680
msgid "SEARCH RESULTS"
msgstr "ZOEKRESULTATEN"
#: ../js/ui/dash.js:615
msgid "DOCUMENTS"
msgstr "DOCUMENTEN"
#: ../js/ui/runDialog.js:75
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Voer een opdracht in:"
#: ../src/shell-global.c:841
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Korter dan een minuut geleden"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuut geleden"
msgstr[1] "%d minuten geleden"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d uur geleden"
msgstr[1] "%d uur geleden"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag geleden"
msgstr[1] "%d dagen geleden"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"

182
po/pa.po Normal file
View File

@ -0,0 +1,182 @@
# Punjabi translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
#
# A S Alam <aalam@users.sf.net>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug."
"cgi?product=gnome-shell&component=general\n"
"POT-Creation-Date: 2009-08-31 22:31+0000\n"
"PO-Revision-Date: 2009-09-01 06:51+0530\n"
"Last-Translator: A S Alam <aalam@users.sf.net>\n"
"Language-Team: Punjabi/Panjabi <punjabi-users@lists.sf.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 1.0\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "ਗਨੋਮ ਸ਼ੈਲ"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "ਵਿੰਡੋ ਪਰਬੰਧ ਅਤੇ ਐਪਲੀਕੇਸ਼ਨ ਚਲਾਓ"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "ਸਰਗਰਮੀਆਂ"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "ਖੋਜ..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "ਝਲਕ"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(ਸਭ ਵੇਖੋ)"
#. **** Applications ****
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "ਐਪਲੀਕੇਸ਼ਨ"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "ਥਾਵਾਂ"
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "ਤਾਜ਼ਾ ਡੌਕੂਮੈਂਟ"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "ਖੋਜ ਨਤੀਜੇ"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "ਕਮਾਂਡ ਦਿਓ ਜੀ:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "ਇੱਕ ਮਿੰਟ ਤੋਂ ਘੱਟ ਚਿਰ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
msgstr[1] "%d ਮਿੰਟ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d ਘੰਟਾ ਪਹਿਲਾਂ"
msgstr[1] "%d ਘੰਟੇ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d ਦਿਨ ਪਹਿਲਾਂ"
msgstr[1] "%d ਦਿਨ ਪਹਿਲਾਂ"
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d ਹਫ਼ਤਾ ਪਹਿਲਾਂ"
msgstr[1] "%d ਹਫ਼ਤੇ ਪਹਿਲਾਂ"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "ਅਣਜਾਣ"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "ਸਕਰੀਨ ਲਾਕ ਨਹੀਂ ਹੋ ਸਕਦੀ: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "ਸਕਰੀਨ ਬੰਦ ਕਰਨ ਲਈ ਆਰਜ਼ੀ ਰੂਪ ਵਿੱਚ ਸਕਰੀਨ-ਸੇਵਰ ਨਹੀਂ ਸੈੱਟ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "ਲਾਗਆਉਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "ਅਕਾਊਂਟ ਜਾਣਕਾਰੀ..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "ਬਾਹੀ"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "ਸਿਸਟਮ ਪਸੰਦ..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "ਸਕਰੀਨ ਲਾਕ ਕਰੋ"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "ਯੂਜ਼ਰ ਬਦਲੋ"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "ਲਾਗਆਉਟ..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "ਬੰਦ ਕਰੋ..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "ਘਰ ਫੋਲਡਰ"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "ਫਾਇਲ ਸਿਸਟਮ"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "ਖੋਜ"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-18 23:25+0200\n"
"PO-Revision-Date: 2009-08-18 23:23+0100\n"
"POT-Creation-Date: 2009-09-09 03:06+0200\n"
"PO-Revision-Date: 2009-09-09 03:02+0100\n"
"Last-Translator: Tomasz Dominikowski <dominikowski@gmail.com>\n"
"Language-Team: Polish <gnomepl@aviary.pl>\n"
"MIME-Version: 1.0\n"
@ -29,57 +29,58 @@ msgid "Window management and application launching"
msgstr "Zarządzanie oknami i uruchamianiem programów"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Czynności"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a, %H:%M"
#: ../js/ui/dash.js:251
msgid "Find apps or documents"
msgstr "Wyszukuje programy lub dokumenty"
#: ../js/ui/dash.js:255
msgid "Find..."
msgstr "Znajdź..."
#: ../js/ui/dash.js:369
#: ../js/ui/dash.js:372
msgid "Browse"
msgstr "Przeglądaj"
#: ../js/ui/dash.js:508
msgid "(see all)"
msgstr "(wyświetl wszystko)"
#. **** Applications ****
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
#: ../js/ui/dash.js:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
msgid "APPLICATIONS"
msgstr "Programy"
#. **** Documents ****
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
msgid "RECENT DOCUMENTS"
msgstr "Ostatnie dokumenty"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:598
#: ../js/ui/dash.js:720
msgid "PLACES"
msgstr "Miejsca"
#: ../js/ui/runDialog.js:74
#. **** Documents ****
#: ../js/ui/dash.js:727 ../js/ui/dash.js:768 ../js/ui/dash.js:861
msgid "RECENT DOCUMENTS"
msgstr "Ostatnie dokumenty"
#. **** Search Results ****
#: ../js/ui/dash.js:746 ../js/ui/dash.js:850 ../js/ui/dash.js:876
msgid "SEARCH RESULTS"
msgstr "Wyniki wyszukiwania"
#: ../js/ui/runDialog.js:90
msgid "Please enter a command:"
msgstr "Proszę wprowadzić polecenie:"
#: ../src/gdmuser/gdm-user.c:243
msgid "Manager"
msgstr "Menedżer"
#: ../src/gdmuser/gdm-user.c:244
msgid "The user manager object this user is controlled by."
msgstr "Obiekt menedżera użytkowników, który steruje tym użytkownikiem."
#: ../src/shell-global.c:841
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Mniej niż minutę temu"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
@ -87,7 +88,7 @@ msgstr[0] "%d minuta temu"
msgstr[1] "%d minuty temu"
msgstr[2] "%d minut temu"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
@ -95,7 +96,7 @@ msgstr[0] "%d godzina temu"
msgstr[1] "%d godziny temu"
msgstr[2] "%d godzin temu"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
@ -103,7 +104,7 @@ msgstr[0] "%d dzień temu"
msgstr[1] "%d dni temu"
msgstr[2] "%d dni temu"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-25 07:48+0200\n"
"PO-Revision-Date: 2009-08-25 07:48+0100\n"
"POT-Creation-Date: 2009-09-01 00:31+0200\n"
"PO-Revision-Date: 2009-09-01 00:31+0100\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"MIME-Version: 1.0\n"
@ -25,80 +25,81 @@ msgid "Window management and application launching"
msgstr "Fönsterhantering och programstarter"
#. left side
#: ../js/ui/panel.js:266
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%a %H.%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Hitta program eller dokument"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Sök..."
#: ../js/ui/dash.js:368
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Bläddra"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(se alla)"
#. **** Applications ****
#: ../js/ui/dash.js:556
#: ../js/ui/dash.js:606
#: ../js/ui/dash.js:633
#: ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "PROGRAM"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:576
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "PLATSER"
#. **** Documents ****
#: ../js/ui/dash.js:583
#: ../js/ui/dash.js:660
#: ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "SENASTE DOKUMENT"
#. **** Search Results ****
#: ../js/ui/dash.js:602
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "SÖKRESULTAT"
#: ../js/ui/dash.js:615
msgid "DOCUMENTS"
msgstr "DOKUMENT"
#: ../js/ui/runDialog.js:75
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Ange ett kommando:"
#: ../src/shell-global.c:841
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Mindre än en minut sedan"
#: ../src/shell-global.c:844
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minut sedan"
msgstr[1] "%d minuter sedan"
#: ../src/shell-global.c:847
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d timme sedan"
msgstr[1] "%d timmar sedan"
#: ../src/shell-global.c:850
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag sedan"
msgstr[1] "%d dagar sedan"
#: ../src/shell-global.c:853
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
@ -179,6 +180,10 @@ msgstr "Sök"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "Find apps or documents"
#~ msgstr "Hitta program eller dokument"
#~ msgid "DOCUMENTS"
#~ msgstr "DOKUMENT"
#~ msgid "Manager"
#~ msgstr "Hanterare"
#~ msgid "The user manager object this user is controlled by."

176
po/zh_CN.po Normal file
View File

@ -0,0 +1,176 @@
# Chinese (China) translation for gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Ray Wang <raywang@gnome.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-08-29 19:32+0000\n"
"PO-Revision-Date: 2009-08-30 00:08+0800\n"
"Last-Translator: Ray Wang <raywang@gnome.org>\n"
"Language-Team: Chinese (Simplified) <i18n-zh@googlegroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "窗口管理和应用程序启动"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "活动"
#. Translators: This is a time format.
#: ../js/ui/panel.js:454
msgid "%a %l:%M %p"
msgstr "%A %H:%M"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "查找..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "浏览"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(查看所有)"
#. **** Applications ****
#: ../js/ui/dash.js:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "应用程序"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "位置"
#. **** Documents ****
#: ../js/ui/dash.js:660 ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "最近的文档"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "搜索结果"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "请输入一个命令:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "少于一分钟前"
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d 分钟前"
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d 小时前"
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d 天前"
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d 周前"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "未知"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "不能锁住屏幕:%s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "不能临时将屏幕保护设置成空白屏幕:%s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "不能退出:%s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "帐户信息..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "侧边栏"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "系统首选项..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "锁住屏幕"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "切换用户"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "退出..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "关机..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "主文件夹"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "文件系统"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "搜索"
#. Translators: the first string is the name of a gvfs
#. * method, and the second string is a path. For
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-uri-util.c:298
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

View File

@ -1,9 +1,11 @@
NULL =
BUILT_SOURCES =
CLEANFILES =
EXTRA_DIST =
EXTRA_DIST =
libexec_PROGRAMS =
noinst_LTLIBRARIES =
noinst_LTLIBRARIES =
.AUTOPARALLEL:
bin_SCRIPTS = gnome-shell
@ -14,6 +16,7 @@ gnome-shell: gnome-shell.in
-e "s|@libexecdir[@]|$(libexecdir)|" \
-e "s|@libdir[@]|$(libdir)|" \
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
-e "s|@PYTHON[@]|$(PYTHON)|" \
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
$< > $@ && chmod a+x $@
CLEANFILES += gnome-shell
@ -72,6 +75,8 @@ libgnome_shell_la_SOURCES = \
shell-generic-container.h \
shell-gtk-embed.c \
shell-gtk-embed.h \
shell-menu.c \
shell-menu.h \
shell-overflow-list.c \
shell-overflow-list.h \
shell-process.c \
@ -161,6 +166,7 @@ Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
--include=Clutter-1.0 \
--include=Meta-2.27 \
--libtool="$(LIBTOOL)" \
--add-include-path=$(builddir) \
--include=Big-1.0 \
--program=mutter \
@ -180,12 +186,13 @@ Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
Shell-0.1.gir -o $@
CLEANFILES += Shell-0.1.typelib
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la $(srcdir)/big-enum-types.h Makefile
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Big \
--nsversion=1.0 \
--include=Clutter-1.0 \
--include=GdkPixbuf-2.0 \
--libtool="$(LIBTOOL)" \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(big_source_h)) \

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!@PYTHON@
import atexit
import optparse
@ -253,6 +253,7 @@ if options.debug:
normal_exit = False
try:
shell = None
if options.xephyr:
xephyr = start_xephyr()
# This makes us not grab the org.gnome.Panel name
@ -281,7 +282,9 @@ finally:
except OSError:
pass
if shell.returncode == 0:
if shell is None:
print "Failed to start shell"
elif shell.returncode == 0:
normal_exit = True
if options.verbose:
print "Shell exited normally"

View File

@ -345,7 +345,7 @@ window_is_tracked (MetaWindow *window)
}
/**
* window_is_usage_tracked:
* shell_app_monitor_is_window_usage_tracked:
*
* Determine if it makes sense to track the given window for application
* usage. An example of a window we don't want to track is the root
@ -358,12 +358,15 @@ window_is_tracked (MetaWindow *window)
*
* Returns: %TRUE iff we want to record focus time spent in this window
*/
static gboolean
window_is_usage_tracked (MetaWindow *window)
gboolean
shell_app_monitor_is_window_usage_tracked (MetaWindow *window)
{
if (!window_is_tracked (window))
return FALSE;
if (meta_window_is_skip_taskbar (window))
return FALSE;
switch (meta_window_get_window_type (window))
{
/* Definitely ignore these. */
@ -434,9 +437,10 @@ get_app_for_window_direct (MetaWindow *window)
if (id != NULL)
result = shell_app_system_load_from_desktop_file (appsys, id, NULL);
else
result = create_transient_app_for_window (window);
}
if (result == NULL)
result = create_transient_app_for_window (window);
return result;
}
@ -562,7 +566,7 @@ get_active_window (ShellAppMonitor *monitor)
display = meta_screen_get_display (screen);
window = meta_display_get_focus_window (display);
if (window != NULL && window_is_usage_tracked (window))
if (window != NULL && shell_app_monitor_is_window_usage_tracked (window))
return window;
return NULL;
}
@ -756,7 +760,7 @@ track_window (ShellAppMonitor *self,
* tracked it doesn't count for the purposes of an application
* running.
*/
if (!window_is_usage_tracked (window))
if (!shell_app_monitor_is_window_usage_tracked (window))
return;
usage = get_app_usage_from_window (self, window);
@ -812,7 +816,7 @@ disassociate_window (ShellAppMonitor *self,
if (window == self->watched_window)
self->watched_window = NULL;
if (window_is_usage_tracked (window))
if (shell_app_monitor_is_window_usage_tracked (window))
{
AppUsage *usage;
const char *context;
@ -930,7 +934,7 @@ shell_app_monitor_get_windows_for_app (ShellAppMonitor *self,
ShellAppInfo *app = value;
const char *id = shell_app_info_get_id (app);
if (!window_is_usage_tracked (window))
if (!shell_app_monitor_is_window_usage_tracked (window))
continue;
if (strcmp (id, appid) != 0)
@ -1181,7 +1185,7 @@ shell_app_monitor_get_running_apps (ShellAppMonitor *monitor,
if (strcmp (get_window_context (window), context) != 0)
continue;
if (!window_is_usage_tracked (window))
if (!shell_app_monitor_is_window_usage_tracked (window))
continue;
id = shell_app_info_get_id (app);

View File

@ -44,6 +44,8 @@ GList *shell_app_monitor_get_most_used_apps (ShellAppMonitor *monitor,
GSList *shell_app_monitor_get_windows_for_app (ShellAppMonitor *monitor, const char *appid);
gboolean shell_app_monitor_is_window_usage_tracked (MetaWindow *window);
/* Get whatever's running right now */
GSList *shell_app_monitor_get_running_apps (ShellAppMonitor *monitor, const char *context);

View File

@ -52,10 +52,13 @@ struct _ShellAppSystemPrivate {
GList *cached_favorites; /* utf8 */
gint app_monitor_id;
guint app_change_timeout_id;
};
static void shell_app_system_finalize (GObject *object);
static void on_tree_changed (GMenuTree *tree, gpointer user_data);
static gboolean on_tree_changed (gpointer user_data);
static void on_tree_changed_cb (GMenuTree *tree, gpointer user_data);
static void reread_menus (ShellAppSystem *self);
static void on_favorite_apps_changed (GConfClient *client, guint id, GConfEntry *entry, gpointer user_data);
static void reread_favorite_apps (ShellAppSystem *system);
@ -233,8 +236,10 @@ shell_app_system_init (ShellAppSystem *self)
priv->apps_tree = gmenu_tree_lookup ("applications.menu", GMENU_TREE_FLAGS_INCLUDE_NODISPLAY);
priv->settings_tree = gmenu_tree_lookup ("settings.menu", GMENU_TREE_FLAGS_NONE);
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed, self);
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed, self);
priv->app_change_timeout_id = 0;
gmenu_tree_add_monitor (priv->apps_tree, on_tree_changed_cb, self);
gmenu_tree_add_monitor (priv->settings_tree, on_tree_changed_cb, self);
reread_menus (self);
@ -251,8 +256,8 @@ shell_app_system_finalize (GObject *object)
ShellAppSystem *self = SHELL_APP_SYSTEM (object);
ShellAppSystemPrivate *priv = self->priv;
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed, self);
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed, self);
gmenu_tree_remove_monitor (priv->apps_tree, on_tree_changed_cb, self);
gmenu_tree_remove_monitor (priv->settings_tree, on_tree_changed_cb, self);
gmenu_tree_unref (priv->apps_tree);
gmenu_tree_unref (priv->settings_tree);
@ -410,14 +415,39 @@ reread_menus (ShellAppSystem *self)
cache_by_id (self, self->priv->cached_settings, TRUE);
}
static gboolean
on_tree_changed (gpointer user_data)
{
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
reread_menus (self);
self->priv->app_change_timeout_id = 0;
return FALSE;
}
static void
on_tree_changed (GMenuTree *monitor, gpointer user_data)
on_tree_changed_cb (GMenuTree *monitor, gpointer user_data)
{
ShellAppSystem *self = SHELL_APP_SYSTEM (user_data);
g_signal_emit (self, signals[INSTALLED_CHANGED], 0);
/* GMenu currently gives us a separate notification on the entire
* menu tree for each node in the tree that might potentially have
* changed. (See http://bugzilla.gnome.org/show_bug.cgi?id=172046.)
* We need to compress these to avoid doing large extra amounts of
* work.
*
* Even when that bug is fixed, compression is still useful; for one
* thing we want to need to compress across notifications of changes
* to the settings tree. Second we want to compress if multiple
* changes are made to the desktop files at different times but in
* short succession.
*/
reread_menus (self);
if (self->priv->app_change_timeout_id != 0)
return;
self->priv->app_change_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 3000,
(GSourceFunc) on_tree_changed,
self, NULL);
}
static GList *

View File

@ -14,6 +14,7 @@
G_DEFINE_TYPE(ShellButtonBox, shell_button_box, BIG_TYPE_BOX);
struct _ShellButtonBoxPrivate {
gboolean active;
gboolean held;
gboolean hover;
gboolean pressed;
@ -29,12 +30,23 @@ enum
enum {
PROP_0,
PROP_ACTIVE,
PROP_HOVER,
PROP_PRESSED,
};
static guint shell_button_box_signals [LAST_SIGNAL] = { 0 };
static void
set_active (ShellButtonBox *box,
gboolean active)
{
if (box->priv->active == active)
return;
box->priv->active = active;
g_object_notify (G_OBJECT (box), "active");
}
static void
set_hover (ShellButtonBox *box,
gboolean hover)
@ -67,28 +79,34 @@ shell_button_box_contains (ShellButtonBox *box,
}
static gboolean
shell_button_box_on_enter (ShellButtonBox *box,
ClutterEvent *event,
gpointer user_data)
shell_button_box_enter_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
if (shell_button_box_contains (box, event->crossing.related))
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (shell_button_box_contains (box, event->related))
return TRUE;
if (!shell_button_box_contains (box, clutter_event_get_source (event)))
if (!shell_button_box_contains (box, event->source))
return TRUE;
set_hover (box, TRUE);
g_object_freeze_notify (G_OBJECT (actor));
if (box->priv->held)
set_pressed (box, TRUE);
set_hover (box, TRUE);
g_object_thaw_notify (G_OBJECT (actor));
return TRUE;
}
static gboolean
shell_button_box_on_leave (ShellButtonBox *box,
ClutterEvent *event,
gpointer user_data)
shell_button_box_leave_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
if (shell_button_box_contains (box, event->crossing.related))
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (shell_button_box_contains (box, event->related))
return TRUE;
set_hover (box, FALSE);
@ -98,17 +116,18 @@ shell_button_box_on_leave (ShellButtonBox *box,
}
static gboolean
shell_button_box_on_press (ShellButtonBox *box,
ClutterEvent *event,
gpointer user_data)
shell_button_box_button_press_event (ClutterActor *actor,
ClutterButtonEvent *event)
{
ClutterActor *source;
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (event->button != 1 || event->click_count != 1)
return FALSE;
if (box->priv->held)
return TRUE;
source = clutter_event_get_source (event);
if (!shell_button_box_contains (box, source))
if (!shell_button_box_contains (box, event->source))
return FALSE;
box->priv->held = TRUE;
@ -120,38 +139,68 @@ shell_button_box_on_press (ShellButtonBox *box,
}
static gboolean
shell_button_box_on_release (ShellButtonBox *box,
ClutterEvent *event,
gpointer user_data)
shell_button_box_button_release_event (ClutterActor *actor,
ClutterButtonEvent *event)
{
ClutterActor *source;
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (event->button != 1 || event->click_count != 1)
return FALSE;
if (!box->priv->held)
return TRUE;
source = clutter_event_get_source (event);
box->priv->held = FALSE;
clutter_ungrab_pointer ();
if (!shell_button_box_contains (box, source))
if (!shell_button_box_contains (box, event->source))
return FALSE;
set_pressed (box, FALSE);
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0);
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0, event);
return TRUE;
}
/**
* shell_button_box_fake_release:
* @box:
*
* If this button box is holding a pointer grab, this function will
* will ungrab it, and reset the pressed state. The effect is
* similar to if the user had released the mouse button, but without
* emitting the activate signal.
*
* This function is useful if for example you want to do something after the user
* is holding the mouse button for a given period of time, breaking the
* grab.
*/
void
shell_button_box_fake_release (ShellButtonBox *box)
{
if (!box->priv->held)
return;
box->priv->held = FALSE;
clutter_ungrab_pointer ();
set_pressed (box, FALSE);
}
static void
shell_button_box_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (object);
switch (prop_id)
{
case PROP_ACTIVE:
set_active (box, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -168,6 +217,9 @@ shell_button_box_get_property(GObject *object,
switch (prop_id)
{
case PROP_ACTIVE:
g_value_set_boolean (value, box->priv->active);
break;
case PROP_PRESSED:
g_value_set_boolean (value, box->priv->pressed);
break;
@ -184,13 +236,20 @@ static void
shell_button_box_class_init (ShellButtonBoxClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->get_property = shell_button_box_get_property;
gobject_class->set_property = shell_button_box_set_property;
actor_class->enter_event = shell_button_box_enter_event;
actor_class->leave_event = shell_button_box_leave_event;
actor_class->button_press_event = shell_button_box_button_press_event;
actor_class->button_release_event = shell_button_box_button_release_event;
/**
* ShellButtonBox::activate
* @box: The #ShellButtonBox
* @event: Release event which triggered the activation
*
* This signal is emitted when the button should take the action
* associated with button click+release.
@ -202,7 +261,22 @@ shell_button_box_class_init (ShellButtonBoxClass *klass)
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT);
/**
* ShellButtonBox:active
*
* The property allows the button to be used as a "toggle button"; it's up to the
* application to update the active property in response to the activate signal;
* it doesn't happen automatically.
*/
g_object_class_install_property (gobject_class,
PROP_ACTIVE,
g_param_spec_boolean ("active",
"Active",
"Whether the button persistently active",
FALSE,
G_PARAM_READWRITE));
/**
* ShellButtonBox:hover
@ -240,9 +314,4 @@ shell_button_box_init (ShellButtonBox *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_BUTTON_BOX,
ShellButtonBoxPrivate);
g_signal_connect (G_OBJECT (self), "enter-event", G_CALLBACK(shell_button_box_on_enter), NULL);
g_signal_connect (G_OBJECT (self), "leave-event", G_CALLBACK(shell_button_box_on_leave), NULL);
g_signal_connect (G_OBJECT (self), "button-press-event", G_CALLBACK(shell_button_box_on_press), NULL);
g_signal_connect (G_OBJECT (self), "button-release-event", G_CALLBACK(shell_button_box_on_release), NULL);
}

View File

@ -30,4 +30,6 @@ struct _ShellButtonBoxClass
GType shell_button_box_get_type (void) G_GNUC_CONST;
void shell_button_box_fake_release (ShellButtonBox *box);
#endif /* __SHELL_BUTTON_BOX_H__ */

View File

@ -146,79 +146,33 @@ shell_draw_clock (ClutterCairoTexture *texture,
cairo_destroy (cr);
}
static void
draw_glow (cairo_t *cr, double red, double green, double blue, double alpha)
{
cairo_pattern_t *gradient;
cairo_save (cr);
gradient = cairo_pattern_create_radial (0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
cairo_pattern_add_color_stop_rgba (gradient, 0.0, red, green, blue, alpha);
cairo_pattern_add_color_stop_rgba (gradient, 0.7, red, green, blue, alpha * 0.7);
cairo_pattern_add_color_stop_rgba (gradient, 1.0, red, green, blue, alpha * 0.3);
cairo_set_source (cr, gradient);
cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
cairo_fill (cr);
cairo_restore (cr);
cairo_pattern_destroy (gradient);
}
void
shell_draw_app_highlight (ClutterCairoTexture *texture,
int num_windows,
double red,
double green,
double blue,
double alpha)
shell_draw_box_pointer (ClutterCairoTexture *texture,
ClutterColor *border_color,
ClutterColor *background_color)
{
cairo_t *cr;
guint width, height;
g_return_if_fail (num_windows > 0);
cairo_t *cr;
clutter_cairo_texture_get_surface_size (texture, &width, &height);
clutter_cairo_texture_clear (texture);
cr = clutter_cairo_texture_create (texture);
cairo_save (cr);
cairo_translate (cr, width / 2.0, height / 2.0);
cairo_set_line_width (cr, 1.0);
if (num_windows == 1)
{
cairo_scale (cr, width / 2.0, height / 2.0);
draw_glow (cr, red, green, blue, alpha);
}
else
{
int num_circles, i;
double scale, highlight_width;
clutter_cairo_set_source_color (cr, border_color);
num_circles = num_windows == 2 ? 2 : 3;
cairo_move_to (cr, width, 0);
cairo_line_to (cr, 0, floor (height * 0.5));
cairo_line_to (cr, width, height);
/* The circles will have radius 1.0 (diameter 2.0) and overlap
* by 0.2, so the total width of the highlight is:
*/
highlight_width = 2.0 * num_circles - 0.2 * (num_circles - 1);
cairo_stroke_preserve (cr);
scale = MIN (height / 2.0, width / highlight_width);
cairo_scale (cr, scale, scale);
clutter_cairo_set_source_color (cr, background_color);
/* The leftmost circle's left side is at -highlight_width/2, so
* its center is that plus 1.
*/
cairo_translate (cr, -highlight_width / 2.0 + 1.0, 0.0);
for (i = 0; i < num_circles; i++)
{
draw_glow (cr, red, green, blue, alpha);
cairo_translate (cr, 1.8, 0.0);
}
}
cairo_fill (cr);
cairo_restore (cr);
cairo_destroy (cr);
}

View File

@ -13,17 +13,14 @@ ClutterCairoTexture *shell_create_vertical_gradient (ClutterColor *top,
ClutterCairoTexture *shell_create_horizontal_gradient (ClutterColor *left,
ClutterColor *right);
void shell_draw_box_pointer (ClutterCairoTexture *texture,
ClutterColor *border_color,
ClutterColor *background_color);
void shell_draw_clock (ClutterCairoTexture *texture,
int hour,
int minute);
void shell_draw_app_highlight (ClutterCairoTexture *texture,
int num_windows,
double red,
double blue,
double green,
double alpha);
guint shell_add_hook_paint_red_border (ClutterActor *actor);
G_END_DECLS

View File

@ -295,47 +295,6 @@ shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
0, NULL);
}
/**
* shell_get_event_key_symbol:
*
* Return value: Clutter key value for the key press and release events,
* as specified in clutter-keysyms.h
*/
guint16
shell_get_event_key_symbol(ClutterEvent *event)
{
g_return_val_if_fail(event->type == CLUTTER_KEY_PRESS ||
event->type == CLUTTER_KEY_RELEASE, 0);
return event->key.keyval;
}
/**
* shell_get_button_event_click_count:
*
* Return value: click count for button press and release events
*/
guint16
shell_get_button_event_click_count(ClutterEvent *event)
{
g_return_val_if_fail(event->type == CLUTTER_BUTTON_PRESS ||
event->type == CLUTTER_BUTTON_RELEASE, 0);
return event->button.click_count;
}
/**
* shell_get_event_related:
*
* Return value: (transfer none): related actor
*/
ClutterActor *
shell_get_event_related (ClutterEvent *event)
{
g_return_val_if_fail (event->type == CLUTTER_ENTER ||
event->type == CLUTTER_LEAVE, NULL);
return event->crossing.related;
}
/**
* shell_global_get:
*

View File

@ -36,10 +36,6 @@ GType shell_global_get_type (void) G_GNUC_CONST;
gboolean shell_clutter_texture_set_from_pixbuf (ClutterTexture *texture,
GdkPixbuf *pixbuf);
guint16 shell_get_event_key_symbol(ClutterEvent *event);
guint16 shell_get_button_event_click_count(ClutterEvent *event);
ClutterActor *shell_get_event_related(ClutterEvent *event);
ShellGlobal *shell_global_get (void);

335
src/shell-menu.c Normal file
View File

@ -0,0 +1,335 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* SECTION:shell-menu
* @short_description: A box which acts like a popup menu
*
* A #BigBox subclass which adds methods and signals useful for implementing
* popup-menu like actors.
*/
#include "shell-menu.h"
G_DEFINE_TYPE(ShellMenu, shell_menu, BIG_TYPE_BOX);
struct _ShellMenuPrivate {
gboolean popped_up;
gboolean have_grab;
gboolean released_on_source;
ClutterActor *source_actor;
ClutterActor *selected;
};
/* Signals */
enum
{
UNSELECTED,
SELECTED,
ACTIVATE,
CANCELLED,
LAST_SIGNAL
};
static guint shell_menu_signals [LAST_SIGNAL] = { 0 };
static gboolean
container_contains (ClutterContainer *container,
ClutterActor *actor)
{
while (actor != NULL && actor != (ClutterActor*)container)
{
actor = clutter_actor_get_parent (actor);
}
return actor != NULL;
}
static void
shell_menu_popdown_nosignal (ShellMenu *box)
{
box->priv->popped_up = FALSE;
if (box->priv->have_grab)
clutter_ungrab_pointer ();
clutter_actor_hide (CLUTTER_ACTOR (box));
}
static void
on_selected_destroy (ClutterActor *actor,
ShellMenu *box)
{
box->priv->selected = NULL;
}
static void
set_selected (ShellMenu *box,
ClutterActor *actor)
{
if (actor == box->priv->selected)
return;
if (box->priv->selected)
{
g_signal_handlers_disconnect_by_func (box->priv->selected, G_CALLBACK(on_selected_destroy), box);
g_signal_emit (G_OBJECT (box), shell_menu_signals[UNSELECTED], 0, box->priv->selected);
}
box->priv->selected = actor;
if (box->priv->selected)
{
g_signal_connect (box->priv->selected, "destroy", G_CALLBACK(on_selected_destroy), box);
g_signal_emit (G_OBJECT (box), shell_menu_signals[SELECTED], 0, box->priv->selected);
}
}
static gboolean
shell_menu_enter_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
ShellMenu *box = SHELL_MENU (actor);
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
return TRUE;
if (event->source == (ClutterActor*)box)
return TRUE;
if (g_object_get_data (G_OBJECT (event->source), "shell-is-separator"))
return TRUE;
set_selected (box, event->source);
return TRUE;
}
static gboolean
shell_menu_leave_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
ShellMenu *box = SHELL_MENU (actor);
set_selected (box, NULL);
return TRUE;
}
static gboolean
shell_menu_button_release_event (ClutterActor *actor,
ClutterButtonEvent *event)
{
ShellMenu *box = SHELL_MENU (actor);
if (event->button != 1)
return FALSE;
if (box->priv->source_actor && !box->priv->released_on_source)
{
if (box->priv->source_actor == event->source ||
(CLUTTER_IS_CONTAINER (box->priv->source_actor) &&
container_contains (CLUTTER_CONTAINER (box->priv->source_actor), event->source)))
{
/* On the next release, we want to pop down the menu regardless */
box->priv->released_on_source = TRUE;
return TRUE;
}
}
shell_menu_popdown_nosignal (box);
if (!container_contains (CLUTTER_CONTAINER (box), event->source))
{
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
return FALSE;
}
if (box->priv->selected == NULL)
{
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
return FALSE;
}
g_signal_emit (G_OBJECT (box), shell_menu_signals[ACTIVATE], 0, box->priv->selected);
return TRUE;
}
void
shell_menu_popup (ShellMenu *box,
guint button,
guint32 activate_time)
{
if (box->priv->popped_up)
return;
box->priv->popped_up = TRUE;
box->priv->have_grab = TRUE;
box->priv->released_on_source = FALSE;
clutter_grab_pointer (CLUTTER_ACTOR (box));
}
/**
* shell_menu_popdown:
* @box:
*
* If the menu is currently active, hide it, emitting the 'cancelled' signal.
*/
void
shell_menu_popdown (ShellMenu *box)
{
if (!box->priv->popped_up)
return;
shell_menu_popdown_nosignal (box);
g_signal_emit (G_OBJECT (box), shell_menu_signals[CANCELLED], 0);
}
static void
on_source_destroyed (ClutterActor *actor,
ShellMenu *box)
{
box->priv->source_actor = NULL;
}
/**
* shell_menu_set_persistent_source:
* @box:
* @source: Actor to use as menu origin
*
* This function changes the menu behavior on button release. Normally
* when the mouse is released anywhere, the menu "pops down"; when this
* function is called, if the mouse is released over the source actor,
* the menu stays.
*
* The given @source actor must be reactive for this function to work.
*/
void
shell_menu_set_persistent_source (ShellMenu *box,
ClutterActor *source)
{
if (box->priv->source_actor)
{
g_signal_handlers_disconnect_by_func (G_OBJECT (box->priv->source_actor),
G_CALLBACK (on_source_destroyed),
box);
}
box->priv->source_actor = source;
if (box->priv->source_actor)
{
g_signal_connect (G_OBJECT (box->priv->source_actor),
"destroy",
G_CALLBACK (on_source_destroyed),
box);
}
}
/**
* shell_menu_append_separator:
* @box:
* @separator: An actor which functions as a menu separator
* @flags: Packing flags
*
* Actors added to the menu with default functions are treated like
* menu items; this function will add an actor that should instead
* be treated like a menu separator. The current practical effect
* is that the separators will not be selectable.
*/
void
shell_menu_append_separator (ShellMenu *box,
ClutterActor *separator,
BigBoxPackFlags flags)
{
g_object_set_data (G_OBJECT (separator), "shell-is-separator", GUINT_TO_POINTER(TRUE));
big_box_append (BIG_BOX (box), separator, flags);
}
static void
shell_menu_dispose (GObject *gobject)
{
ShellMenu *self = SHELL_MENU (gobject);
shell_menu_set_persistent_source (self, NULL);
G_OBJECT_CLASS (shell_menu_parent_class)->dispose (gobject);
}
static void
shell_menu_class_init (ShellMenuClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->dispose = shell_menu_dispose;
actor_class->enter_event = shell_menu_enter_event;
actor_class->leave_event = shell_menu_leave_event;
actor_class->button_release_event = shell_menu_button_release_event;
/**
* ShellMenu::unselected
* @box: The #ShellMenu
* @actor: The previously hovered-over menu item
*
* This signal is emitted when a menu item transitions to
* an unselected state.
*/
shell_menu_signals[UNSELECTED] =
g_signal_new ("unselected",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
/**
* ShellMenu::selected
* @box: The #ShellMenu
* @actor: The hovered-over menu item
*
* This signal is emitted when a menu item is in a selected state.
*/
shell_menu_signals[SELECTED] =
g_signal_new ("selected",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
/**
* ShellMenu::activate
* @box: The #ShellMenu
* @actor: The clicked menu item
*
* This signal is emitted when a menu item is selected.
*/
shell_menu_signals[ACTIVATE] =
g_signal_new ("activate",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, CLUTTER_TYPE_ACTOR);
/**
* ShellMenu::cancelled
* @box: The #ShellMenu
*
* This signal is emitted when the menu is closed without an option selected.
*/
shell_menu_signals[CANCELLED] =
g_signal_new ("cancelled",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 0);
g_type_class_add_private (gobject_class, sizeof (ShellMenuPrivate));
}
static void
shell_menu_init (ShellMenu *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_MENU,
ShellMenuPrivate);
}

41
src/shell-menu.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef __SHELL_MENU_H__
#define __SHELL_MENU_H__
#include <clutter/clutter.h>
#include "big/box.h"
#define SHELL_TYPE_MENU (shell_menu_get_type ())
#define SHELL_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_MENU, ShellMenu))
#define SHELL_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_MENU, ShellMenuClass))
#define SHELL_IS_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_MENU))
#define SHELL_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_MENU))
#define SHELL_MENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_MENU, ShellMenuClass))
typedef struct _ShellMenu ShellMenu;
typedef struct _ShellMenuClass ShellMenuClass;
typedef struct _ShellMenuPrivate ShellMenuPrivate;
struct _ShellMenu
{
BigBox parent;
ShellMenuPrivate *priv;
};
struct _ShellMenuClass
{
BigBoxClass parent_class;
};
GType shell_menu_get_type (void) G_GNUC_CONST;
void shell_menu_popup (ShellMenu *behavior, guint button, guint32 activate_time);
void shell_menu_set_persistent_source (ShellMenu *behavior, ClutterActor *source);
void shell_menu_append_separator (ShellMenu *behavior, ClutterActor *separator, BigBoxPackFlags flags);
void shell_menu_popdown (ShellMenu *behavior);
#endif /* __SHELL_MENU_H__ */

View File

@ -1236,6 +1236,35 @@ shell_texture_cache_evict_recent_thumbnail (ShellTextureCache *cache,
shell_texture_cache_evict_thumbnail (cache, gtk_recent_info_get_uri (info));
}
static size_t
pixbuf_byte_size (GdkPixbuf *pixbuf)
{
/* This bit translated from gtk+/gdk-pixbuf/gdk-pixbuf.c:gdk_pixbuf_copy. The comment
* there was:
*
* Calculate a semi-exact size. Here we copy with full rowstrides;
* maybe we should copy each row individually with the minimum
* rowstride?
*/
return (gdk_pixbuf_get_height (pixbuf) - 1) * gdk_pixbuf_get_rowstride (pixbuf) +
+ gdk_pixbuf_get_width (pixbuf) * ((gdk_pixbuf_get_n_channels (pixbuf)* gdk_pixbuf_get_bits_per_sample (pixbuf) + 7) / 8);
}
/**
* shell_texture_cache_pixbuf_equal:
*
* Returns: %TRUE iff the given pixbufs are bytewise-equal
*/
gboolean
shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b)
{
size_t size_a = pixbuf_byte_size (a);
size_t size_b = pixbuf_byte_size (b);
if (size_a != size_b)
return FALSE;
return memcmp (gdk_pixbuf_get_pixels (a), gdk_pixbuf_get_pixels (b), size_a) == 0;
}
static ShellTextureCache *instance = NULL;
/**

View File

@ -79,4 +79,6 @@ ClutterActor *shell_texture_cache_load_uri_sync (ShellTextureCache *cache,
int available_height,
GError **error);
gboolean shell_texture_cache_pixbuf_equal (ShellTextureCache *cache, GdkPixbuf *a, GdkPixbuf *b);
#endif /* __SHELL_TEXTURE_CACHE_H__ */

View File

@ -53,7 +53,8 @@ fi
#
# Non-devel packages needed by gnome-shell and its deps:
# glxinfo, gstreamer-plugins-base, gstreamer-plugins-good,
# python, Xephyr, xeyes*, xlogo*, xterm*, zenity
# python, pygobject, gnome-python (gconf),
# Xephyr, xeyes*, xlogo*, xterm*, zenity
#
# (*)ed packages are only needed because gnome-shell launches them
# when running in Xephyr mode, and we should probably change it to use
@ -80,8 +81,8 @@ if test x$system = xUbuntu -o x$system = xDebian ; then
automake bison flex git-core gnome-common gtk-doc-tools \
libdbus-glib-1-dev libgconf2-dev libgtk2.0-dev libffi-dev \
libgnome-menu-dev libgnome-desktop-dev librsvg2-dev libwnck-dev libgl1-mesa-dev \
mesa-common-dev mesa-utils python-dev libreadline5-dev xulrunner-dev \
xserver-xephyr \
libreadline5-dev mesa-common-dev mesa-utils python-dev python-gconf python-gobject \
xulrunner-dev xserver-xephyr \
libgstreamer0.10-dev gstreamer0.10-plugins-base gstreamer0.10-plugins-good \
; do
if ! dpkg_is_installed $pkg; then
@ -101,9 +102,9 @@ if test x$system = xFedora ; then
binutils curl gcc make \
automake bison flex git gnome-common gnome-doc-utils intltool \
libtool pkgconfig \
dbus-glib-devel GConf2-devel gnome-menus-devel gtk2-devel libffi-devel gnome-desktop-devel \
librsvg2-devel libwnck-devel mesa-libGL-devel python-devel readline-devel \
xulrunner-devel libXdamage-devel \
dbus-glib-devel GConf2-devel gnome-menus-devel gnome-python2-gconf gtk2-devel libffi-devel \
gnome-desktop-devel librsvg2-devel libwnck-devel mesa-libGL-devel python-devel pygobject2 \
readline-devel xulrunner-devel libXdamage-devel \
gstreamer-devel gstreamer-plugins-base gstreamer-plugins-good \
glx-utils xorg-x11-apps xorg-x11-server-Xephyr xterm zenity \
; do