Compare commits

...

403 Commits

Author SHA1 Message Date
4f070317d2 lookingGlass: Get font from GConf
Instead of using "Monospace", pick the users configured monospace font
name up from GConf. (This is a nice touch, but is more done here to
demonstrate that we can do it rather than for any great utility.)
2009-09-21 20:13:00 -04:00
661100abe8 Port LookingGlass console to NBTK
* Style aspects like colors and fonts are moved into gnome-shell.css.
* Scrolling is adding using NbtkScrollView.

Based on a patch from Colin Walters
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-21 20:11:09 -04:00
3e90b11cfb Add clutter-text properties to NbtkEntry and NbtkLabel
Add clutter-text properties to allow getting access to the underlying
ClutterText actor. This corresponds to the get_clutter_text() methods.

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

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

clip-to-allocation is removed from NbtkScrollView since it's just
not right - if the child has any non-moving elements, like headers or
borders, it will need to set a narrower clip. And even if the entire
child scrolls, we want to clip to an arrow that excludes the scrollbars.
2009-09-21 19:32:38 -04:00
1a4861ec4f Remove NbtkViewport from our tree
NbtkBoxLayout provides the basic functionality of 2-dimensional
scrolling and we don't use NbtkViewport anywhere, so remove it.

This avoids fixing NbtkViewport up for the interaction of scrolling
and borders/padding, which would be a little involved and require
a test program for NbtkViewport to be written.
2009-09-21 19:32:33 -04:00
2ac82da232 Allocate children as wide as the scrolled area
When we are scrolling a vertical box horizontally , children should be
allocated horizontally as wide as the full horizontal scrolled area,
not just to the size of the "viewport". Similarly for a horizontal box.

http://bugzilla.moblin.org/show_bug.cgi?id=6312
2009-09-21 19:32:33 -04:00
8f7e6f8117 Allow NbtkBoxLayout to shrink down to its minimum size
When a NbtkBoxLayout is allocated a size less than its natural size,
think "shrink" needs to be divided among the children that have
a smaller minimum size than natural size.

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

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

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

http://bugzilla.moblin.org/show_bug.cgi?id=6311
2009-09-21 19:32:33 -04:00
d2b98701be Don't count not-visible children among expand children
When counting how many children we should divide extra space among,
don't count not-visible children.

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

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

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

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

(If we don't want this behavior - e.g., to be able to use the
transparent borders as margins, then alternatively transparent
border handling would have to be fixed in nbtk-widget.c, since
prior to this transparent and translucent borders were handled
differently.)
2009-09-21 19:32:32 -04:00
2232a92ba8 Rename ShellThemeImage to ShellBorderImage
The current CSS3 border-image is close to a superset of what we were
doing for -hippo-background-image. Woot! rename ShellThemeImage to
ShellBorderImage and change parsing to look for:

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

Rather than

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

percentanges for the border sizes are not currently supported, neither
are the keywords for handling of the middle part. We always do 'stretch'
for now.
2009-09-21 19:32:32 -04:00
4743a8e750 Add support for colored borders
Use BigRectangle to draw the border and background if there's
a border width or border radius and no border image. (Only
uniform borders are supported for now with some deviations
from the CSS model noted in the comments.)

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

Add a test case for borders, and also use borders to style
the buttons in the 'inline-style' test case.
2009-09-21 19:32:32 -04:00
e1390c7dd5 Centralize computations of border and padding into ShellThemeNode
Rather than repeating the computation of borders in many different
widget subclasses, add helper functions:

 shell_theme_node_adjust_for_height()
 shell_theme_node_adjust_preferred_width()
 shell_theme_node_adjust_for_width()
 shell_theme_node_adjust_preferred_height()
 shell_theme_node_get_content_box()

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

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

Borders are included in the geometry adjustments, but borders
are not yet drawn.
2009-09-21 19:32:24 -04:00
49ba54820c ShellThemeNode: Add border-radius support
Add support for parsing and caching the border-radius property.
Different radii for the 4 corners are supported; elliptical corners
are not supported.
2009-09-21 19:32:23 -04:00
8ffa161a7f Fix problems with 4-sided padding: specifiers
The test for identifying such a specifier was wrong, and the last
value was assigned to the wrong sides.
2009-09-21 19:32:23 -04:00
0eca3efcb0 Add support for inline styles
Add support for passing an inline-style string when creating a
ShellThemeNode.

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

Add a test case that demonstrates using this to update font sizes
on the fly.
2009-09-21 19:32:23 -04:00
9c3af62dc4 run-test.sh: support running tests under gdb
As with the 'gnome-shell' -g/--debug can be passed to run under
the debugger.
2009-09-21 19:32:23 -04:00
db0c2b5959 Port our imported parts of Nbtk to ShellTheme
ShellTheme replaces both NbtkStyle and ccss_stylesheet_t.

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

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

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

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

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

Some more javascript tests for CSS functionality are added; workarounds for
a CSS bug where *.some-class was needed instead of .some-class are removed.
2009-09-21 19:32:18 -04:00
98215f497d Import stylesheet code from hippo-canvas
Import:

  HippoCanvasTheme      => ShellTheme
  HippoCanvasThemeImage => ShellThemeImage
  HippoCanvasStyle      => ShellThemeNode

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

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

Various changes are made in the import:

 - Comprehensive reindentation
 - guint32 pixels replaced with ClutterColor
 - General pseudo-class support added
 - Old-fashioned (non-bordered) background image support added, though
   with no support for repeat, etc.
 - Bug fixes for problems revealed by test program
2009-09-20 16:59:06 -04:00
9dbafe156e Makefile.am cleanups for NBTK
Clean up indentation, line up backslashes, and add missing $(AM_V_GEN).
Remove include of GTK+ when generating Nbtk-1.0.gir.
2009-09-20 16:58:30 -04:00
277dd7106a Fix installation and distribution of stylesheet data
Install and distribute gnome-shell.css and theme images. They are moved
down from $datadir to $datadir/theme to avoid a weirdness where we have
images in $datadir and then also in $datadir/images.

(Also moved in the source tree to avoid adding another difference between
installed and uninstalled operation.)
2009-09-18 16:29:28 -04:00
431f299756 Extend distcheck for files in Git to all files
Instead of just checking that we distribute all Javascript files, check
that we distribute everything that is in Git.

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

Remove several stale C files that we are no longer using.
2009-09-18 16:18:54 -04:00
d8d7f5f711 Add some structure for interactive tests of UI components
js/ui/environment.js: Split out initial UI setup (Tweener initialization,
  Nbtk monkey-patching) into a separate file we can import from tests.

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

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

tests/interactive/box-layout.js: A sample test of NbtkLayout
2009-09-18 16:18:50 -04:00
a07af9fb14 Monkey-patch in ClutterContainer methods for NbtkBoxLayout
Setting options for children added to NbtkBoxLayout is not convenient
since we are missing the varargs methods of clutter_container.

Patch in:

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=595419
2009-09-16 19:59:38 -04:00
f1f11f1e76 Add GObject Introspection annotations
Add GObject Introspection annotations to methods where needed, in
particular adding (transfer none) to return values that don't transfer
ownership.

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

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 19:12:53 -04:00
c60a6a49de Import NbtkEntry, NbtkLabel, NbtkClipboard
For now this commit introduces an external dependency on clutter-imcontext.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 18:04:51 -04:00
6687054474 Import NbtkBoxLayout, NbtkBoxLayoutChild
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 17:59:06 -04:00
60819b3a79 Add css for scrolling
Port bits of Nbtk's default.css into gnome-shell.css, and use some
hand-rolled .pngs with colors from
http://live.gnome.org/GnomeShell/DesignerPlayground/ExpandedViewMockups

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 17:58:55 -04:00
3e265b4bc6 Load gnome-shell.css at startup
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 17:56:24 -04:00
e2aa2a00f0 Add a "datadir" property
Will be used to load stylesheets from main.js.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 17:56:24 -04:00
1edc88a2bd Remove hardcoded '28' from NbtkScrollView
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 17:56:22 -04:00
271e4ca07e Import NbtkScrollView and dependencies
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 16:52:26 -04:00
9f79296276 Import nbtk core
Import the core NbtkWidget/NbtkBin and their dependencies.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-09-16 11:35:43 -04:00
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
dfbbf9b436 Bump version to 2.27.1 2009-08-28 20:10:43 -04:00
a230ad9225 Improve the display of search results
Use bigger font and brighter color for the search results section headers.
Add more padding.

Display "(see all)" tooltip in the section headers on mouse-over.
(Still TODO: supressing that tooltip when all results are already being shown.)
2009-08-28 16:26:06 -04:00
7a87474bcd Switch Find entry text size to px
All our font sizes were in px, other than the size for the text in
the search entry. Switch that from 12 to 16px (which is the same size
at the standard 96dpi), it doesn't become out of scale if the DPI
is different. (Using fixed px sizes isn't probably what we want to
do in the long term; moving to style sheets will be a good place to
fix that. But better to be consistent.)

http://bugzilla.gnome.org/show_bug.cgi?id=593212
2009-08-28 16:21:21 -04:00
479acf2d18 Renable PrintScreen and Super_L in the overview
When we are modal, examine keypresses and look for:

 - 'Print': Run the screenshot command in any mode; very useful for
   bug filing, reviews, etc.

 - Release of Super_L/Super_R - if in the overview, toggle back
   out of the overview.

http://bugzilla.gnome.org/show_bug.cgi?id=593427
2009-08-28 15:15:17 -04:00
943c5e2edc Improve comment about button-release-event handler
Improve the documentation about the button-release-event handler
we put on the status-menu button at Colin's suggestion.

http://bugzilla.gnome.org/show_bug.cgi?id=593362
2009-08-28 12:40:56 -04:00
1340413740 Fix hang when clicking on the user status menu in the overview
shell-global.[ch]: Add shell_global_display_is_grabbed() that
  uses the newly added meta_display_get_grab_op() to check
  for existing grabs.
shell-status-menu.[ch]: Add shell_status_menu_is_active() to
  check if the menu is popped up. Check for active grabs before
  popping the menu up. Use gtk_menu_popdown() rather than
  gtk_widget_hide(). Remove an excess gtk_widget_show() and
  some excess casts.
panel.js: Check whether the status menu is popped up after button
  release, and if it's not popped up, unhighlight the button.

Reported by Nuno Donato
http://bugzilla.gnome.org/show_bug.cgi?id=593362
2009-08-28 12:34:04 -04:00
3adec65e20 Remove pre-GNOME-2.26 panel-replacement code
gnome-shell.in: Remove the code to replace gnome-panel by attaching
  to it with GDB; this was always problematical (required gdb, debug
  symbols, finding the pid of gnome-panel, etc.)

gnome-shell-build-setup.sh: Require 2.26 to be in place before building
  the shell; remove gdb from the list of required packages.

http://bugzilla.gnome.org/show_bug.cgi?id=593325
2009-08-28 12:34:04 -04:00
d116f707c5 Clear save_id when removing idle_save_application_usage()
When we remove the timeout for saving application usage when application
usage is disabled, set the save_id member variable to 0.

http://bugzilla.gnome.org/show_bug.cgi?id=589676
2009-08-28 12:34:04 -04:00
6f94b8cffe Change search box text to "Find..."
We want to find more than apps and documents and the previous
string was too long in some languages and on some display sizes.
2009-08-28 11:56:40 -04:00
14a7e310fc Make the gradient on the top panel the same as the "dash"
The previous top color was a bit too bright.
2009-08-28 11:47:19 -04:00
bf680fdc7c New class ShellButtonBox
This is a Box subclass which adds several signals useful for implementing
"button like" behavior, such as hover and pressed states, as well as
click activation on release.
2009-08-27 18:05:41 -04:00
851bf18265 Restore GNOME based on GNOME configuration
Instead of using pidof to find what was running when we started,
and then hacking in a restart with hardcoded paths in /usr/bin,
approximate how GNOME starts the panel and window manager.

This fixes restarting Compiz correctly:
 http://bugzilla.gnome.org/show_bug.cgi?id=593184

And restarting gnome-shell correctly:
 http://bugzilla.gnome.org/show_bug.cgi?id=591171
2009-08-27 15:33:47 -04:00
452e98e3bc Require an explicit --xephyr option
Instead of starting Xephyr automatically, require --xephyr to be
passed explicitly.

This makes the operation easier to understand and has the benefit
of allowing running in Xephyr mode when some other window manager
(like gnome-shell!) is running. We also want to emphasize that
Xephyr is a development tool, and not a good preview of the
user-interface.

http://bugzilla.gnome.org/show_bug.cgi?id=592881
2009-08-27 15:33:47 -04:00
3cb54f6707 Fix allocation implementations for ShellStack and ShellDrawingArea
In both, using our allocation directly for the child is wrong; we
should create a new allocation that's our width and height.

In ShellDrawingArea, also need to chain up to parent.
2009-08-27 13:11:19 -04:00
ed7881d6c9 [AppMonitor] Handle window title changes causing mapping changes
For Firefox/OpenOffice, right now we have a workaround in the
code where we look at their "title" property.  However, we
weren't monitoring that property for changes, and I'm fairly
certain Firefox at least was mapping a window and then very
quickly changing its title after.  So we need to handle
dynamic changes.

Split out the wm_class mapping from the title hack.  It was
messy and weird to have the two mixed because they're not
at all related, and we're not trying to handle WM_CLASS changes
right now.

Explicitly connect to notify::title in the case where we had
a title fallback.  When a title changes, just treat it as
an add+remove.

In the Application Menu area in the panel, hook up to app-added
and app-removed so we get notification of the active app changing.
2009-08-27 02:22:25 -04:00
ea1a45a878 Also remove libtidy-1.0.la from Makefile 2009-08-27 02:18:55 -04:00
003807334b Delete Tidy
It wasn't used any more.
2009-08-27 02:00:23 -04:00
24a5c3c19a Add "mozilla" as a vendor prefix
Clean up the vendor prefix handling a bit, and add "mozilla" so that
we pick up "mozilla-firefox.desktop" from Firefox's (recent?) change
to have a WM_CLASS of "Firefox".
2009-08-27 01:49:15 -04:00
62b2d69c2b Bug 592402 - Better handling of Nautilus window
Separate the application monitor logic for "tracking" and "usage tracking".
The first means we associate an application with a window.  The second
means we count focus time inside that window, and consider the window
interesting from a user point of view.

(Really, should probably split ShellAppMonitor into two classes along
 this line, with the second consuming the first).

For the purposes of counting running applications and returning
the list of open windows for an application, skip not-usage-tracked
windows.

Together this allows us to associate the Nautilus desktop window
with the nautilus.desktop, but not show "File Manager" open all
of the time.
2009-08-27 01:41:25 -04:00
cdbb7f8f5f Display only first page of search results by default and display a total results count
Display only first page of search results by default for each section and
allow clicking on the section header to view all the results for a given
section. This design will allow us to easily move from paging to scrolling
without having to stack multiple scrollbars in a single pane.

Display a total results count next to the section name. This serves as an
indicator that there are more results. The section header pre-lights to
indicate that it can be clicked on.

Make sure we go back to the first page of results when we exit a single
section mode. Make sure we re-instate all result sections if the search
mode is left.

Close the only section search mode on Esc, and only close the search
when Esc is hit again.
2009-08-26 18:46:58 -04:00
ecc1f964c9 Add 'r' as an alias to 'restart' in run dialog
For even faster turnaround inspection of changes.

Also add a comment about the idle_add in the 'lg' command.
2009-08-26 18:43:44 -04:00
0f4e9189c5 Split out "AppIcon" and make WellDisplayItem a subclass of it 2009-08-26 16:28:42 -04:00
799f56fe87 Use new plugin-modality functionality in Mutter
We now have functionality in Mutter to grab the keyboard on behalf
of a plugin. This avoids interactions with the key handling code
in Mutter that could leave the user with an inconsistent state
and no way to get out of it.

src/shell-global.[ch]: Change shell_global_grab_keyboard() and
  shell_global_grab_keyboard() to shell_global_begin_modal()
  shell_global_end_modal() and call mutter_plugin_begin_modal()
  mutter_plugin_end_modal() rather than directly grabbing the
  keyboard.
main.js: Call global.begin_modal/end_modal from Main.startModal()
  and Main.endModal()
altTab.js; Remove call to Main.startModal() - we're letting Mutter
  handle modality for Alt-Tab.
main.js lookingGlass.js overview.js runDialog.js: Rename
  Main.startModal() to Main.beginModal() for consistency with
  naming in mutter and ShellGlobal.

http://bugzilla.gnome.org/show_bug.cgi?id=590686
2009-08-26 14:07:02 -04:00
af9ab5dbb6 Only respawn if gnome-shell exits abnormally
If Mutter exits with an exit status of 0, then that most likely
means that it was replaced by another window manager and we shoudln't
try to start the previous window manager and the panel.

(We don't actually know about the panel, but assume that if someone
is replacing us they know what they are doing.)

When Mutter exits with a signal, we know we want to restart.

When Mutter exits with a non-signal non-zero exit status, it's
ambiguous - we could be exiting because we lost the connection to
the X server, or because of a assertion failure in gnome-shell.
We assume the latter; if the X server is gone, all that will happen
is a bit of noise.

To know why Mutter exited accurately, we always wait() and
kill() the Mutter process, and then, if running in Xephyr, clean up
Xephyr afterwards. This has the nice side effect of exiting when
gnome-shell does and not forcing the user to close Xephyr manually.

http://bugzilla.gnome.org/show_bug.cgi?id=591171
2009-08-25 19:01:42 -04:00
3486fcc89a Updated Swedish translation 2009-08-25 07:48:31 +02:00
1e2018d1b7 Update and improve Dutch translation
Improvements mentioned by Wouter Bolsterlee in gnome-nl-list.
2009-08-24 22:39:53 +02:00
fb46bad665 Add Korean translation 2009-08-23 04:51:56 +09:00
e2d912c037 Added Galician Translation 2009-08-22 16:40:06 +02:00
2879d9cdef Updated Spanish translation 2009-08-22 12:22:25 +02:00
300cefd66a Display search results in the dash
Display search results in the dash instead of showing them in a separate pane.
We get dynamic allocation for the section height based on the number of
results, but a lot of the problems with the previous search results display,
such as displaying empty sections and paging overflow are still present.

Also, we don't yet close the browse pane for applications or documents when
we display the search results and only replace it if we are showing the
details pane, so all that looks weird. We'll need to work out the interaction
for these cases.
2009-08-21 18:21:35 -04:00
72b4d2a234 Make hotCorner a class variable
This fixes a bug where we were already using this._hotCorner
in _onHotCornerEnvironsLeft() and were incorrectly setting
this._hotCornerEntered to false when the hot corner was
re-entered from the environs.
2009-08-21 15:56:07 -04:00
02e438b1f8 Add Dutch (nl) translation 2009-08-21 20:10:13 +02:00
58690c210e [ShellAppSystem] fix missing break; in _unref 2009-08-21 13:19:28 -04:00
61f19a6c22 Added Norwegian bokmål translation. 2009-08-21 12:44:31 +02:00
7465338ea1 [appDisplay] Always relaunch application on drag and drop
Rather than just launching if we weren't already running, always
relaunch, which happens to make Firefox, etc. work.  See
the comment in the commit for more explanation.
2009-08-20 20:03:28 -04:00
9dff05a394 places: Implement drag&drop for overview
Add drag and drop.  We need to be able to recreate the icon texture,
so instead of passing it directly into PlaceDisplay, pass
a factory function which knows how to create a new texture.
2009-08-20 19:37:51 -04:00
9f5a5ad635 appDisplay: Don't leave overview for drag&drop of an app
The design says we stay in the overview for these situations.
2009-08-20 19:37:50 -04:00
2dcd0511c4 dash: Make recent docs display two columns
The design has smaller icons in two columns.  Add a new
custom display to docDisplay for it.

Clean up some of the texture cache handling for recent URIs so
it's not size-dependent, since the dash size is now different
from the default GenericDisplay size.
2009-08-20 19:37:50 -04:00
dd1a309cb6 dnd: Centralize drag actor positioning code, use shellWorkspaceLaunch for workspaces
We had multiple copies of the code to position a drag actor given a particular
source.  Instead, just put it inside dnd.js.

Second, rather than test for GenericDisplay/WellDisplayItem etc.,
in various places, add a new method on each source "shellWorkspaceLaunch"
which both marks the item as being droppable on a workspace, and is
called by the workspaces code to launch the item.
2009-08-20 19:37:50 -04:00
9563515e97 Fixed problem in tr.po file. 2009-08-21 00:45:14 +03:00
ba77c51ee0 Added Turkish (tr) translation. 2009-08-21 00:43:21 +03:00
2e83b95484 Updated Italian translation 2009-08-20 23:30:23 +02:00
756374b2e4 Unmark GdmUser property strings for translation 2009-08-20 18:09:33 +02:00
527ff6fb1d Added Swedish translation 2009-08-20 16:57:28 +02:00
fb4fc496da Updated German translation. 2009-08-20 16:51:19 +02:00
8d9bd87c22 Updated Italian translation 2009-08-20 16:48:37 +02:00
36acb0a63d Added Italian translation
* Added it to LINGUAS
2009-08-20 11:42:39 +02:00
3e0f5aec0c Bug 587951 - Don't show empty categories
When loading menus, skip ones which entirely consist of NoDisplay=true
items.
2009-08-18 23:27:49 -04:00
4f5c3b4b74 Bug 591267 - Fix places icon centering
Pack the place icon in a vertical centering box to avoid the horizontal
box stretching it vertically.
2009-08-18 23:15:57 -04:00
a4bf54e465 ShellAppMonitor: create "applications" for unknown windows
Use MetaGroup for a window when looking up applications.  If
we know the application for a TYPE_NORMAL window in the group,
use that.

However, we aren't always going to know the application for a window.  In
that case, create a fake one.

ShellAppInfo has a "transient" flag so we know not to write these
fake apps to the usage file.

Clean up the idle focus handler to better handle the case where
no window is focused, and where we don't want to track the
particular window.

Update track_window to create the fake window.

When a window goes away, we want to delete the usage.

Rewrite shell_app_monitor_get_running_apps to be based
on the window_to_app hash, because that's what has the pointer
to ShellAppInfo*.  Before we were looking up all ids through
ShellAppSystem, but that shouldn't be holding a ref to transients.

Change the well display icon to be centered, since our icons for
window apps aren't 48 pixels.
2009-08-18 23:07:16 -04:00
d94606587b Add shell_app_system_create_from_window
For various cases such as when we don't know a .desktop file
for a window, it's desirable to "fake" an application from
the contents of a MetaWindow*.
2009-08-18 23:00:47 -04:00
74ea9f9305 Add shell_texture_cache_bind_pixbuf_property
This utility function is targeted for MetaWindow; we can create
a ClutterTexture which tracks the value of an "icon" property.
2009-08-18 22:58:27 -04:00
4dc04d8c53 Update .gitignore for i18n files 2009-08-18 18:19:16 -04:00
6e298759a4 Use g_shell_parse_argv() in run dialog
http://bugzilla.gnome.org/show_bug.cgi?id=581137
2009-08-18 18:17:02 -04:00
3b320de8d7 Updated Polish translation 2009-08-18 23:26:25 +02:00
30d3c1fe72 Use a larger area around the hot corner to decide if the user has left the hot corner
Using a larger area around the hot corner to decide if the user has left the
hot corner prevents triggering the hot corner multiple times due to an
accidental jitter.
2009-08-18 14:59:53 -04:00
7469a2626a Bug 591859 - Use glib/gi18n-lib to get correct gettext package
We need to use the -lib variant which in turn uses the
GETTEXT_PACKAGE define, because the default translation
domain is actually mutter, not gnome-shell.
2009-08-17 08:53:59 -04:00
d534597589 Add a po/POTFILES.skip with gnome-shell.desktop.in
It's generated from the .in.in.
2009-08-17 08:47:29 -04:00
ec3c8464d3 Updated Spanish translation 2009-08-16 16:23:35 +02:00
6319f649c2 Some search appearance fixes for last commit
Add a close-black.svg.  Add some padding around the content.
Fix magnifier.svg to be 18 pixels wide.
2009-08-16 10:09:34 -04:00
44d34aba19 Highlight the search entry when the user clicks or starts typing in it
This will give the user a visual indication that the search is active.

We need to replace the gray close button in the search entry with a black one.
2009-08-15 16:40:59 -04:00
4245c573df Clean up our .typelib generation rules
- Prepend to the LD_LIBRARY_PATH not append
- Use $(G_IR_COMPILER) instead of g-ir-compiler
- Use $(AM_V_GEN)
2009-08-15 10:17:36 -04:00
c27b6493d6 autoconf-2.64 compat: Don't use $(builddir)
$(builddir) is not a standard automake variable. With autoconf < 2.64
it ends up getting set in every Makefile.in to '.' (because autoconf
defines it), but that is no longer the case for 2.64.

Since $(builddir) was always '.', just use that instead.
2009-08-15 10:17:35 -04:00
7200207009 Initial Czech translation 2009-08-15 15:35:32 +02:00
9ba66fd800 Remove whitespace so l10n.gnome.org is happy 2009-08-15 14:49:48 +02:00
e4552fca40 Updated Irish translation 2009-08-15 06:01:33 -06:00
b7d892e4c6 Added Spanish translation 2009-08-15 12:53:00 +02:00
5b096be68b Added es to LINGUAS 2009-08-15 12:51:29 +02:00
e843d11566 Added missing files to POTFILES.in 2009-08-15 12:43:09 +02:00
9c7803030e Added Irish translation 2009-08-15 04:24:19 -06:00
67ef36ef8e Hungarian translation added 2009-08-15 11:37:06 +02:00
4c1614f6a5 added hu to LINGUAS 2009-08-15 11:36:42 +02:00
3766784799 Pass foreign option to automake
We don't want a ChangeLog file.  NEWS maybe.
2009-08-14 20:02:07 -04:00
56e16ef712 Add Catalan translation. 2009-08-15 00:14:28 +02:00
559c313fc7 Fix untranslatable string: "Find apps or documents" 2009-08-15 00:13:55 +02:00
5e10d56d89 Added Brazilian Portuguese translation. 2009-08-14 18:11:00 -04:00
d289ce6aca Updated German translation. 2009-08-14 23:43:27 +02:00
c68e69bd6e 2009-08-14 Hendrik Brandt <heb@gnome-de.org>
* Update LINGUAS, add de
2009-08-14 20:42:51 +02:00
a6f312cfd3 2009-08-14 Hendrik Brandt <heb@gnome-de.org>
* po/de.po: Initial German translation.
2009-08-14 20:40:16 +02:00
ca51a8c926 Add initial calls to Gettext
We don't have a lot of strings, and what ones we do have we've
been avoiding duplication.  This patch adds calls to _() i.e. gettext
for those strings we do have.
2009-08-14 09:32:15 -04:00
ec95a1c2d3 Add test fr translation
Useful to verify that translation infrastructure is working.
2009-08-14 09:32:12 -04:00
a418558b73 Add localization
Infrastructure for localization; hook up intltool, create po/
and po/POTFILES.in.  We need to call bindtextdomain/bind_textdomain_codeset.

Switch to gnome-autogen.sh to call intltool.
2009-08-14 09:14:34 -04:00
f097304f3b Bug 582763 - Remove maximization effects
The maximize effect looked really ugly.  In the absence of any cooler
effects, none at all is better than what we have.  Current compiz
doesn't have one either.

Note that in the future when we merge the frame into the panel
in the maximize case, we may want an effect for that.
2009-08-14 08:41:00 -04:00
ea4ea4a9b2 Disable sidebar by default
The sidebar is a bit neglected currently; we'll revisit it when
we have more design and code time to focus on it.
2009-08-13 22:51:16 -04:00
b94452ee42 Redo highlight-drawing logic slightly, as suggested by Owen 2009-08-13 13:51:48 -04:00
51db34d223 Implement distinct 2-window and multi-window highlights 2009-08-13 13:19:24 -04:00
059c330d95 Clear _searchTimeoutId when removing search
When we remove the search because the search empty is
entry, we need to reset _searchTimeoutId to 0.

http://bugzilla.gnome.org/show_bug.cgi?id=591719
2009-08-13 13:15:02 -04:00
557f9ceb97 Bug 591590 - Fix some applications not appearing in menu
Use the correct address for the entry, instead of treating the
ShellAppInfo pointer as one.
2009-08-13 13:02:29 -04:00
4aae57c274 Explicitly set the size of the workspace actors
Instead of counting on the implicit sizing of ClutterGroup, which isn't
going to work well because of current limitations of ClutterClone, set
the size of workspace explicitly based on the screen size.

This should fix various problems with drag-and-drop being unreliable;
if a workspace was sized to big it could overlap other workspaces or
elements of the overview.

http://bugzilla.gnome.org/show_bug.cgi?id=591643
2009-08-13 08:50:05 -04:00
fb0ca1ba9d Make dragging an item to the Add Workspace button launch it on a new workspace
It is convenient to drag an item to the Add Workspace button and
have it be launched on a new workspace.

Based on a patch from Josh Adams.
2009-08-12 20:13:24 -04:00
51723bb93b Bug 591626 - Fix crash in ShellAppMonitor
Pass application into signal as expected.  Be sure to reference
it across the call, since removal from the hash unrefs it.
2009-08-12 19:45:17 -04:00
1e41f869de Bug 591624 - dash: Rename searchId to searchTimeoutId
From review comments.
2009-08-12 19:37:47 -04:00
28517e4c34 places: Use consistent variable for bookmark monitor timeout
We had an inconsistent usage of the timeout variable name.  Fix
it to consistently be a member property of this.
2009-08-12 19:34:02 -04:00
619066780f dash: Clean up search pane creation
There was some weirdness relating to when the search pane is shown
in a timeout, and how that relates to setSearch.  Instead of doing
this in the timeout, just call setSearch() in the timeout.  The
pane hide/show state is directly controlled from the handler.
2009-08-12 19:33:08 -04:00
1636e6c187 dash: Don't expand displayControl
It shouldn't take up more space than it needs.
2009-08-12 19:32:50 -04:00
d17c94f9b9 Initialize ShellAppMonitor/ShellAppSystem at predicatable time
Currently ShellAppMonitor relies on all the .desktop files being
loaded.  We should initialize it very early to ensure that anything
that uses it has up-to-date information right away.
2009-08-12 17:10:17 -04:00
4b47803162 Implement the multi-window highlight on WellDisplayItem 2009-08-12 17:08:19 -04:00
15a3f39f65 Add finer-grained signals to ShellAppMonitor, update appDisplay 2009-08-12 17:08:19 -04:00
f7d85e618c Bug591246 - Minor code-cosmetic fixes
Missed these two in original commit.
2009-08-12 16:33:39 -04:00
f00500d3d5 Bug 591246 - Move towards shell-black02 mockup
Remove the last use of passing width into Dash by having the
Pane with the previews scaling dynamically and relying on
Clutter scaling.

If we only have one workspace, don't display a selection frame
for it.

Rework Dash into a searchArea and sectionArea, which get
explicitly sized by overlay.js.  We use the workspaces size
to choose the size of those dash areas.

Switch dash colors/boxes etc. to ones from shell-black02.

Add a gradient to the panel.

Add a magnifier.svg for use in search.
2009-08-12 16:07:05 -04:00
25a5da074c ShellTextureCache: Don't try to scale pixbuf to 0 size
If we pass in -1 for both width and height, we'd attempt
to scale the image to 0x0.  Don't do that; just avoid
scaling the pixbuf and let ClutterTexture do it for us.
2009-08-12 15:56:43 -04:00
43d737c663 Ensure dash is raised over workspaces
Having the workspace actor on top of the dash broke drag and drop.
2009-08-12 15:12:55 -04:00
789e24b59a ShellAppMonitor: Correctly handle transients
If looking up the application for a transient window, try look up
its transient source.  Ignore transients for the purposes of counting
open windows.
2009-08-12 10:10:19 -04:00
b51bcf3e2b Catch exception trying to create a preview of an unknown image type 2009-08-12 01:30:58 +02:00
babb13f603 Remove unused button width and height arguments and specify button height explicitly
minWidth and minHeight arguments of the Button class were not used.

Panel buttons need their height to be explicitly specified as
PANEL_HEIGHT to take up full panel height. This fixes the problem with the
user not being able to click at the very top edge of the panel to activate
the button.
2009-08-11 18:16:33 -04:00
21ef33df65 Replace libgnomegnomeui with gnome-desktop in gnome-shell-build-setup.sh
With the recent switch to use libgnome-desktop for thumbnailing instead
of libngomeui, we should require that instead.

(Updated for Debian/Ubuntu, Fedora, OpenSuSE, unable to figure out
the right name for Mandriva in a quick web search.)
2009-08-11 16:39:43 -04:00
83b1cedb86 Use distinct filenames for all code generation tempories
Because of a history of cut and paste, the different enumeration
and marshal generation generation shell snippets were using the
same temporary file names. This caused problems for parallel
builds.

http://bugzilla.gnome.org/show_bug.cgi?id=591474
2009-08-11 16:05:31 -04:00
36ee36283a ShellAppMonitor: Add static to definition of sequence_ref 2009-08-11 13:35:08 -04:00
74eac21870 Add application menu area to panel
This is a start at the "Active Appliction Item" component of the
shell design.  Currently we just show the currently focused
application.  When launching a new application, we show that as well.

The implementation here is not complete; basically when launching
we de-focus the active one, and the application well shows the
most recent startup sequence.

This kind of fails in the case of multiple sequences, and we
also don't correctly de-focus the current window in other
launch paths.
2009-08-11 13:09:41 -04:00
e330c5ea17 panel: Switch to fully dynamic layout
There was lots of fixed positioning in the Panel; now it is completely
dynamic, and width/height is driven from main.js.  We still have a
global constant Panel.PANEL_HEIGHT, but this is a big step towards
eliminating it.

Also, this avoids overdraw in the "way too many tray icons" case.  The
clock will shift left.
2009-08-11 13:08:19 -04:00
e6644b7feb Use GnomeDesktopThumbnailFactory instead of GnomeThumbnailFactory
http://bugzilla.gnome.org/show_bug.cgi?id=591008
2009-08-11 11:27:52 -04:00
47af454115 Bug 591437 - Rename overlay.js to overview.js
Replace 'overlay' with the more descriptive name 'overview'
where the Activities Overview is meant. Call it Overview
(capitalized) in code comments.

The overlay-group and overlay-key provided by Mutter are not
affected, since they may be used for other components than
the Activities Overview.
2009-08-11 15:15:25 +02:00
1f31e80c47 Bug 584609 - Zoom the whole overlay when showing or hiding
Instead of only transforming the active workspace, create a
zooming effect when showing or hiding the overlay. This makes
the transitions simpler: the workspaces are now fixed to the
overlay actor group and will not slide over the Dash.

overlay.js: Add zoom animations, fade in/out Dash during those,
    remove obsolete Dash clipping and stacking logic, add public
    get[Scale|Position]() and getZoomedIn[Scale|Position]()
    functions.
workspaces.js: Remove zoom animations, add fade animations for
    the remove button, add helper functions for the overlay
    zooming, keep the movement of windows linear to that of
    their workspaces, remove the updatePosition() and
    updateInOverlay() functions and fullSize variables that
    were left from the old overlay design.
2009-08-11 02:21:13 +02:00
b0c7dac56b Distribute places.js
Add places.js to the Makefile.am
2009-08-10 18:36:54 -04:00
e5aa67421d Fix distcheck-hook for missing distributed JS files
Use git ls-files not git-ls-files, since git-ls-files is no longer
on the path with Git 1.6
2009-08-10 18:18:29 -04:00
fdd50f09dd Don't dist gnome-shell.in
We only want to include gnome-shell.in.in in the tarball. If we
include gnome-shell.in, then it won't be regenerated, and paths
won't be correct for the install location.
2009-08-10 18:02:41 -04:00
26a074588b Bug 591114 - Remove expanded background
The "expanded background" that is behind the workspaces etc. in the overview
should be removed.  It isn't in the designs, it is distracting, and it breaks
the overview metaphor.

At least temporarily, just make the background of the overview black.
Change the pane popup to black as well, but keep a blue border so that
it is visually distinguished from the background.

Based on a patch by Colin Walters, with fixes from  Marina Zhurakhinskaya.
2009-08-10 17:25:05 -04:00
00cc32d95a Ignore clicks on hot corner during transition
It's both intuitive to go to the corner of the screen
and click the activities button at the same time.

Both actions bring up the overlay,  but combined
they cancel each other out.  This commit makes
clicking the hot corner not cancel the act of
going to the hot corner.

Based on a patch from Ray Strode.
2009-08-10 14:19:07 -04:00
df8f727bba Add .desktop file to .gitignore 2009-08-10 13:57:40 -04:00
de8084ed40 Specify the clutter-1.0 branch of Clutter
For now, we want to stick to the stable branch of clutter rather
than tracking new developments. Now that Clutter has branched for
1.0 switch our moduleset to the clutter-1.0 branch.
2009-08-10 12:13:09 -04:00
9fa88caded Bug 591316 - Fix bad notify:: parameters
We weren't using them, and they were wrong.
2009-08-10 11:18:19 -04:00
06d17e08c0 Reposition windows when scaling workspaces
The scale of windows within a workspace is determined by the
scale of the workspace since we never scale a window bigger
than the original size of the window. So when we rescale
workspaces we have to rerun Workspace.positionWindows().

http://bugzilla.gnome.org/show_bug.cgi?id=591124
2009-08-10 10:09:25 -04:00
4830808d2f When fading in window icons, use the final position not current position
The onComplete when positioning windows may come before the
final stage of the workspace positioning animation. So we can't
use actor.get_transformed_position() to figure out where to put
the icons. Compute the final position manually ourselves instead.

http://bugzilla.gnome.org/show_bug.cgi?id=591123
2009-08-10 09:59:40 -04:00
02ee6f69b3 Fix updating of workspace frame actor
Both the position and size of the frame actor depend on the scale
of the workspace, so update them both when the scale changes.

On the other hand, the the frame actor doesn't need to be
repositioned when the workspace moves (since it is relative to the
workspace). We do base the frame  position of the desktop actor, but
that will presumably stay fixed (at 0,0) in most all cases.

http://bugzilla.gnome.org/show_bug.cgi?id=591122
2009-08-10 09:56:35 -04:00
5d0808e1c0 Use the size of the window, not of the clone to position windows
When Workspace._positionWindows is called, the clone might nto
yet have its final size (because of the clone is is a clone of
the window texture and the window texture isn't updated until
right before painting.) So get the size from the MetaWindow
instead ... the MetaWindow size is determined synchronously when
the window is managed.

http://bugzilla.gnome.org/show_bug.cgi?id=590741
2009-08-10 09:54:38 -04:00
1f864fba7f Show bookmarks with spaces in the name correctly
Take everything in the ~/.gtk-bookmark lines after the URI
as label, not only the first word. (eg. if there's a line like
"file:///home/rainct/Ubuntu%20One Ubuntu One", now "Ubuntu One"
is taken as the label, instead of only "Ubuntu").
2009-08-09 19:19:07 +02:00
cc83aee401 Show "Network" item on Ubuntu
If gnome-network-scheme.desktop can't be found, look for
network-scheme.desktop (which is used, for example, on
Ubuntu).
2009-08-09 19:00:00 +02:00
185ccecec1 Make <AppSystem>.load_from_desktop_file() raise an exception again
Pass the error variable to g_key_file_load_from_data_dirs in
Shell.AppSystem.get_default().load_from_desktop_file again, and
use a try/catch in places.js.
2009-08-09 18:32:22 +02:00
f96193dc8c Thumbnail generation without GtkRecentlyUsed in TextureCache
This fixes Shell.TextureCache.get_default().load_thumbnail so
that it can be used to get thumbnails (with an icon matching
the mimetype or, in the worst case, gtk-file, as fallback) for
items which don't have a GtkRecentlyUsed object. This is needed
for the Zeitgeist integration.
2009-08-09 17:46:21 +02:00
205c57d6af Fix FTBFS and crash triggered by <AppSystem>.load_from_desktop_file()
- Avoid error '"iconname" may be used uninitialized in this function'
  by initializing said variable to NULL.

- Define shell_util_get_file_description as static (like the other
  similar functions) to avoid another compiler error.

- Don't save errors from g_key_file_load_from_data_dirs into the
  variable "error" (ie. pass NULL to it instead). Without this,
  gnome-shell crashes if the key file can't be found (with message
  "Error invoking Shell.load_from_desktop_file: Valid key file could
  not be found in search dirs").

- Check the result of the load_from_desktop_file() call in places.js,
  as it may be null.
2009-08-09 17:39:17 +02:00
5c97d21889 Fix comment header for shell_texture_cache_load_uri 2009-08-09 09:53:06 -04:00
e323593f4a Add Places
Implement the Places mockup.  This commit adds a link to Home,
Network, Connect to server, and the GTK+ bookmarks.
2009-08-09 09:53:06 -04:00
3bae3fa203 Add shell-uri-util.[ch]; functions ported from gnome-panel for URIs
These two functions are useful for the Places implementation to
get name/icon for a desktop-related URI such as Documents or
Downloads.
2009-08-09 09:53:06 -04:00
9bd22dc033 ShellAppSystem: Support loading a .desktop file directly
Previously, ShellAppSystem only loaded (and cached) the set of
.desktop files from applications.menu and settings.menu, using
the gnome-menus library.  The ShellAppInfo structure was
a "hidden typedef" for GMenuTreeEntry.

But we need to support loading an arbitrary .desktop file.  Thus,
refactor the ShellAppInfo into a real struct, with a refcount,
and allow it to point to either a GMenuTreeEntry or a GKeyFile.

Also, in the case where we fail to lookup an icon for an
application, ensure we return a 0 opacity texture.
2009-08-09 09:53:06 -04:00
5064d873bb Add shell_texture_cache_load_from_name
Utility function to load a texture for a themed icon from a
string name.
2009-08-09 09:53:05 -04:00
4495f98dce Fix negative height request in WellGrid
When WellGrid had no child it was doing a division by zero,
which screwed up the calculation for the height request and
having it ask for a negative number. This commit fixes this
by always requesting 0 in this case.
2009-08-09 03:34:35 +02:00
5a75b44f71 Consider height when positioning windows in the overlay
I've done some little modifications to the window positioning code
used in the overlay so that it considers the height of the windows
and they don't overlap or get out of the workspace.

I've also raised the hard-coded scales a bit to have the windows as
big as possible without overlapping (this could use some testing on
a non-widescreen monitor).
2009-08-08 22:10:40 +02:00
ebd6f4bc8f appDisplay: Reimplement well layout to be width-independent
Use ShellGenericContainer to implement a fully dynamic layout
for the application well.  It's still fixed to 4 columns by default,
but no longer requires a fixed width to be passed in on start.

With another chunk of work, it could likely try to adjust to
the case where we can only fit fewer than 4 items in the well.

Remove the border highlighting on mouseover, since that caused
reallocations, and the grid layout isn't trivial.

Delete the unused shell_global_get_word_with function.
2009-08-08 15:47:49 -04:00
687a87d3d0 Define stable ordering for application favorites and running apps
For both of these, because of optimizations a few patches ago, we
ended up relying on hash table ordering which caused instability
in the application well among other things. Define an ordering
for both.

The favorites is just the order of the GConf keys, and new items
get appended.  In the future we should allow insertion at any
point which the grid could use.

For running applications order, define a new "initially_seen_sequence"
transient variable which is just an monotonically incrementing
integer assigned to an application for the first time we saw it
running in this session.  When an application is closed, it's reset.
2009-08-08 15:47:49 -04:00
464842ea36 Change to $HOME before launching gnome-panel again
When exiting from --replace mode, we want to start the new
gnome-panel with a reasonable working directory so that if, you say,
open a terminal from it it doesn't start off in the gnome-shell
directory.

(gnome-shell itself is running in $HOME because mutter changes
directory itself at startup.)

Reported by Mathieu Bridon
http://bugzilla.gnome.org/show_bug.cgi?id=591145
2009-08-08 12:51:01 -04:00
91911da302 Bug 590985 - Fix frequent apps list being empty
We shouldn't append .desktop again, that was a leftover from
the old WM_CLASS based application code.
2009-08-08 11:57:09 -04:00
3c87d76741 dnd: Fix used of undefined variables
The variables this._yOffset and this._xOffset are included in the
drop coordinates, but as far as I can tell never defined.  Looking
back on the commit that introduced this code, they weren't removed
from anywhere else either.

The drop coordinates seem correct without them, so just delete them.
2009-08-08 10:09:30 -04:00
ccafa53bd6 Enable hot corner for triggering the overview mode
Use the 1x1 actor in the top left corner of the screen to enter and leave
the overview mode by just moving the mouse over to it.

No delay is used for triggering the hot corner because a delay significant
enough to allow moving away the mouse to avoid triggering it ruins the desired
flow when triggering the hot corner is actually intended.

The hot corner is not enabled in the full screen mode because the application
or the virtual system might have a hot corner of its own in that place.
2009-08-07 16:45:35 -04:00
4e23f4cfc9 Bug 591077 - Hide overlay when activating an application
It's easier to explicitly call Main.overlay.hide() instead
of chaining activation signals, this got lost in a mix between
the big dash rewrite and ongoing changes to the Application well.
2009-08-07 15:45:52 -04:00
544a80fc6e Add a desktop file for gnome-shell
Add a desktop file for GNOME Shell. This allows making GNOME Shell
your desktop default by adding it to your auto-start items.

http://bugzilla.gnome.org/show_bug.cgi?id=591089
2009-08-07 14:13:24 -04:00
4d52c10958 Bug 589316 - Add application/window icon to overlay windows
To better distinguish between vast fields of white of which many
windows are composed, add the application icon to the bottom
right of the window.

We fade them in to avoid an abrupt feel.  The icons are in the
workspaces group, not individual workspace groups to avoid
having to adjust them when we scale the workspaces.

Replace Workspace._lookupIndexAndClone with Workspace.lookupIndex,
and make the caller go from index to clone, or clone and index.
2009-08-07 13:29:34 -04:00
c23b9ee192 dnd: Emit drag-end in after snapback complete
Emit the signal at the correct time to take action
on snapback (i.e. after the end of the snapback animation).

Add a boolean to the drag-end signal saying whether it was accepted,
which ensures consumers know whether the drag was successful.
2009-08-07 13:29:34 -04:00
296e0c2054 Remove residual references to libXScrnSaver in required packages
See 5527fa2bc3. Now that we don't use it at all, no need to install the package either.
2009-08-07 15:28:05 +02:00
5527fa2bc3 Remove residual references to libXScrnSaver
Now that we are no longer using the screen saver X extension, remove the check
for the .pc file and the include of the header file.
2009-08-06 18:30:47 -04:00
59532ab0c7 Check the result of fgets() to deal with warn_unused_result
Some C library versions have __attribute__((warn_unused_result)) on
fgets(). We really don't care since we are just throwing the data
away, but check the result anyways.
2009-08-06 17:59:20 -04:00
ad5a9d8f8b Turn on "silent-rules" for automake >= 1.11
When AM_SILENT_RULES is available, use it to strip down the output
of make so we can see what's important rather than gigantic long
compile lines.

Use 'make V=1' to see everything again.

Fix a couple of places where we had 'cmp' rather than 'cmp' and were
getting standard-error spew about missing files when generating
enum-types.h files.

http://bugzilla.gnome.org/show_bug.cgi?id=591002
2009-08-06 16:58:40 -04:00
d243634602 Fix compiler warnings
src/shell-global.c src/shell-process.c: Remove dead code
src/shell-texture-cache.c src/shell-status-menu.c: Remove
  <foo>_new() functions that weren't in the header file and
  not used anyways:
src/shell-texture-cache.[ch]: Fix a prototype that used ()
  when (void) was intended.

http://bugzilla.gnome.org/show_bug.cgi?id=590998
2009-08-06 16:46:55 -04:00
e89d3c7b07 Turn on -Werror and -Wmissing-prototypes
When compiling with GCC turn on -Wmissing-prototypes, and by default
turn on -Werror as well.

As with most gnome modules:

 --enable-compile-warnings=minimum/maximum

Can be used to disable -Werror (they are the same)

http://bugzilla.gnome.org/show_bug.cgi?id=590998
2009-08-06 16:46:55 -04:00
354112fb41 Tweak sizing of windows in overview
Tweak arrangements with 2,3,4,5 windows in a desktop so:

 - Windows are a bit bigger
 - All windows for 5 windows are equally sized instead of making
   the windows in the bottom row larger

This does cause some more problems with tall windows overlapping
or running off the edge of the workspace, but it's an overall
small improvement to the behavior.
2009-08-06 15:19:04 -04:00
f7746ec3f6 Initialize GStreamer from shell_recorder_init()
Move the GStreamer initialization from the Javascript code into
shell_recorder_init(). This avoids a dependency on the GStreamer
introspection information and will make it easier to drop the
gir-repository module dependency.
2009-08-06 15:19:04 -04:00
03e0fe1e95 Replace _getIndexOfDisplayedActor with a function in OverflowList
Said function in genericDisplay.js was returning the index of the
actor based upon its position in the entire list, while everywhere
else indexes relative to the currently displayed page were used.

This made actions in the details pane break (bug #590949), so I
replace it with a new function in shell-overflow-list.c,
shell_overflow_list_get_actor_index, which is page based.
2009-08-06 19:51:11 +02:00
22c98e6240 Fix incorrect variable name: mimeType -> this.mimeType. 2009-08-06 17:25:58 +02:00
90979faedd ShellAppMonitor: Fix case of not seeing apps being closed
Remove the app from the window_to_app hash *before* emitting
CHANGED, otherwise a signal handler could see stale data.
2009-08-05 20:13:44 -04:00
21858d928a Clear text in the run dialog when it's hidden with escape 2009-08-06 02:04:04 +02:00
be95ca553a Fix indentation issues in altTab.js, plus minor cleanup in some other files. 2009-08-06 01:54:22 +02:00
c4b4248707 Bug 589086 - Fix non-integer positioning in altTab
Non-integer makes fonts look awful.  Fix this by rounding
down.
2009-08-05 11:43:54 -04:00
91353c6d60 Add ShellGenericContainer, which makes it possible to write containers in JS
Subclass ClutterGroup (to avoid having to implement all of dispose,
raise, lower, add, etc.), and have it proxy the allocation requests
out into signals.  We have to group up the two out parameters
into a struct unfortunately.

Included example code in the C file source for now.
2009-08-05 11:36:33 -04:00
31851cbc32 Install missing svg files. #590814 2009-08-05 08:59:57 -04:00
41f6e8ef86 Add dash.js to js/ui/Makefile.am. #590813 2009-08-05 08:58:35 -04:00
85b4b97b7b Rewrite Dash, remove hardcoded width/height from GenericDisplay
This patch is a near-total rewrite of the Dash.  First, the dash
code moves into a separate file, dash.js.

Inside dash.js, the components are more broken up into separate
classes; in particular there's now a Pane class and a MoreLink
class.  Instead of each section of the dash, when activated,
attempting to close all N-1 other sections, instead there
is the concept of a single "active pane", and when e.g. activating
the More link for documents, if we know there's an active pane
which happens to be the apps, close it.

Many redundant containers were removed from the dash, and all
manual width, height and x/y offsets are entirely gone.  We move
the visual apperance closer to the design by using the view-more.svg,
etc.

To complete the removal of height/width calculations from the dash,
we also had to do the same for GenericDisplay.  Also clean up
the positioning inside overlay.js so calculation of children's
positioning is inside a single function that flows from screen.width
and screen.height, so in the future we can stop passing the width
into the Dash constructor and call this once and work on screen
resizing.
2009-08-05 04:04:27 -04:00
2726fdb831 Bug 588343 - Major rework of window monitoring to be application-based
The previous application monitoring code was originally designed
to be based on WM_CLASS, which was then resolved on a server.
We have that resolution code locally now, so instead
of saving WM_CLASS data, save application IDs.

Also, inside the WM we have a much better
infrastructure for tracking windows.  In particular, rather
than polling, we can just watch for focus notification on
the display, and window add/remove.

Instead of polling XScreensaver, use DBus to watch org.gnome.Session
which already has an idle time watch.

Now there is no polling at all inside the monitor.
2009-08-04 18:40:37 -04:00
b1150eb147 Bug 589276 - Use 0 opacity while loading textures, preserve aspect ratio by default
When we fail to load a texture, make sure we keep it 0 opacity to avoid
a white square.  Also this is useful to avoid the square while loading
a texture asynchronously.
2009-08-04 16:48:12 -04:00
898d76af53 lookingGlass: Add hierarchy list and property inspector
Add a Notebook class which we then use to pack in separate Hierarchy
and Properties tabs.

Split out the inspector into its own class to avoid bloat in the
main class.
2009-08-04 11:12:02 -04:00
7c26303b25 lookingGlass: Add to Makefile.am
Signed-off-by: Colin Walters <walters@verbum.org>
2009-08-04 10:01:06 -04:00
902956ca0d lookingGlass: Draw a red border around target actor 2009-08-04 09:55:52 -04:00
3429abff40 lookingGlass: Faster history save, avoid empty lines
5 seconds is should help ensure we lose work less often on
Alt-f2 restart.

Avoid saving empty lines to history, and filter them out if
we find them.

Minor fixes for the still-not-enabled inspector.
2009-08-04 09:55:46 -04:00
61b28c5c7d Adjust tray spacing to cope with many icons
This patch attempts to adjust if we have many tray icons; currently
the simple algorithm is to drop down to a spacing of 8 if we have
more than 6.  In the future we should fix the panel layout so that
the clock moves to the side.
2009-08-03 20:42:00 -04:00
e84e842c1e Fix 'redeclaration of global' error in lookingGlass.js. 2009-08-04 02:36:53 +02:00
0792f8d4a3 lookingGlass: Fix spacing and line appearance 2009-08-03 20:21:07 -04:00
52ae75d4b8 LookingGlass - JavaScript prompt and interactive Clutter controller
Add a dropdown pane triggered by Alt-F2, "lg" which supports interactive
JavaScript evaluation, saving/restoring a history file, as well as
an inspector element to pick by using the mouse.
2009-08-03 20:17:08 -04:00
224538c885 Cleanups for runDialog
Using an internal boolean rather than the visibility property seems
more reliable to me.  Add a list of internal functions rather than
an if/else chain, so for example an extension could hook something on.

Delete the javascript evaluator in favor of the upcoming lookingGlass.js.
2009-08-03 20:16:15 -04:00
45dc34bfa2 Add mesa-utils to build-setup.sh for Debian/Utils
At least on Ubuntu 9.04 and Debian Squeeze, glxinfo is in the
mesa-utils package, so pull that in.

Reported by Flamarion Jorge
http://bugzilla.gnome.org/show_bug.cgi?id=590480
2009-08-03 15:14:53 -04:00
0b801a0d2d Fix the amount of fitting elements calculation in the OverflowList
Before this in certain conditions (depending on the available
height) two items could be drawn in the same position. Bug #590278.
2009-08-02 20:06:32 +02:00
d7f5fd5d24 Give the runDialog a rounded corner
Just makes things a bit nicer looking.
2009-08-01 21:46:02 -04:00
026f014d32 Bug 589937 - Raise clone on window activation
We had duplicate code in appDisplay and workspaces for handling activating
a window; unify that inside workspaces, add an API to Main.overlay to
access it from both contexts.

Also, explicitly raise the clone we're activating to the top
before starting the animation to leave the overlay.
2009-07-31 19:26:32 -04:00
a439a58f13 Remove taskpanel
The new design doesn't have the task panel at the bottom; remove it.

Signed-off-by: Colin Walters <walters@verbum.org>
2009-07-31 17:42:49 -04:00
29ffa46d08 Move drawing functions from shell-global into new shell-drawing.c file
Just to avoid shell-global.c bloat.
2009-07-31 17:26:47 -04:00
0a1aac862f Fix details pane repositioning
Two calls to _repositionDetails() were done too early,
before the visibility of the results pane had changed,
so they had no effect. Thus when a search was done while
a details pane was active, the pane with the results was
hidden by the details pane.

In addition to fixing this, move the two remaining calls to
the line after changing the results pane's visibility
to make it clearer why the calls are there.
2009-07-31 16:12:19 +02:00
f7fff83647 Fix showing small item previews
Don't use a clone of an actor that's not part of the scene graph for the
item previews. This patch fixes previews in the details pane for documents
for which we don't have full previews and for applications.

Use create_icon_texture() from AppInfo instead of looking up the file
for gicon when creating an application icon for the details pane.
2009-07-29 17:56:13 -04:00
66e48da7cb Bug 589260 - Don't replace panel in Xephyr mode
Avoid grabbing the org.gnome.Panel name if we're running in
Xephyr, since that affects the main desktop.
2009-07-29 17:47:34 -04:00
93ea4b07c1 Add appInfo.get_desktop_file_path method
Add shell_app_info_get_desktop_file_path, matching *_get_executable,
*_get_id, etc. This is useful for Zeitgeist.
2009-07-29 23:40:23 +02:00
77c92d75d5 Toggle the info pane when clicking the info icon (#587550)
Now clicking on the information icon of the same item a second
time will hide the details pane. Clicking it another time will
show it again, etc.

This is achieved by adding a 'toggle-details' signal which
switches the visibility of the details pane.

Other than the necessary changes, function _selectIndex (in
genericDisplay.js) has been restructured a bit to avoid
duplicating checks.
2009-07-29 19:35:11 +02:00
119516424d Update to using Clutter 1.0
Change the pkg-config and .gir requirements.
2009-07-29 13:00:41 -04:00
f3efbf432f Replace lastVisited method in DocInfo with timestamp attribute
This is not only more consistent with the name, uri and
mimeType attributes, but makes adding Zeitgeist support easier.
2009-07-29 10:52:33 +02:00
04538c65b5 Changed logout menu to include Log Out and Shutdown options, #583955 2009-07-27 23:28:00 -04:00
efcf8bae9d Align category labels vertically
Add a box to contain the MenuItem labels and align them vertically.

Clean up the style in the MenuItem code.
2009-07-27 19:02:46 -04:00
adfb419ceb Don't line wrap application names in wells, fix running alignment
The experiment with avoiding ellipsization was a definite failure;
several translations have very long names, and we'd end up
with a single column.

Also fix extra padding; we only want some space at the top, not
left/right.
2009-07-27 18:35:41 -04:00
09948ce033 Remove unused gdm-user-chooser-*.[ch] files
These widgets aren't currently used, delete them for now.
2009-07-27 17:23:32 -04:00
ff6ee2c0c2 DocsWidget -> RecentDocsWidget
Rename DocsWidget to RecentDocsWidget (as widgets for most used docs,
docs related to the currently open documents, etc. may be added in the
future), and change the title so that it doesn't abbreviate 'Docs' (for
consistency with the overlay).
2009-07-27 14:50:54 -04:00
96cf9c739e Avoid ellipsizing app names; Draw glow around running
Corresponding with the design, if an application is in a running
state (has > 0 windows open), draw a glow behind the name.

To make the display look a bit nicer, set the width of each item
to be equal to the longest word among all the items.
2009-07-27 12:45:22 -04:00
9f4ccb83e3 Make dash background darker
Make dash background darker so that the blue color used for indicating
running apps can be visible. Use the dark blue (almost black) color from
Jeremy's mockup.

Make the dash height be the full screen height minus the height of the panel.
Don't use padding on top or on the bottom.

Remove the border from the main dash, but leave it for the results and details
panes. Make the border slightly transparent.

Make sure the details pane is correctly positioned by not applying the
additional padding when determining its x position.
2009-07-24 17:25:20 -04:00
978ab8a4dd Return false from the timeout callback function
Timeout callback function should not be rescheduled again with the same timeout
because we compute a new timeout and schedule it again instead. So the callback
function needs to return false to not be scheduled again by default.
2009-07-24 12:58:53 -04:00
2cc650e389 Bug 589437 - Switch to workspace of target app to activate
The user explicitly selected a window, so take them to it.
2009-07-23 12:28:31 -04:00
f24169735a Fix updating last visited time for the doc display items.
Make sure that we calculate the next update time correctly.

Store timeout time instead of the timeout delta, so that it doesn't get outdated.

Create a new callback when the time update happens for the original callback.

Make sure last visited time is updated in the details pane by keeping track
of the description actors created for the detail actors.

Add comments to the new functions.
2009-07-22 18:57:05 -04:00
75c875f073 Fix time updating for recent files 2009-07-22 12:46:05 -04:00
6ea2822fa3 Merge branch 'bug589185-docinfo-time' 2009-07-22 12:11:06 -04:00
b4cf178cc5 Display last visited time as docInfo description
It's useful information, and takes up some of the blank space.
2009-07-21 23:05:08 -04:00
a7c1ff3729 Fix prototype for shell_app_monitor_get_window_app
It contained a stale definition for the old version of _id, it
now returns the app.
2009-07-21 21:27:56 -04:00
fdd9b85448 If org.gnome.Panel exists on the bus, replace it rather than using gdb
Avoid depending on gdb for replacing an existing panel, since it
requires debuginfo and gdb installed.

Instead we grab the org.gnome.Panel DBus name, using DBus name
replacement semantics.
2009-07-21 13:29:49 -04:00
e12587619b Fix reference counting of textures loaded via _load_uri_sync
Avoid double unref, fixes image previews.
2009-07-20 18:23:03 -04:00
8d9fc28872 Bug 588050 - Cache information icon forever, only look up recent once
Extend ShellTextureCache by adding the concept of a policy, which
we expose to the public API for loading URIs.

This lets us have the shell tell the cache to keep the information
icon texture around forever.

Secondly, fix the caching of recent info; we shouldn't always be
loading the backup pixbuf.  Move recent info loading entirely
into ShellTextureCache.
2009-07-17 17:35:53 -04:00
2c5d520395 Fix srcdir != builddir issue when installing schemeas
Since we aren't (currently) generating our GConf schemas by merging in
.po files, the schemas file is in sourcedir not builddir.
2009-07-17 13:14:35 -04:00
9e85d197fd Bug 588462 - Use a plain black panel with a different layout
The semi-transparent gradient on the panel is replaced by a
solid black background. The shadow below the panel is removed.
The clock is put at the center instead of the right side of
the panel and has the date removed. The user icon is hidden.
Instead of boldface, a regular font is used. Padding is added
on each side and between panel elements.

button.js: Allow for custom text colors and fonts.
panel.js: Change the panel colors and layout, remove the shadow.
2009-07-16 22:02:32 +02:00
2aea9c59a4 Bug 588173 - No remove button on the first workspace
If there is only one workspace and it's empty, it should
not get a remove button. Add a workspaceNum != 0 check to
workspaces.js.
2009-07-14 14:58:24 +02:00
001af72727 Merge branch 'bug588050-doc-textures' 2009-07-13 16:24:55 -04:00
9d594d7f26 Always clear details pane when unsetting more mode
We don't want a detail pane hanging around for an item no
longer visible.
2009-07-13 11:01:50 -04:00
2161e90cda Fixes for GenericDisplay
GenericDisplay wasn't quite completely converted to the ShellOverflowList
model.  Since the list now holds all actors, the indexing/wrapping
was incorrect.

Add a property which lets us keep track of how many items are displayed,
use this in genericDisplay.

Avoid setting selectedIndex to -2 when going up with no items.

If we're not displaying any results at all, don't attempt keynav (for now).
2009-07-13 11:01:49 -04:00
f7a82d6400 Bug 588445 - Use BigBox vertical alignment for the clock
panel.js: Replace the manual vertical padding calculation
    for the panel's clock with an y_align property on its
    BigBox container.
2009-07-13 16:16:44 +02:00
10e30f7dc7 Bug 588405 - Handle status menu button appearance in JavaScript
Make the ClutterText and ClutterTexture from the status menu
button available to JavaScript, and from there improve the
font definition of the user name.

shell-status-menu.[ch]: Add public get_name() and get_icon()
    functions that return the user name label and icon
    texture, remove the markup from update_name_text().
panel.js: Set the font for the button consistently with that
    of the other panel labels.
2009-07-13 13:54:38 +02:00
177edc5444 Bug 587955 - Small cleanups to iconButton
Missing trailing ; after "this._fadeOut()". A few missing spaces after "if". Parameter inconsistently named "icon" instead of "texture".
2009-07-11 18:44:21 +02:00
b45cd0a4eb Small fixes for sidebar application bits
We need to set the .name property, also skip unknown apps.
2009-07-10 17:04:39 -04:00
8a56b990dd Bug 587949 - Handle locale-encoded names from struct pwent
Convert to utf8 internally.
2009-07-10 10:19:17 -04:00
f353283a40 Merge up to commit 92e608bd0f3807314c45ee5f5daf6ba781c27d58 of gdm
Pull in a few fixes from gdm trunk for gdm-user.c
2009-07-10 10:19:17 -04:00
5d067ec718 Better caching for document textures and information
Move thumbnail creation into ShellTextureCache.  It's now asynchronous,
and we cache the result.

Create a DocManager class which keeps around the DocInfo objects between
invocations.  This is also where we ensure we remove thumbnails for
recent items not known anymore.
2009-07-09 13:58:45 -04:00
1cb6fc004b Add magic "js " prefix to runDialog to run arbitrary JavaScript
This is useful for debugging things; e.g. you can "js Meta.quit(0)"
to exit the WM, "js Shell.Global.get().<whatever>..." etc.
2009-07-08 17:30:09 -04:00
3b603ef7e0 Don't fail if we can't find an application
Instead of logging and passing null through, explicitly skip
apps we don't know about.  It's valid to have say uninstalled
an app.
2009-07-08 11:54:15 -04:00
0971ba54b8 Bug 587952 - Immediately fade in information button
0.5s is a pretty long time, start immediate fade in.
2009-07-08 11:41:40 -04:00
c136acc879 Remove inadvertent early return in apps search 2009-07-08 11:38:22 -04:00
cc2d3fd56d Major rework of application data structures and caching
Before, we looked up application data in several ways; the ShellAppSystem
exported just application ids (though it parsed the .desktop files internally),
and we'd create a Gio.DesktopAppInfo object (reparsing the desktop file again),
wrapping that inside a JavaScript AppInfo class, and finally the AppDisplay
would again parse the .desktop file to get the categories.

Also, to look up applications by id previously, we traversed the entire
menu structure each time.

Some qualities such as the NoDisplay flag were not easily exposed in the old
system.  And if we wanted to expose them we'd have to change several different
application information wrapper classes.

All in all, it was quite suboptimal.

The theme of this new code is basically "just use libgnome-menus".  We do
not call into Gio for app lookups anymore.  The new Shell.AppInfo class
is a disguised pointer for the GMenuTreeEntry item.

To fix the caching, we keep a simple hash table of desktop id -> ShellAppInfo.
2009-07-08 11:33:47 -04:00
72e6e7839f Reset page number when changing the active category 2009-07-07 11:59:51 +01:00
732573331a Fix DND to left side of the screen
Set the size of the Dash actor to 0x0 so that it doesn't
interfere with drag and drop.

http://bugzilla.gnome.org/show_bug.cgi?id=587899
2009-07-07 10:58:49 +01:00
00407d6971 Explicitly include gio/gio.h in ShellGlobal
Because we use GFile.
2009-07-06 23:13:58 -04:00
db630b2945 More for applications now displays a category list
Rework the previously extant Application category code to display
in the expanded list.  Add a "Frequent" category which corresponds
to the most_used_apps, and selected by default.

Instead of adding the background and shadow as expanded items to
the results/details panes as fixed, we slave the background/shadow
sizes to the results using notify::allocation.

Also clean up the code for sizing the details pane, using a common
function which adjusts its x position in one place.
2009-07-06 16:15:12 -04:00
a15ee28177 Add ShellDrawingArea and ShellStack
ShellDrawingArea is a size-independent wrapper for a ClutterCairoTexture.
Useful when drawing non-fixed size areas.

ShellStack is a simple container class which holds items
in a completely overlapping Z stack.  The main difference
from ClutterGroup is that items will be constrained to
(and allocated) the size of the stack, not getting their
preferred size always.
2009-07-06 14:11:18 -04:00
92e9bc85a1 AppWell: If an application is running, activate an existing window
Instead of relaunching, pick the first window and activate
2009-07-06 13:43:19 -04:00
70c51beeeb Add a sidebar show/hide menu item to the status menu
This is how it is in the mockups, but we may want to revisit it
2009-07-06 11:55:17 -04:00
9890887126 Add GConf schemas for sidebar prefs, and use those prefs from sidebar.js 2009-07-06 11:55:17 -04:00
203ec385c5 Add ShellGConf
Although methods like gconf_client_get/set_bool() and such are usable
from gjs, get_list/set_list is not, since there's only one method for
all list types. So ShellGConf wraps GConfClient and adds separate
typed list methods.

Also, add a detailed "changed" signal that can easily be connected to
from js, since we can't currently use gconf_client_notify_add()
directly.
2009-07-06 11:55:17 -04:00
5a0d8eca9f Fix Chrome.removeActor()
The split between this.actor and this.nonOverlayActor in chrome.js is
annoying, but aside from actually subclassing ClutterGroup (which
would have to be done from C), all of the other possibilities are
annoying too.
2009-07-06 11:55:17 -04:00
ae779c7f20 Fixes to allow widgets to be initially collapsed 2009-07-06 11:55:16 -04:00
3852176e80 Use a fading icon button in genericDisplay
Add a new icon button in button.js that fades in/out with a short delay when the mouse enters/leaves its parent. Use it for the information button of genericDisplay.
2009-07-05 10:40:50 +02:00
7a0ce6c57b ShellOverflowList: Implement pick
This gives us the correct event behavior.
2009-07-04 19:50:55 -04:00
15e862f974 Switch GenericDisplay to ShellOverflowList for dynamic height
This converts GenericDisplay to totally dynamic layout, where
we display as many items as we can, and the rest cleanly overflow
into pages.

For now, remove multi-column; to readd this, we can pack multiple
display items into a single ShellOverflowList item.
2009-07-04 15:30:12 -04:00
a1908d9db1 Add ShellOverflowList, a dynamic list with paging
This container class will be used for GenericDisplay.
2009-07-04 15:29:51 -04:00
8ee740e425 Don't include NoDisplay items, except for window identification
Searching across NoDisplay desktop items can produce weird
results to the user (including duplicates, and items that
aren't really applications at all.) So, don't include them
normally.

But continue including NoDisplay items when we look up the
desktop file for a window, since we want to catch applications
like Evince and Nautilus which are otherwise NoDisplay.

http://bugzilla.gnome.org/show_bug.cgi?id=587548
2009-07-04 15:07:10 +01:00
f44b3e0553 Hide the running-apps area when empty
It looks funny to have the "more running apps area" there as a gap
when empty and dragging to it is an unintuitive way to remove stuff
from the favorites list, in any case, so just hide the area when
empty.

http://bugzilla.gnome.org/show_bug.cgi?id=587720
2009-07-04 14:19:25 +01:00
bddcb40237 Fix expand flags for the contents of the Dash
Pack everything we don't want to expand with BigBoxPackFlags.NONE;
this fixes the More... button for the docs section ending up with
a gap underneath it.

Since the More... button for the docs now ends is right at the bottom
of the dash, add some padding to it.

http://bugzilla.gnome.org/show_bug.cgi?id=587720
2009-07-04 14:16:57 +01:00
66ea19fbfb Switch to dynamic layout for Dash
Instead of laying out the dash contents "manually" and having
the content items explicitly passed their height, just give them
a set width.
2009-07-04 13:45:27 +01:00
e9966b4aff Add partial implementation of dynamic width/height layout to TidyGrid
This is not a complete patch; it doesn't attempt to handle the homogenous
property or column major.

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

http://bugzilla.gnome.org/show_bug.cgi?id=587720
2009-07-04 13:45:27 +01:00
a71ae65f8b Allow dragging a Workspace.WindowClone into favorites well
It's a natural thing to do, though in the future we may want
to split the WindowClone into js/misc/window.js or the like.
2009-07-02 05:04:33 -04:00
96a2747e0b Wire up search up/down
This is not a complete fix; the search selection will not cross
the apps/docs boundary.  But it's good enough until we have a more
final search design.
2009-07-02 01:04:40 -04:00
8ef48ca33c Animate panel appearance on startup 2009-07-02 01:04:40 -04:00
8a0cebccdc Display full application title, allow DnD from More
For now display the full application name, centered to avoid
excessive ellipsization.

Highlight on mouseover, and allow DnD from the More display.
2009-07-02 01:04:40 -04:00
5ae6239344 SuSE needs xorg-x11-proto-devel for X11 screen saver extension header
libXScrnSaver-devel was a Mandriva package, not available on SuSE.
2009-07-02 00:37:05 +02:00
aaeb980688 Add info.svg to Makefile.am 2009-07-01 13:43:27 -04:00
77c325772a fix tag name in schema 2009-07-01 10:34:24 -04:00
2eb0d20221 Make the sidebar's horizontal padding symmetric
Widgets should be horizontally centered in the sidebar. Else they look
out of place (in particular the clock and the applications widgets).
Due to little tricks with the sidebar starting out of the screen to
hide rounded corners, this implies playing with paddings. The patch
decreases the widgets padding from 4 to 2 pixels, removes additionnal
padding on the right, and adds an out-of-screen padding to the widget
box to make up for the negative horizontal position of the sidebar.
2009-07-01 09:28:03 -04:00
454ca09575 Make individual dash panes reactive instead of making the dash Group actor reactive
The width of a Group actor ends up including the width of its hidden children,
so we were getting a reactive object as wide as the details pane that was
blocking the clicks to the workspaces underneath it even when the details
pane was actually hidden.

Not making the dash Group actor reactive solves this problem. However, we
have to make individual parts of the dash reactive instead so that the clicks
are not passed to the transparent actor underneath them. That transparent
actor is used for dismissing the additional panes when the user clicks over
the workspaces area.
2009-06-30 19:45:56 -04:00
8f0bf5deae Fix double free and under-dup in ShellAppMonitor
The hash table is keeping ownership of appid, we don't need
to free it again.  However we do need to re-dup it when we
insert as a key.
2009-06-30 18:16:39 -04:00
09d9d91297 Include NoDisplay applications in application data
For now, we want to get Evince and Nautilus at least in the application
list.
2009-06-30 18:16:39 -04:00
a5e3227b64 Set GCONF_DEFAULT_SOURCE_PATH from the gnome-shell wrapper script
Needed so that a jhbuilt gnome-shell can find its schemas at runtime
2009-06-30 17:29:40 -04:00
8a790e1c38 Fix schema install 2009-06-30 17:29:20 -04:00
db52e024e8 Use a separate icon image as a drag actor instead of using the clone of the icon
Clutter no longer allows using a clone of an actor that is not a part of
the scene graph. This is what used to happen when we created a clone for
the icon of the item that was being dragged, and then closed the More panes
with the original item, removing the icon from the scene graph. This was
also when happened when the user hit Esc while dragging, which prompted the
overlay to close, removing the original icon from the scene graph.

Rename getIcon() methods to createIcon() to better reflect on the fact that
a new icon is created each time the method is called (we do use cache in
some cases).

Remove a stray log message in overlay.js

Fixes http://bugzilla.gnome.org/show_bug.cgi?id=585490
and http://bugzilla.gnome.org/show_bug.cgi?id=585489
2009-06-30 16:42:00 -04:00
79c166c38d Make workspaces accept a drop of AppDisplay.WellDisplayItem
AppDispplay.WellDisplayItem needed to be added along with the
GenericDisplay.GenericDisplayItem as a type of a drop object
that workspaces accept.
2009-06-30 16:42:00 -04:00
04fbaf4f27 Avoid duplicating most used applications in the AppDisplay cache
All used applications should be in the database from the menus
anyways.
2009-06-30 16:42:00 -04:00
b92263e80c Fix invalid function signature and a memory leak
Add the missing GParamSpec to on_n_workspaces_changed.

Also, we don't need to re-dup the appid, since it's already dup'd.
2009-06-30 16:42:00 -04:00
12f78a08cd Replace Dash application display with AppWell
The new class AppWell implements the application favorite well
in the Dash component.  The previous AppDisplay remains for use
in the More... mode now.

Delete DEFAULT_APPLICATIONS; this is now in GConf.

Rename getMostUsedApps to getTopApps since we now have the
idea of explicit favorites.

Delete some GenericDisplay-related calls from overlay related
to the seletion - we'll reimplement keyboard nav in a more
coherent way later.
2009-06-30 16:41:54 -04:00
88c9a23866 ShellAppSystem: Add favorites API and shell_app_system_lookup_basename
Add a GConf key for favorites, and API for retrieving them.

Also add shell_app_system_lookup_basename, which we use from
the app monitor to look up WM_CLASS ids.
2009-06-30 16:35:16 -04:00
94f92072c2 ShellAppMonitor now always assocates windows with desktop files
Track all windows; at the time of opening (and shell startup)
we call into ShellAppSystem to take the WM_CLASS property and
try to find an associated .desktop file.

Add mozilla-firefox to the list of our WM_CLASS workarounds.

Add shell_global_get_screen, since it's often used.
2009-06-30 16:20:24 -04:00
5ca4b41063 Use a single ItemResults class instead of AppResults and DocResults
AppResults and DocResults classes were identical with an exception of
the display class they used and the text label for the results. Merged
them into a single ItemResults class that takes these two additional
arguments.
2009-06-30 15:38:18 -04:00
45c97862e5 Move the activate and select functionality inside the callbacks
Move the activate and select functionality inside the callbacks for
'button-release-event' signals of the display item and the information
button correspondingly. This way it is more obvious that this is an
event handling code that needs to return a boolean value for whether
the signal has been fully handled by the actor.
2009-06-30 15:38:18 -04:00
3a7447dacc Use TextureCache to load the information icon
Use TextureCache to load the information icon, so that we don't create a
new ClutterTexture for information icons corresponding to each display
item.
2009-06-30 15:38:18 -04:00
dc7b2b03e1 Make sure we show the information button when a new item appears under the pointer
Update the code for checking a display item under the pointer to expect
the item itself rather than its child to be returned by stage_get_actor_at_pos().

This code is now used to display an information button when an item is
drawn under the pointer, so update the comment accordingly.
2009-06-30 15:38:18 -04:00
8b15724c2a Show and hide dash panes instead of adding and removing each time
Add results and details panes up-front, and show and hide them instead
of adding and removing them each time
2009-06-30 15:38:17 -04:00
587f04f807 Add a comment about the use of the transparent background and set its opacity to 0
Add a comment about the use of the transparent background to catch clicks
in the workspaces area when the dash panes are being displayed and dismiss
the dash panes.

Set opacity for the background to 0 instead of using a transparent background
color so that Clutter optimizes the drawing of the background actor.
2009-06-30 15:38:17 -04:00
9faf161aae Fix up horizontal gradient code and its use
Fix up the comments about the horizontal gradient code and use 8x1 texture
instead of 8x8.

Make sure the values we assign to the three-stop horizontal gradient
require the use of the three stop gradient, with the middle value not being
right between the side values.
2009-06-30 15:38:17 -04:00
3b56807e78 Display search results automatically
Display a pane with search results for both applications and documents
automatically when a search string is entered.

Allow viewing search results for the individual section when More link
for applications or documents is clicked.

Move text labels for the applications and documents sections into the
respective classes.
2009-06-30 15:38:17 -04:00
d5882c0cd3 Add back search functionality
Enable typing in the search box and display results in the results pane.
This means that the user has to open the details pane for applications
or documents to view the results for now.

Connect Enter to launch the seleted item.

Connect Escape to clear search, remove results and details panes,
or exit overlay.
2009-06-30 15:38:17 -04:00
c92268a615 Hide details panel by default
Don't show the details panel when the overlay is activated,
only when explicitly requested by clicking the info icon.
2009-06-30 15:38:17 -04:00
e1fa61cd58 Fix the height allocated to the results sections
The results sections no longer include a label on top of them, so the
height of that label needs to be subtracted when specifying the height
for the sections. This ensures that display controls are positioned
correctly on the bottom of the section.
2009-06-30 15:38:17 -04:00
98c5f35324 Select an item when information button is clicked, launch on single click
Clicking the information button for an item selects it (i.e. highlights it)
and shows details about the item.
Clicking the rest of the item area launches it.
Item does not become draggable if the dragging is started over the information
icon (i.e. if the user presses the information icon, but releases elsewhere).

Make sure we emit "activated" signal and close the overlay when an item from
one of the results displays is launched.
2009-06-30 15:38:17 -04:00
3841e8da74 Add an icon for the information link
Use an (i) icon supplied by Jeremy for the information link and display
it on hover. Make sure it is positioned nicely and the text doesn't
overlap with it.
2009-06-30 15:38:17 -04:00
e3291aa5ba Remove pop-up previews
Pop-up previews are not part of the new design and interfere with the information link.

Make sure details display for applications has the appropriate width set.
2009-06-30 15:38:17 -04:00
fab13dbb89 Make sure at most one item is selected in the overlay
Make sure at most one item is selected in the overlay and we always show
a details pane for the selected item.

Improve the positioning of the search box.

Remove a duplicate variable DASH_PAD and use DASH_SECTION_PADDING everywhere instead.
2009-06-30 15:38:17 -04:00
c0c79e59fc Split out separate AppResults, DocResults classes. Readd search as stub.
Avoid bloating the Dash class by separating out a bit more functionality.
2009-06-30 15:38:17 -04:00
90b7d9a7fa Change selected item color and make sure only one item is selected at a time
A blue selected item color fits better with the new color scheme than a green one.

Only one item should be selected across all the displays we are showing.
2009-06-30 15:38:17 -04:00
662c995515 Display a pane with item details
Display a pane with item details, such as a full image previews, when an item is single clicked.

Add a placeholder information link that shows up when an item is moused over.
2009-06-30 15:38:16 -04:00
3c54893656 Add icons from Jeremy
These icons are for the "more", "close", and "info" images in the overlay.
2009-06-30 15:38:16 -04:00
580794f3fb Display all recent documents in the results pane
Display all recent documents in the results pane, in addition to the first
few displayed in the main dash. All documents can be viewed with the help
of a paging control.
2009-06-30 15:38:16 -04:00
1154a1e8d7 Add a results pane in the overlay
Display the results pane above the workspaces. The results pane is somewhat
transparent and has a blue gradient background. The dash pane is slightly
transparent and also has a blue gradient background.

The results pane shows up when a More control is clicked. It disappears when
a Less control is clicked, an area outside of the dash area is clicked,
an item starts being dragged, or the overlay mode is exited.

Add shell_global_create_horizontal_gradient() to shell-global.[ch]
2009-06-30 15:38:16 -04:00
837683004d Remove a lot of obsolete code from old Sideshow (now Dash) 2009-06-30 15:38:16 -04:00
14bb73220b Increase priority of region-updating idle
Increase the priority of the idle for updating work area and struts
to META_PRIORITY_BEFORE_REDRAW. This prevents it from being starved
by a constantly-redrawing client.

http://bugzilla.gnome.org/show_bug.cgi?id=585500
2009-06-29 15:11:51 -04:00
f1a9ada5f0 Improve postioning of status menu
Currently we position the user status menu at the upper left of
the user status button. Then, because Mutter is inappropriately
positioning override-redirect windows it get shoved into the
workarea. Once that bug is fixed (bug 582639), we'll have to
position the menu ourselves.

This patch aligns the user status menu at the left end of
and beneath the top panel.

http://bugzilla.gnome.org/show_bug.cgi?id=586156
2009-06-29 15:11:51 -04:00
185 changed files with 34240 additions and 6709 deletions

13
.gitignore vendored
View File

@ -16,7 +16,17 @@ config.log
config.status
config
configure
data/gnome-shell.desktop
data/gnome-shell.desktop.in
intltool-extract.in
intltool-merge.in
intltool-update.in
libtool
omf.make
po/*.gmo
po/Makefile.in.in
po/POTFILES
po/stamp-it
scripts/launcher.pyc
src/*.gir
src/*.typelib
@ -28,4 +38,7 @@ src/gnomeshell-taskpanel
src/gnome-shell
src/test-recorder
src/test-recorder.ogg
src/test-theme
stamp-h1
tests/run-test.sh
xmldocs.make

View File

@ -1,13 +1,22 @@
SUBDIRS = data js src
SUBDIRS = data js src tests po
EXTRA_DIST = \
.project \
.settings
.settings \
autogen.sh
# These are files checked into Git that we don't want to distribute
DIST_EXCLUDE = \
.gitignore \
gnome-shell.doap \
MAINTAINERS \
tools/build/*
distcheck-hook:
@echo "Checking disted javascript against files in git"
@echo "Checking disted files against files in git"
@failed=false; \
for f in `cd $(srcdir) && git-ls-files js` ; do \
exclude=`(for p in $(DIST_EXCLUDE) ; do echo --exclude=$$p ; done)`; \
for f in `cd $(srcdir) && git ls-files $$exclude` ; do \
if ! test -e $(distdir)/$$f ; then \
echo File missing from distribution: $$f ; \
failed=true ; \

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,8 +1,22 @@
#!/bin/sh
#!/bin/bash
# Run this to generate all the initial makefiles, etc.
(cd `dirname $0`;
touch ChangeLog NEWS &&
autoreconf --install --symlink &&
autoreconf &&
./configure --enable-maintainer-mode $@
)
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gnome-shell"
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
echo " top-level gnome-shell directory"
exit 1
}
which gnome-autogen.sh || {
echo "You need to install gnome-common from GNOME Subversion (or from"
echo "your OS vendor's package manager)."
exit 1
}
USE_GNOME2_MACROS=1 USE_COMMON_DOC_BUILD=yes . gnome-autogen.sh

View File

@ -1,10 +1,12 @@
AC_INIT(gnome-shell, 0.0.1)
AC_INIT(gnome-shell, 2.27.3)
AC_CONFIG_AUX_DIR(config)
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AC_CONFIG_HEADERS(config.h)
AC_DISABLE_STATIC
@ -20,8 +22,16 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
PKG_PROG_PKG_CONFIG(0.16)
IT_PROG_INTLTOOL(0.26)
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
@ -33,23 +43,25 @@ if $PKG_CONFIG --exists gstreamer-0.10 '>=' $GSTREAMER_MIN_VERSION ; then
AC_MSG_RESULT(yes)
build_recorder=true
recorder_modules="gstreamer-0.10 gstreamer-base-0.10 xfixes"
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-0.9)
PKG_CHECK_MODULES(TEST_SHELL_RECORDER, $recorder_modules clutter-1.0)
else
AC_MSG_RESULT(no)
fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
PKG_CHECK_MODULES(MUTTER_PLUGIN, gtk+-2.0 dbus-glib-1 mutter-plugins gjs-gi-1.0 xscrnsaver libgnome-menu $recorder_modules gconf-2.0 gdk-x11-2.0 clutter-x11-0.9 clutter-glx-0.9)
PKG_CHECK_MODULES(TIDY, clutter-0.9)
PKG_CHECK_MODULES(BIG, clutter-0.9 gtk+-2.0 librsvg-2.0)
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(MUTTER_PLUGIN, gio-unix-2.0 gtk+-2.0 dbus-glib-1 mutter-plugins
gjs-gi-1.0 libgnome-menu $recorder_modules gconf-2.0
gdk-x11-2.0 clutter-x11-1.0 clutter-glx-1.0
gnome-desktop-2.0 >= 2.26 libstartup-notification-1.0
gobject-introspection-1.0 >= 0.6.5)
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(NBTK, clutter-1.0 gtk+-2.0 clutter-imcontext-0.1)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
PKG_CHECK_MODULES(TOOLKIT, clutter-1.0 libcroco-0.6)
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
PKG_CHECK_MODULES(TASKPANEL, libwnck-1.0 dbus-glib-1)
# We require libgnomeui for generating thumbnails for recent files with GnomeThumbnailFactory.
# We'll switch to using GnomeDesktopThumbnailFactory once the branch of gnome-desktop that contains
# it becomes stable.
PKG_CHECK_MODULES(LIBGNOMEUI, libgnomeui-2.0)
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
# FIXME: metacity-plugins.pc should point directly to its .gir file
@ -80,17 +92,31 @@ AC_SUBST(GIRDIR)
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
AC_SUBST(TYPELIBDIR)
changequote(,)dnl
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
[Turn on compiler warnings]),,
enable_compile_warnings=error)
case " $OBJCFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) OBJCFLAGS="$OBJCFLAGS -Wall" ;;
esac
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
if test "$enable_compile_warnings" = error ; then
case " $CFLAGS " in
*[\ \ ]-Werror[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Werror" ;;
esac
fi
fi
fi
changequote([,])dnl
@ -104,4 +130,6 @@ AC_OUTPUT([
js/misc/Makefile
js/ui/Makefile
src/Makefile
tests/Makefile
po/Makefile.in
])

View File

@ -1,14 +1,48 @@
imagedir = $(pkgdatadir)/images
desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop
dist_image_DATA = \
add-workspace.svg \
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
gnome-shell.desktop.in: gnome-shell.desktop.in.in
$(AM_V_GEN) sed -e "s|@bindir[@]|$(bindir)|" \
-e "s|@VERSION[@]|$(VERSION)|" \
$< > $@ || rm $@
# Placeholder until we add intltool
gnome-shell.desktop: gnome-shell.desktop.in
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
imagesdir = $(pkgdatadir)/images
dist_images_DATA = \
add-workspace.svg \
app-well-glow.png \
back.svg \
close.svg \
close-black.svg \
info.svg \
magnifier.svg \
remove-workspace.svg
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
theme/gnome-shell.css \
theme/scroll-button-down.png \
theme/scroll-button-down-hover.png \
theme/scroll-button-up.png \
theme/scroll-button-up-hover.png \
theme/scroll-vhandle.png
schemadir = @GCONF_SCHEMA_FILE_DIR@
schema_DATA = gnome-shell.schemas
install-data-local:
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(top_builddir)/data/$(schema_DATA)
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA)
EXTRA_DIST = \
EXTRA_DIST = \
gnome-shell.desktop.in.in \
$(schema_DATA)
CLEANFILES = \
gnome-shell.desktop.in \
$(desktop_DATA)

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

66
data/close-black.svg Normal file
View File

@ -0,0 +1,66 @@
<?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.1"
id="Foreground"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46+devel"
sodipodi:docname="close-black.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
id="metadata2399"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs2397"><linearGradient
id="linearGradient3173"><stop
style="stop-color:#c4c4c4;stop-opacity:1;"
offset="0"
id="stop3175" /><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3177" /></linearGradient><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective2401" /></defs><sodipodi:namedview
inkscape:window-height="811"
inkscape:window-width="1272"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
showgrid="false"
inkscape:zoom="32.125"
inkscape:cx="8"
inkscape:cy="10.440056"
inkscape:window-x="40"
inkscape:window-y="40"
inkscape:current-layer="Foreground" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10.5,3.5l2,2L10,8l2.5,2.5l-2,2L8,10l-2.5,2.5l-2-2L6,8L3.5,5.5l2-2L8,6L10.5,3.5 z M0,8c0-4.418,3.582-8,8-8s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
id="path2394"
style="fill-opacity:1;fill:#000000" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

74
data/close.svg Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Foreground"
x="0px"
y="0px"
width="16px"
height="16px"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="x_circle_16.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
id="metadata2399"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs2397"><linearGradient
id="linearGradient3173"><stop
style="stop-color:#c4c4c4;stop-opacity:1;"
offset="0"
id="stop3175" /><stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="1"
id="stop3177" /></linearGradient><inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 8 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="16 : 8 : 1"
inkscape:persp3d-origin="8 : 5.3333333 : 1"
id="perspective2401" /><linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3173"
id="linearGradient3179"
x1="7.844358"
y1="16"
x2="7.7198443"
y2="-0.062256809"
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
inkscape:window-height="713"
inkscape:window-width="1197"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
showgrid="false"
inkscape:zoom="32.125"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="40"
inkscape:window-y="40"
inkscape:current-layer="Foreground" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10.5,3.5l2,2L10,8l2.5,2.5l-2,2L8,10l-2.5,2.5l-2-2L6,8L3.5,5.5l2-2L8,6L10.5,3.5 z M0,8c0-4.418,3.582-8,8-8s8,3.582,8,8s-3.582,8-8,8S0,12.418,0,8z"
id="path2394"
style="fill-opacity:1;fill:url(#linearGradient3179)" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,15 @@
[Desktop Entry]
Type=Application
_Name=GNOME Shell
_Comment=Window management and application launching
Exec=@bindir@/gnome-shell
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-shell
X-GNOME-Bugzilla-Component=general
X-GNOME-Bugzilla-Version=@VERSION@
Categories=GNOME;GTK;Utility;Core;
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-Phase=WindowManager
X-GNOME-Provides=panel;windowmanager;
X-GNOME-Autostart-Notify=true

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>
@ -15,6 +30,64 @@
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/favorite_apps</key>
<applyto>/desktop/gnome/shell/favorite_apps</applyto>
<owner>gnome-shell</owner>
<type>list</type>
<list_type>string</list_type>
<default>[mozilla-firefox.desktop,evolution.desktop,openoffice.org-writer.desktop]</default>
<locale name="C">
<short>List of desktop file IDs for favorite applications</short>
<long>
The applications corresponding to these identifiers will be displayed in the favorites area.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/visible</key>
<applyto>/desktop/gnome/shell/sidebar/visible</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>false</default>
<locale name="C">
<short>Whether or not to display the sidebar</short>
<long>
Determines whether or not the sidebar is visible.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/expanded</key>
<applyto>/desktop/gnome/shell/sidebar/expanded</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Whether the sidebar should be in the expanded (wide) mode</short>
<long>
Controls the expanded/collapsed state of the sidebar.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/widgets</key>
<applyto>/desktop/gnome/shell/sidebar/widgets</applyto>
<owner>gnome-shell</owner>
<type>list</type>
<list_type>string</list_type>
<default>[imports.ui.widget.ClockWidget,imports.ui.widget.AppsWidget,imports.ui.widget.RecentDocsWidget]</default>
<locale name="C">
<short>The widgets to display in the sidebar</short>
<long>
The widgets to display in the sidebar, in order from top to bottom. Each widget "name" is actually a JavaScript expression referring to a widget constructor object.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>
</gconfschemafile>

74
data/info.svg Normal file
View File

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

After

Width:  |  Height:  |  Size: 2.5 KiB

80
data/magnifier.svg Normal file
View File

@ -0,0 +1,80 @@
<?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="18"
height="18"
viewBox="0 0 18 18"
enable-background="new 0 0 29 18"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46+devel"
sodipodi:docname="magnifier.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="9.5844061"
inkscape:cy="9.4435574"
inkscape:window-x="142"
inkscape:window-y="26"
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>
<g
id="g5"
style="fill:#ffffff;fill-opacity:1"
transform="translate(-4,-0.023114)">
<path
d="m 6.246,13.98 c -0.319,-0.319 -0.319,-0.837 0,-1.157 L 9.963,9.106 c 0.319,-0.319 0.837,-0.319 1.157,0 l 0.786,0.787 c 0.32,0.319 0.32,0.837 0,1.157 l -3.717,3.717 c -0.32,0.319 -0.838,0.319 -1.157,0 l -0.786,-0.787 0,0 z"
id="path7"
style="fill:#ffffff;fill-opacity:1" />
<path
d="M 9.076,11.937"
id="path9"
style="fill:#ffffff;fill-opacity:1" />
</g>
<path
clip-rule="evenodd"
d="m 7.25,7.476886 c 0,-1.243 1.007,-2.25 2.2499998,-2.25 1.2430002,0 2.2500002,1.007 2.2500002,2.25 0,1.243 -1.007,2.25 -2.2500002,2.25 C 8.257,9.726886 7.25,8.719886 7.25,7.476886 z m -2.25,0 c 0,-2.485 2.015,-4.5 4.4999998,-4.5 2.4850002,0 4.5000002,2.015 4.5000002,4.5 0,2.4849998 -2.015,4.5 -4.5000002,4.5 C 7.015,11.976886 5,9.9618858 5,7.476886 z"
id="path11"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd" />
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,97 @@
/* Copyright 2009, Red Hat, Inc.
*
* Portions adapted from NBTK's data/style/default.css
* Copyright 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
NbtkScrollBar
{
background-color: #354761;
padding: 0px;
}
NbtkScrollView
{
scrollbar-width: 16px;
scrollbar-height: 16px;
}
NbtkButton#up-stepper
{
border-image: url("scroll-button-up.png") 5;
}
NbtkButton#up-stepper:hover,
NbtkButton#up-stepper:active
{
border-image: url("scroll-button-up-hover.png") 5;
}
NbtkButton#down-stepper
{
border-image: url("scroll-button-down.png") 5;
}
NbtkButton#down-stepper:hover,
NbtkButton#down-stepper:active
{
border-image: url("scroll-button-down-hover.png") 5;
}
NbtkScrollBar NbtkButton#vhandle
{
border-image: url("scroll-vhandle.png") 5;
}
NbtkScrollBar NbtkButton#vhandle:hover
{
border-image: url("scroll-vhandle.png") 5;
}
/* LookingGlass */
#LookingGlassDialog
{
background-color: rgba(0,0,0,0.85);
spacing: 4px;
padding: 4px;
border: 1px solid rgba(0,0,172,0.85);
border-radius: 4px;
color: #88ff66;
}
#LookingGlassDialog > #Toolbar
{
border: 1px solid grey;
border-radius: 4px;
}
#LookingGlassDialog NbtkLabel
{
color: #88ff66;
}
#LookingGlassDialog NbtkEntry
{
color: #88ff66;
}
#LookingGlassDialog NbtkBoxLayout#EvalBox
{
padding: 4px;
spacing: 4px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

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

@ -1,5 +1,4 @@
jsmiscdir = $(pkgdatadir)/js/misc
dist_jsmisc_DATA = \
appInfo.js \
docInfo.js

View File

@ -1,135 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
// TODO - move this into GConf once we're not a plugin anymore
// but have taken over metacity
// This list is taken from GNOME Online popular applications
// http://online.gnome.org/applications
// but with nautilus removed (since it should already be running)
// and evince, totem, and gnome-file-roller removed (since they're
// usually started by opening documents, not by opening the app
// directly)
const DEFAULT_APPLICATIONS = [
'mozilla-firefox.desktop',
'gnome-terminal.desktop',
'evolution.desktop',
'gedit.desktop',
'mozilla-thunderbird.desktop',
'rhythmbox.desktop',
'epiphany.desktop',
'xchat.desktop',
'openoffice.org-1.9-writer.desktop',
'emacs.desktop',
'gnome-system-monitor.desktop',
'openoffice.org-1.9-calc.desktop',
'eclipse.desktop',
'openoffice.org-1.9-impress.desktop',
'vncviewer.desktop'
];
function AppInfo(appId) {
this._init(appId);
}
AppInfo.prototype = {
_init : function(appId) {
this.appId = appId;
this._gAppInfo = Gio.DesktopAppInfo.new(appId);
if (!this._gAppInfo)
throw new Error('Unknown appId ' + appId);
this.id = this._gAppInfo.get_id();
this.name = this._gAppInfo.get_name();
this.description = this._gAppInfo.get_description();
this.executable = this._gAppInfo.get_executable();
this._gicon = this._gAppInfo.get_icon();
},
getIcon : function(size) {
if (this._gicon)
return Shell.TextureCache.get_default().load_gicon(this._gicon, size);
else
return new Clutter.Texture({ width: size, height: size });
},
getIconPath : function(size) {
if (this._gicon) {
let iconTheme = Gtk.IconTheme.get_default();
let previewIconInfo = iconTheme.lookup_by_gicon(this._gicon, size, 0);
if (previewIconInfo)
return previewIconInfo.get_filename();
}
return null;
},
launch : function() {
this._gAppInfo.launch([], Main.createAppLaunchContext());
}
};
var _infos = {};
// getAppInfo:
// @appId: an appId
//
// Gets an #AppInfo for @appId. This is preferable to calling
// new AppInfo() directly, because it caches #AppInfos.
//
// Return value: the new or cached #AppInfo, or %null if @appId
// doesn't point to a valid .desktop file
function getAppInfo(appId) {
let info = _infos[appId];
if (info === undefined) {
try {
info = _infos[appId] = new AppInfo(appId);
} catch (e) {
info = _infos[appId] = null;
}
}
return info;
}
// getMostUsedApps:
// @count: maximum number of apps to retrieve
//
// Gets a list of #AppInfos for the @count most-frequently-used
// applications
//
// Return value: the list of #AppInfo
function getMostUsedApps(count) {
let appMonitor = Shell.AppMonitor.get_default();
// Ask for more apps than we need, since the list of recently used
// apps might contain an app we don't have a desktop file for
let apps = appMonitor.get_most_used_apps (0, Math.round(count * 1.5));
let matches = [], alreadyAdded = {};
for (let i = 0; i < apps.length && matches.length <= count; i++) {
let appId = apps[i] + ".desktop";
let appInfo = getAppInfo(appId);
if (appInfo) {
matches.push(appInfo);
alreadyAdded[appId] = true;
}
}
// Fill the list with default applications it's not full yet
for (let i = 0; i < DEFAULT_APPLICATIONS.length && matches.length <= count; i++) {
let appId = DEFAULT_APPLICATIONS[i];
if (alreadyAdded[appId])
continue;
let appInfo = getAppInfo(appId);
if (appInfo)
matches.push(appInfo);
}
return matches;
}

View File

@ -5,6 +5,8 @@ const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Main = imports.ui.main;
const THUMBNAIL_ICON_MARGIN = 2;
@ -16,40 +18,17 @@ function DocInfo(recentInfo) {
DocInfo.prototype = {
_init : function(recentInfo) {
this._recentInfo = recentInfo;
// We actually used get_modified() instead of get_visited()
// here, as GtkRecentInfo doesn't updated get_visited()
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
this.timestamp = recentInfo.get_modified().getTime() / 1000;
this.name = recentInfo.get_display_name();
this.uri = recentInfo.get_uri();
this.mimeType = recentInfo.get_mime_type();
},
getIcon : function(size) {
let icon = new Clutter.Texture();
let iconPixbuf;
if (this.uri.match("^file://"))
iconPixbuf = Shell.get_thumbnail(this.uri, this.mimeType);
if (iconPixbuf) {
// We calculate the width and height of the texture so as
// to preserve the aspect ratio of the thumbnail. Because
// the images generated based on thumbnails don't have an
// internal padding like system icons do, we create a
// slightly smaller texture and then create a group around
// it for padding purposes
let scalingFactor = (size - THUMBNAIL_ICON_MARGIN * 2) / Math.max(iconPixbuf.get_width(), iconPixbuf.get_height());
icon.set_width(Math.ceil(iconPixbuf.get_width() * scalingFactor));
icon.set_height(Math.ceil(iconPixbuf.get_height() * scalingFactor));
Shell.clutter_texture_set_from_pixbuf(icon, iconPixbuf);
let group = new Clutter.Group({ width: size,
height: size });
group.add_actor(icon);
icon.set_position(THUMBNAIL_ICON_MARGIN, THUMBNAIL_ICON_MARGIN);
return group;
} else {
Shell.clutter_texture_set_from_pixbuf(icon, this._recentInfo.get_icon(size));
return icon;
}
createIcon : function(size) {
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this._recentInfo);
},
launch : function() {
@ -63,7 +42,7 @@ DocInfo.prototype = {
if (appInfo != null) {
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
} else {
log("Failed to get default application info for mime type " + mimeType +
log("Failed to get default application info for mime type " + this.mimeType +
". Will try to use the last application that registered the document.");
let appName = this._recentInfo.last_application();
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
@ -101,14 +80,62 @@ DocInfo.prototype = {
exists : function() {
return this._recentInfo.exists();
},
lastVisited : function() {
// We actually used get_modified() instead of get_visited()
// here, as GtkRecentInfo doesn't updated get_visited()
// correctly. See
// http://bugzilla.gnome.org/show_bug.cgi?id=567094
return this._recentInfo.get_modified();
}
};
var docManagerInstance = null;
function getDocManager() {
if (docManagerInstance == null)
docManagerInstance = new DocManager();
return docManagerInstance;
}
function DocManager() {
this._init();
}
DocManager.prototype = {
_init: function() {
this._recentManager = Gtk.RecentManager.get_default();
this._items = {};
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
this._reload();
this.emit('changed');
}));
this._reload();
},
_reload: function() {
let docs = this._recentManager.get_items();
let newItems = {};
for (let i = 0; i < docs.length; i++) {
let recentInfo = docs[i];
if (!recentInfo.exists())
continue;
let docInfo = new DocInfo(recentInfo);
// we use GtkRecentInfo URI as an item Id
newItems[docInfo.uri] = docInfo;
}
let deleted = {};
for (var uri in this._items) {
if (!(uri in newItems))
deleted[uri] = this._items[uri];
}
/* If we'd cached any thumbnail references that no longer exist,
dump them here */
let texCache = Shell.TextureCache.get_default();
for (var uri in deleted) {
texCache.evict_recent_thumbnail(this._items[uri]);
}
this._items = newItems;
},
getItems: function() {
return this._items;
}
}
Signals.addSignalMethods(DocManager.prototype);

View File

@ -3,15 +3,20 @@ jsuidir = $(pkgdatadir)/js/ui
dist_jsui_DATA = \
altTab.js \
appDisplay.js \
appIcon.js \
button.js \
chrome.js \
dash.js \
dnd.js \
docDisplay.js \
environment.js \
genericDisplay.js \
link.js \
lookingGlass.js \
main.js \
overlay.js \
overview.js \
panel.js \
places.js \
runDialog.js \
sidebar.js \
tweener.js \

View File

@ -36,38 +36,34 @@ function AltTabPopup() {
AltTabPopup.prototype = {
_init : function() {
let global = Shell.Global.get();
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
corner_radius: POPUP_GRID_SPACING,
padding: POPUP_GRID_SPACING,
spacing: POPUP_GRID_SPACING,
orientation: Big.BoxOrientation.VERTICAL });
// Icon grid. It would be nice to use Tidy.Grid for the this,
// but Tidy.Grid is lame in various ways. (Eg, it seems to
// have a minimum size of 200x200.) So we create a vertical
// Big.Box containing multiple horizontal Big.Boxes.
this._grid = new Big.Box({ spacing: POPUP_GRID_SPACING,
// Icon grid. TODO: Investigate Nbtk.Grid once that lands. Currently
// just implemented using a chain of Big.Box.
this._grid = new Big.Box({ spacing: POPUP_GRID_SPACING,
orientation: Big.BoxOrientation.VERTICAL });
let gcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER });
gcenterbox.append(this._grid, Big.BoxPackFlags.NONE);
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
this.actor.append(gcenterbox, Big.BoxPackFlags.NONE);
// Selected-window label
this._label = new Clutter.Text({ font_name: "Sans 16px",
this._label = new Clutter.Text({ font_name: "Sans 16px",
ellipsize: Pango.EllipsizeMode.END });
let labelbox = new Big.Box({ background_color: POPUP_INDICATOR_COLOR,
corner_radius: POPUP_GRID_SPACING / 2,
padding: POPUP_GRID_SPACING / 2 });
labelbox.append(this._label, Big.BoxPackFlags.EXPAND);
labelbox.append(this._label, Big.BoxPackFlags.NONE);
let lcenterbox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
width: POPUP_LABEL_MAX_WIDTH + POPUP_GRID_SPACING });
lcenterbox.append(labelbox, Big.BoxPackFlags.NONE);
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
this.actor.append(lcenterbox, Big.BoxPackFlags.NONE);
// Indicator around selected icon
this._indicator = new Big.Rectangle({ border_width: POPUP_INDICATOR_WIDTH,
@ -76,10 +72,10 @@ AltTabPopup.prototype = {
color: POPUP_TRANSPARENT });
this.actor.append(this._indicator, Big.BoxPackFlags.FIXED);
this._items = [];
this._items = [];
this._toplevels = global.window_group.get_children();
global.stage.add_actor(this.actor);
global.stage.add_actor(this.actor);
// Dark translucent window used to cover all but the
// currently-selected window while Alt-Tabbing. Actually
@ -142,10 +138,6 @@ AltTabPopup.prototype = {
},
show : function(initialSelection) {
let global = Shell.Global.get();
Main.startModal();
global.window_group.add_actor(this._overlay);
this._overlay.raise_top();
this._overlay.show();
@ -154,18 +146,16 @@ AltTabPopup.prototype = {
time: SHOW_TIME,
transition: "easeOutQuad" });
this.actor.show_all();
this.actor.x = (global.screen_width - this.actor.width) / 2;
this.actor.y = (global.screen_height - this.actor.height) / 2;
this.actor.show_all();
this.actor.x = Math.floor((global.screen_width - this.actor.width) / 2);
this.actor.y = Math.floor((global.screen_height - this.actor.height) / 2);
this.select(initialSelection);
},
destroy : function() {
this.actor.destroy();
this.actor.destroy();
this._overlay.destroy();
Main.endModal();
},
select : function(n) {
@ -240,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

File diff suppressed because it is too large Load Diff

133
js/ui/appIcon.js Normal file
View File

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

View File

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

View File

@ -9,7 +9,7 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main;
// This manages the shell "chrome"; the UI that's visible in the
// normal mode (ie, outside the overlay), that surrounds the main
// normal mode (ie, outside the Overview), that surrounds the main
// workspace content.
function Chrome() {
@ -18,13 +18,11 @@ 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);
this.nonOverlayActor = new Clutter.Group();
this.actor.add_actor(this.nonOverlayActor);
this.nonOverviewActor = new Clutter.Group();
this.actor.add_actor(this.nonOverviewActor);
this._obscuredByFullscreen = false;
@ -37,10 +35,10 @@ Chrome.prototype = {
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._queueUpdateRegions));
Main.overlay.connect('showing',
Lang.bind(this, this._overlayShowing));
Main.overlay.connect('hidden',
Lang.bind(this, this._overlayHidden));
Main.overview.connect('showing',
Lang.bind(this, this._overviewShowing));
Main.overview.connect('hidden',
Lang.bind(this, this._overviewHidden));
this._queueUpdateRegions();
},
@ -78,27 +76,27 @@ Chrome.prototype = {
else if (shapeActor && !this._verifyAncestry(shapeActor, actor))
throw new Error('shapeActor is not a descendent of actor');
this.nonOverlayActor.add_actor(actor);
this.nonOverviewActor.add_actor(actor);
if (shapeActor)
this._trackActor(shapeActor, true, true);
},
// setVisibleInOverlay:
// setVisibleInOverview:
// @actor: an actor in the chrome layer
// @visible: overlay visibility
// @visible: Overview visibility
//
// By default, actors in the chrome layer are automatically hidden
// when the overlay is shown. This can be used to override that
// when the Overview is shown. This can be used to override that
// behavior
setVisibleInOverlay: function(actor, visible) {
setVisibleInOverview: function(actor, visible) {
if (!this._verifyAncestry(actor, this.actor))
throw new Error('actor is not a descendent of the chrome layer');
if (visible)
actor.reparent(this.actor);
else
actor.reparent(this.nonOverlayActor);
actor.reparent(this.nonOverviewActor);
},
// addInputRegionActor:
@ -126,9 +124,11 @@ Chrome.prototype = {
//
// Removes @actor from the chrome layer
removeActor: function(actor) {
this.actor.remove_actor(actor);
// We don't have to do anything else; the parent-set handlers
// will do the rest.
if (actor.get_parent() == this.nonOverviewActor)
this.nonOverviewActor.remove_actor(actor);
else
this.actor.remove_actor(actor);
this._untrackActor(actor, true, true);
},
_findActor: function(actor) {
@ -170,7 +170,7 @@ Chrome.prototype = {
this._trackedActors.push(actorData);
actor = actor.get_parent();
if (actor != this.actor)
if (actor != this.actor && actor != this.nonOverviewActor)
this._trackActor(actor, false, false);
if (inputRegion || strut)
@ -198,7 +198,7 @@ Chrome.prototype = {
actor.disconnect(actorData.parentSetId);
actor = actor.get_parent();
if (actor && actor != this.actor)
if (actor && actor != this.actor && actor != this.nonOverviewActor)
this._untrackActor(actor, false, false);
}
@ -209,33 +209,33 @@ Chrome.prototype = {
_actorReparented: function(actor, oldParent) {
if (this._verifyAncestry(actor, this.actor)) {
let newParent = actor.get_parent();
if (newParent != this.actor)
if (newParent != this.actor && newParent != this.nonOverviewActor)
this._trackActor(newParent, false, false);
}
if (oldParent != this.actor)
if (oldParent != this.actor && oldParent != this.nonOverviewActor)
this._untrackActor(oldParent, false, false);
},
_overlayShowing: function() {
_overviewShowing: function() {
this.actor.show();
this.nonOverlayActor.hide();
this.nonOverviewActor.hide();
this._queueUpdateRegions();
},
_overlayHidden: function() {
_overviewHidden: function() {
if (this._obscuredByFullscreen)
this.actor.hide();
this.nonOverlayActor.show();
this.nonOverviewActor.show();
this._queueUpdateRegions();
},
_queueUpdateRegions: function() {
if (!this._updateRegionIdle)
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions));
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this._updateRegions),
Meta.PRIORITY_BEFORE_REDRAW);
},
_windowsRestacked: function() {
let global = Shell.Global.get();
let windows = global.get_windows();
// The chrome layer should be visible unless there is a window
@ -269,7 +269,7 @@ Chrome.prototype = {
break;
}
let shouldBeVisible = !this._obscuredByFullscreen || Main.overlay.visible;
let shouldBeVisible = !this._obscuredByFullscreen || Main.overview.visible;
if (this.actor.visible != shouldBeVisible) {
this.actor.visible = shouldBeVisible;
this._queueUpdateRegions();
@ -277,7 +277,6 @@ Chrome.prototype = {
},
_updateRegions: function() {
let global = Shell.Global.get();
let rects = [], struts = [], i;
delete this._updateRegionIdle;

963
js/ui/dash.js Normal file
View File

@ -0,0 +1,963 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay;
const Places = imports.ui.places;
const GenericDisplay = imports.ui.genericDisplay;
const Button = imports.ui.button;
const Main = imports.ui.main;
const DEFAULT_PADDING = 4;
const DEFAULT_SPACING = 4;
const DASH_SECTION_PADDING = 6;
const DASH_SECTION_SPACING = 40;
const DASH_CORNER_RADIUS = 5;
const DASH_PADDING_SIDE = 14;
const BACKGROUND_COLOR = new Clutter.Color();
BACKGROUND_COLOR.from_pixel(0x000000c0);
const PRELIGHT_COLOR = new Clutter.Color();
PRELIGHT_COLOR.from_pixel(0x4f6fadaa);
const TEXT_COLOR = new Clutter.Color();
TEXT_COLOR.from_pixel(0x5f5f5fff);
const BRIGHTER_TEXT_COLOR = new Clutter.Color();
BRIGHTER_TEXT_COLOR.from_pixel(0xbbbbbbff);
const BRIGHT_TEXT_COLOR = new Clutter.Color();
BRIGHT_TEXT_COLOR.from_pixel(0xffffffff);
const SEARCH_TEXT_COLOR = new Clutter.Color();
SEARCH_TEXT_COLOR.from_pixel(0x333333ff);
const SEARCH_CURSOR_COLOR = BRIGHT_TEXT_COLOR;
const HIGHLIGHTED_SEARCH_CURSOR_COLOR = SEARCH_TEXT_COLOR;
const HIGHLIGHTED_SEARCH_BACKGROUND_COLOR = new Clutter.Color();
HIGHLIGHTED_SEARCH_BACKGROUND_COLOR.from_pixel(0xc4c4c4ff);
const SEARCH_BORDER_BOTTOM_COLOR = new Clutter.Color();
SEARCH_BORDER_BOTTOM_COLOR.from_pixel(0x191919ff);
const SECTION_BORDER_COLOR = new Clutter.Color();
SECTION_BORDER_COLOR.from_pixel(0x262626ff);
const SECTION_BORDER = 1;
const SECTION_INNER_BORDER_COLOR = new Clutter.Color();
SECTION_INNER_BORDER_COLOR.from_pixel(0x000000ff);
const SECTION_BACKGROUND_TOP_COLOR = new Clutter.Color();
SECTION_BACKGROUND_TOP_COLOR.from_pixel(0x161616ff);
const SECTION_BACKGROUND_BOTTOM_COLOR = new Clutter.Color();
SECTION_BACKGROUND_BOTTOM_COLOR.from_pixel(0x000000ff);
const SECTION_INNER_SPACING = 8;
const BROWSE_ACTIVATED_BG = new Clutter.Color();
BROWSE_ACTIVATED_BG.from_pixel(0x303030f0);
const PANE_BORDER_COLOR = new Clutter.Color();
PANE_BORDER_COLOR.from_pixel(0x101d3cfa);
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();
}
Pane.prototype = {
_init: function () {
this._open = false;
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
background_color: PANE_BACKGROUND_COLOR,
border: PANE_BORDER_WIDTH,
border_color: PANE_BORDER_COLOR,
padding: DEFAULT_PADDING,
reactive: true });
this.actor.connect('button-press-event', Lang.bind(this, function (a, e) {
// Eat button press events so they don't go through and close the pane
return true;
}));
let chromeTop = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 6 });
let closeIconUri = "file://" + global.imagedir + "close.svg";
let closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
closeIconUri,
16,
16);
closeIcon.reactive = true;
closeIcon.connect('button-press-event', Lang.bind(this, function (b, e) {
this.close();
return true;
}));
chromeTop.append(closeIcon, Big.BoxPackFlags.END);
this.actor.append(chromeTop, Big.BoxPackFlags.NONE);
this.content = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: DEFAULT_PADDING });
this.actor.append(this.content, Big.BoxPackFlags.EXPAND);
// Hidden by default
this.actor.hide();
},
open: function () {
if (this._open)
return;
this._open = true;
this.actor.show();
this.emit('open-state-changed', this._open);
},
close: function () {
if (!this._open)
return;
this._open = false;
this.actor.hide();
this.emit('open-state-changed', this._open);
},
destroyContent: function() {
let children = this.content.get_children();
for (let i = 0; i < children.length; i++) {
children[i].destroy();
}
},
toggle: function () {
if (this._open)
this.close();
else
this.open();
}
}
Signals.addSignalMethods(Pane.prototype);
function ResultArea(displayType, enableNavigation) {
this._init(displayType, enableNavigation);
}
ResultArea.prototype = {
_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
});
this.actor.append(this.resultsContainer, Big.BoxPackFlags.EXPAND);
this.navContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL });
this.resultsContainer.append(this.navContainer, Big.BoxPackFlags.NONE);
this.display = _createDisplay(displayType);
this.navArea = this.display.getNavigationArea();
if (enableNavigation && this.navArea)
this.navContainer.append(this.navArea, Big.BoxPackFlags.EXPAND);
this.resultsContainer.append(this.display.actor, Big.BoxPackFlags.EXPAND);
this.controlBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER });
this.controlBox.append(this.display.displayControl, Big.BoxPackFlags.NONE);
this.actor.append(this.controlBox, Big.BoxPackFlags.NONE);
this.display.load();
}
}
// Utility function shared between ResultPane and the DocDisplay in the main dash.
// Connects to the detail signal of the display, and on-demand creates a new
// pane.
function createPaneForDetails(dash, display) {
let detailPane = null;
display.connect('show-details', Lang.bind(this, function(display, index) {
if (detailPane == null) {
detailPane = new Pane();
detailPane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (!isOpen) {
/* Ensure we don't keep around large preview textures */
detailPane.destroyContent();
}
}));
dash._addPane(detailPane);
}
if (index >= 0) {
detailPane.destroyContent();
let details = display.createDetailsForIndex(index);
detailPane.content.append(details, Big.BoxPackFlags.EXPAND);
detailPane.open();
} else {
detailPane.close();
}
}));
return null;
}
function ResultPane(dash) {
this._init(dash);
}
ResultPane.prototype = {
__proto__: Pane.prototype,
_init: function(dash) {
Pane.prototype._init.call(this);
this._dash = dash;
},
// 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);
this.content.append(resultArea.actor, Big.BoxPackFlags.EXPAND);
this.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
resultArea.display.resetState();
}));
return resultArea.display;
}
}
function SearchEntry() {
this._init();
}
SearchEntry.prototype = {
_init : function() {
this.actor = new Big.Box({ padding: DEFAULT_PADDING,
border_bottom: SECTION_BORDER,
border_color: SEARCH_BORDER_BOTTOM_COLOR,
corner_radius: DASH_CORNER_RADIUS,
reactive: true });
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
this.actor.append(box, Big.BoxPackFlags.EXPAND);
this.actor.connect('button-press-event', Lang.bind(this, function () {
this._resetTextState(true);
return false;
}));
this.pane = null;
this._defaultText = _("Find...");
let textProperties = { font_name: "Sans 16px" };
let entryProperties = { editable: true,
activatable: true,
single_line_mode: true,
color: SEARCH_TEXT_COLOR,
cursor_color: SEARCH_CURSOR_COLOR };
Lang.copyProperties(textProperties, entryProperties);
this.entry = new Clutter.Text(entryProperties);
this.entry.connect('notify::text', Lang.bind(this, function () {
this._resetTextState(false);
}));
box.append(this.entry, Big.BoxPackFlags.EXPAND);
// Mark as editable just to get a cursor
let defaultTextProperties = { ellipsize: Pango.EllipsizeMode.END,
text: this._defaultText,
editable: true,
color: TEXT_COLOR,
cursor_visible: false,
single_line_mode: true };
Lang.copyProperties(textProperties, defaultTextProperties);
this._defaultText = new Clutter.Text(defaultTextProperties);
box.add_actor(this._defaultText);
this.entry.connect('notify::allocation', Lang.bind(this, function () {
this._repositionDefaultText();
}));
this._iconBox = new Big.Box({ x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
padding_right: 4 });
box.append(this._iconBox, Big.BoxPackFlags.END);
let magnifierUri = "file://" + global.imagedir + "magnifier.svg";
this._magnifierIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
magnifierUri, 18, 18);
let closeUri = "file://" + global.imagedir + "close-black.svg";
this._closeIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
closeUri, 18, 18);
this._closeIcon.reactive = true;
this._closeIcon.connect('button-press-event', Lang.bind(this, function () {
// Resetting this.entry.text will trigger notify::text signal which will
// result in this._resetTextState() being called, but we should not rely
// on that not short-circuiting if the text was already empty, so we call
// this._resetTextState() explicitly in that case.
if (this.entry.text == '')
this._resetTextState(false);
else
this.entry.text = '';
// Return true to stop the signal emission, so that this.actor doesn't get
// the button-press-event and re-highlight itself.
return true;
}));
this._repositionDefaultText();
this._resetTextState();
},
setPane: function (pane) {
this._pane = pane;
},
reset: function () {
this.entry.text = '';
},
getText: function () {
return this.entry.text;
},
_resetTextState: function (searchEntryClicked) {
let text = this.getText();
this._iconBox.remove_all();
// We highlight the search box if the user starts typing in it
// or just clicks in it to indicate that the search is active.
if (text != '' || searchEntryClicked) {
if (!searchEntryClicked)
this._defaultText.hide();
this._iconBox.append(this._closeIcon, Big.BoxPackFlags.NONE);
this.actor.background_color = HIGHLIGHTED_SEARCH_BACKGROUND_COLOR;
this.entry.cursor_color = HIGHLIGHTED_SEARCH_CURSOR_COLOR;
} else {
this._defaultText.show();
this._iconBox.append(this._magnifierIcon, Big.BoxPackFlags.NONE);
this.actor.background_color = BACKGROUND_COLOR;
this.entry.cursor_color = SEARCH_CURSOR_COLOR;
}
},
_repositionDefaultText: function () {
// Offset a little to show the cursor
this._defaultText.set_position(this.entry.x + 4, this.entry.y);
this._defaultText.set_size(this.entry.width, this.entry.height);
}
};
Signals.addSignalMethods(SearchEntry.prototype);
function MoreLink() {
this._init();
}
MoreLink.prototype = {
_init : function () {
this.actor = new Big.Box({ 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_left: SECTION_BORDER,
border_color: SECTION_BORDER_COLOR });
this.pane = null;
let text = new Clutter.Text({ font_name: "Sans 12px",
color: BRIGHT_TEXT_COLOR,
text: _("Browse") });
this.actor.append(text, Big.BoxPackFlags.NONE);
this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
if (this.pane == null) {
// Ensure the pane is created; the activated handler will call setPane
this.emit('activated');
}
this._pane.toggle();
return true;
}));
},
setPane: function (pane) {
this._pane = pane;
this._pane.connect('open-state-changed', Lang.bind(this, function(pane, isOpen) {
}));
}
}
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);
}
SectionHeader.prototype = {
_init : function (title, suppressBrowse) {
this.actor = new Big.Box({ border: SECTION_BORDER,
border_color: SECTION_BORDER_COLOR });
this._innerBox = new Big.Box({ border: SECTION_BORDER,
border_color: SECTION_INNER_BORDER_COLOR,
padding_left: DEFAULT_PADDING,
padding_right: DEFAULT_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_SPACING });
this.actor.append(this._innerBox, Big.BoxPackFlags.EXPAND);
let backgroundGradient = Shell.create_vertical_gradient(SECTION_BACKGROUND_TOP_COLOR,
SECTION_BACKGROUND_BOTTOM_COLOR);
this._innerBox.add_actor(backgroundGradient);
this._innerBox.connect('notify::allocation', Lang.bind(this, function (actor) {
let [width, height] = actor.get_size();
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 });
this.text = new Clutter.Text({ color: TEXT_COLOR,
font_name: "Sans Bold 12px",
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);
}
SearchSectionHeader.prototype = {
_init : function(title, onClick) {
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: DASH_SECTION_PADDING,
padding_bottom: DASH_SECTION_PADDING,
spacing: DEFAULT_SPACING });
let titleText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
font_name: 'Sans Bold 12px',
text: title });
this.tooltip = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
font_name: 'Sans 12px',
text: _("(see all)") });
this.countText = new Clutter.Text({ color: BRIGHTER_TEXT_COLOR,
font_name: 'Sans Bold 14px' });
box.append(titleText, Big.BoxPackFlags.NONE);
box.append(this.tooltip, Big.BoxPackFlags.NONE);
box.append(this.countText, Big.BoxPackFlags.END);
this.tooltip.hide();
let button = new Button.Button(box, PRELIGHT_COLOR, BACKGROUND_COLOR,
TEXT_COLOR);
button.actor.height = box.height;
button.actor.padding_left = DEFAULT_PADDING;
button.actor.padding_right = DEFAULT_PADDING;
button.actor.connect('activate', onClick);
button.actor.connect('notify::hover', Lang.bind(this, this._updateTooltip));
this.actor = button.actor;
},
_updateTooltip : function(actor) {
if (actor.hover)
this.tooltip.show();
else
this.tooltip.hide();
}
}
function Section(titleString, suppressBrowse) {
this._init(titleString, suppressBrowse);
}
Section.prototype = {
_init: function(titleString, suppressBrowse) {
this.actor = new Big.Box({ spacing: SECTION_INNER_SPACING });
this.header = new SectionHeader(titleString, suppressBrowse);
this.actor.append(this.header.actor, Big.BoxPackFlags.NONE);
this.content = new Big.Box({spacing: SECTION_INNER_SPACING });
this.actor.append(this.content, Big.BoxPackFlags.EXPAND);
}
}
function Dash() {
this._init();
}
Dash.prototype = {
_init : function() {
// 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
// can interact with the workspaces. However, this behavior is not desirable when the click is actually over a pane.
//
// We have to make the individual panes reactive instead of making the whole dash actor reactive because the width
// of the Group actor ends up including the width of its hidden children, so we were getting a reactive object as
// wide as the details pane that was blocking the clicks to the workspaces underneath it even when the details pane
// was actually hidden.
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
background_color: BACKGROUND_COLOR,
corner_radius: DASH_CORNER_RADIUS,
padding_left: DASH_PADDING_SIDE,
padding_right: DASH_PADDING_SIDE,
reactive: true });
// Size for this one explicitly set from overlay.js
this.searchArea = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
this.sectionArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: DASH_SECTION_SPACING });
this.actor.append(this.searchArea, Big.BoxPackFlags.NONE);
this.actor.append(this.sectionArea, Big.BoxPackFlags.NONE);
// The currently active popup display
this._activePane = null;
/***** Search *****/
this._searchActive = false;
this._searchEntry = new SearchEntry();
this.searchArea.append(this._searchEntry.actor, Big.BoxPackFlags.EXPAND);
this._searchTimeoutId = 0;
this._searchEntry.entry.connect('text-changed', Lang.bind(this, function (se, prop) {
let text = this._searchEntry.getText();
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "")
this._searchActive = text != '';
this._updateDashActors();
if (!this._searchActive) {
if (this._searchTimeoutId > 0) {
Mainloop.source_remove(this._searchTimeoutId);
this._searchTimeoutId = 0;
}
return;
}
if (this._searchTimeoutId > 0)
return;
this._searchTimeoutId = Mainloop.timeout_add(150, Lang.bind(this, function() {
this._searchTimeoutId = 0;
let text = this._searchEntry.getText();
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
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.
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 = 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._searchResultsSingleShownSection != null)
this._showAllSearchSections();
// If we have an active search, we remove it.
else if (this._searchActive)
this._searchEntry.reset();
// Next, if we're in one of the "more" modes or showing the details pane, close them
else if (this._activePane != null)
this._activePane.close();
// Finally, just close the Overview entirely
else
Main.overview.hide();
return true;
} else if (symbol == Clutter.Up) {
if (!this._searchActive)
return true;
// selectUp and selectDown wrap around in their respective displays
// 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.
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;
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;
}));
/***** Applications *****/
this._appsSection = new Section(_("APPLICATIONS"));
let appWell = new AppDisplay.AppWell();
this._appsSection.content.append(appWell.actor, Big.BoxPackFlags.EXPAND);
this._moreAppsPane = null;
this._appsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
if (this._moreAppsPane == null) {
this._moreAppsPane = new ResultPane(this);
this._moreAppsPane.packResults(APPS, true);
this._addPane(this._moreAppsPane);
link.setPane(this._moreAppsPane);
}
}));
this.sectionArea.append(this._appsSection.actor, Big.BoxPackFlags.NONE);
/***** Places *****/
/* Translators: This is in the sense of locations for documents,
network locations, etc. */
this._placesSection = new Section(_("PLACES"), true);
let placesDisplay = new Places.Places();
this._placesSection.content.append(placesDisplay.actor, Big.BoxPackFlags.EXPAND);
this.sectionArea.append(this._placesSection.actor, Big.BoxPackFlags.NONE);
/***** Documents *****/
this._docsSection = new Section(_("RECENT DOCUMENTS"));
let docDisplay = new DocDisplay.DashDocDisplay();
this._docsSection.content.append(docDisplay.actor, Big.BoxPackFlags.EXPAND);
this._moreDocsPane = null;
this._docsSection.header.moreLink.connect('activated', Lang.bind(this, function (link) {
if (this._moreDocsPane == null) {
this._moreDocsPane = new ResultPane(this);
this._moreDocsPane.packResults(DOCS, true);
this._addPane(this._moreDocsPane);
link.setPane(this._moreDocsPane);
}
}));
this.sectionArea.append(this._docsSection.actor, Big.BoxPackFlags.EXPAND);
/***** Search Results *****/
this._searchResultsSection = new Section(_("SEARCH RESULTS"), true);
this._searchResultsSingleShownSection = null;
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() {
global.stage.set_key_focus(this._searchEntry.entry);
},
hide: function() {
this._firstSelectAfterOverlayShow = true;
this._searchEntry.reset();
if (this._activePane != null)
this._activePane.close();
},
closePanes: function () {
if (this._activePane != null)
this._activePane.close();
},
_addPane: function(pane) {
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (isOpen) {
if (pane != this._activePane && this._activePane != null) {
this._activePane.close();
}
this._activePane = pane;
} else if (pane == this._activePane) {
this._activePane = null;
}
}));
Main.overview.addPane(pane);
},
_updateDashActors: function() {
if (!this._searchActive && this._searchResultsSection.actor.visible) {
this._showAllSearchSections();
this._searchResultsSection.actor.hide();
this._appsSection.actor.show();
this._placesSection.actor.show();
this._docsSection.actor.show();
} else if (this._searchActive && !this._searchResultsSection.actor.visible) {
this._searchResultsSection.actor.show();
this._appsSection.actor.hide();
this._placesSection.actor.hide();
this._docsSection.actor.hide();
}
},
_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 + "'");
}
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();
}
}
this._searchResultsSingleShownSection = type;
},
_showAllSearchSections: function() {
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,44 +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();
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
@ -133,12 +173,12 @@ _Draggable.prototype = {
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
target._delegate.handleDragOver(this.actor._delegate, actor,
(stageX + this._dragOffsetX + this._xOffset - targX) / target.scale_x,
(stageY + this._dragOffsetY + this._yOffset - targY) / target.scale_y,
(stageX + this._dragOffsetX - targX) / target.scale_x,
(stageY + this._dragOffsetY - targY) / target.scale_y,
event.get_time());
}
target = target.get_parent();
}
}
}
return true;
@ -153,8 +193,6 @@ _Draggable.prototype = {
if (!dragging)
return false;
this.emit('drag-end', event.get_time());
// Find a drop target
actor.hide();
let [dropX, dropY] = event.get_coords();
@ -165,14 +203,15 @@ _Draggable.prototype = {
if (target._delegate && target._delegate.acceptDrop) {
let [targX, targY] = target.get_transformed_position();
if (target._delegate.acceptDrop(this.actor._delegate, actor,
(dropX + this._xOffset - targX) / target.scale_x,
(dropY + this._yOffset - targY) / target.scale_y,
(dropX - targX) / target.scale_x,
(dropY - targY) / target.scale_y,
event.get_time())) {
// If it accepted the drop without taking the actor,
// destroy it.
if (actor.get_parent() == actor.get_stage())
actor.destroy();
this.emit('drag-end', event.get_time(), true);
return true;
}
}
@ -196,23 +235,32 @@ _Draggable.prototype = {
transition: "easeOutQuad",
onComplete: this._onSnapBackComplete,
onCompleteScope: this,
onCompleteParams: [actor]
onCompleteParams: [actor, event.get_time()]
});
return true;
},
_onSnapBackComplete : function (dragActor) {
_onSnapBackComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) {
dragActor.reparent(this._dragOrigParent);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
dragActor.set_position(this._dragOrigX, this._dragOrigY);
} else
} else {
dragActor.destroy();
}
this.emit('drag-end', eventTime, false);
}
};
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

@ -1,38 +1,59 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Mainloop = imports.mainloop;
const DocInfo = imports.misc.docInfo;
const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const DASH_DOCS_ICON_SIZE = 16;
const DEFAULT_SPACING = 4;
/* This class represents a single display item containing information about a document.
* We take the current number of seconds in the constructor to avoid looking up the current
* time for every item when they are created in a batch.
*
* docInfo - DocInfo object containing information about the document
* availableWidth - total width available for the item
* currentSeconds - current number of seconds since the epoch
*/
function DocDisplayItem(docInfo, availableWidth) {
this._init(docInfo, availableWidth);
function DocDisplayItem(docInfo, currentSecs) {
this._init(docInfo, currentSecs);
}
DocDisplayItem.prototype = {
__proto__: GenericDisplay.GenericDisplayItem.prototype,
_init : function(docInfo, availableWidth) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this, availableWidth);
_init : function(docInfo, currentSecs) {
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
this._docInfo = docInfo;
this._setItemInfo(docInfo.name, "",
docInfo.getIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE));
this._setItemInfo(docInfo.name, "");
this._timeoutTime = -1;
this._resetTimeDisplay(currentSecs);
},
//// Public methods ////
getUpdateTimeoutTime: function() {
return this._timeoutTime;
},
// Update any relative-time based displays for this item.
redisplay: function(currentSecs) {
this._resetTimeDisplay(currentSecs);
},
//// Public method overrides ////
// Opens a document represented by this display item.
@ -42,66 +63,95 @@ DocDisplayItem.prototype = {
//// Protected method overrides ////
// Ensures the preview icon is created.
_ensurePreviewIconCreated : function() {
if (!this._previewIcon)
this._previewIcon = this._docInfo.getIcon(GenericDisplay.PREVIEW_ICON_SIZE);
// Returns an icon for the item.
_createIcon : function() {
return this._docInfo.createIcon(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
},
// Returns a preview icon for the item.
_createPreviewIcon : function() {
return this._docInfo.createIcon(GenericDisplay.PREVIEW_ICON_SIZE);
},
// Creates and returns a large preview icon, but only if this._docInfo is an image file
// and we were able to generate a pixbuf from it successfully.
_createLargePreviewIcon : function(availableWidth, availableHeight) {
_createLargePreviewIcon : function() {
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
return null;
return Shell.TextureCache.get_default().load_uri_sync(this._docInfo.uri, availableWidth, availableHeight);
try {
return Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.NONE,
this._docInfo.uri, -1, -1);
} catch (e) {
// An exception will be raised when the image format isn't know
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
* only ignore GDK_PIXBUF_ERROR_UNKNOWN_TYPE. */
return null;
}
},
//// Drag and Drop ////
shellWorkspaceLaunch: function() {
this.launch();
},
//// Private Methods ////
// Updates the last visited time displayed in the description text for the item.
_resetTimeDisplay: function(currentSecs) {
let lastSecs = this._docInfo.timestamp;
let timeDelta = currentSecs - lastSecs;
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
this._timeoutTime = currentSecs + nextUpdate;
this._setDescriptionText(text);
}
};
/* This class represents a display containing a collection of document items.
* The documents are sorted by how recently they were last visited.
*
* width - width available for the display
* height - height available for the display
*/
function DocDisplay(width, height, numberOfColumns, columnGap) {
this._init(width, height, numberOfColumns, columnGap);
}
function DocDisplay() {
this._init();
}
DocDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function(width, height, numberOfColumns, columnGap) {
GenericDisplay.GenericDisplay.prototype._init.call(this, width, height, numberOfColumns, columnGap);
let me = this;
this._recentManager = Gtk.RecentManager.get_default();
_init : function() {
GenericDisplay.GenericDisplay.prototype._init.call(this);
// We keep a single timeout callback for updating last visited times
// for all the items in the display. This avoids creating individual
// callbacks for each item in the display. So proper time updates
// for individual items and item details depend on the item being
// associated with one of the displays.
this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
this._docManager = DocInfo.getDocManager();
this._docsStale = true;
this._recentManager.connect('changed', function(recentManager, userData) {
me._docsStale = true;
// Changes in local recent files should not happen when we are in the overlay mode,
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)
Mainloop.source_remove(this._updateTimeoutId);
}));
},
//// Protected method overrides ////
// Gets the list of recent items from the recent items manager.
_refreshCache : function() {
let me = this;
if (!this._docsStale)
return;
this._allItems = {};
let docs = this._recentManager.get_items();
for (let i = 0; i < docs.length; i++) {
let recentInfo = docs[i];
let docInfo = new DocInfo.DocInfo(recentInfo);
// we use GtkRecentInfo URI as an item Id
this._allItems[docInfo.uri] = docInfo;
}
this._allItems = this._docManager.getItems();
this._docsStale = false;
},
@ -116,7 +166,7 @@ DocDisplay.prototype = {
// we should do the sorting manually because we want the order to be based on last visited.
//
// This function is called each time the search string is set back to '' or we display
// the overlay, so we are doing the sorting over the same items multiple times if the list
// the Overview, so we are doing the sorting over the same items multiple times if the list
// of recent items didn't change. We could store an additional array of doc ids and sort
// them once when they are returned by this._recentManager.get_items() to avoid having to do
// this sorting each time, but the sorting seems to be very fast anyway, so there is no need
@ -145,7 +195,7 @@ DocDisplay.prototype = {
let docA = this._allItems[itemIdA];
let docB = this._allItems[itemIdB];
return docB.lastVisited() - docA.lastVisited();
return docB.timestamp - docA.timestamp;
},
// Checks if the item info can be a match for the search string by checking
@ -168,8 +218,219 @@ DocDisplay.prototype = {
// Creates a DocDisplayItem based on itemInfo, which is expected to be a DocInfo object.
_createDisplayItem: function(itemInfo) {
return new DocDisplayItem(itemInfo, this._columnWidth);
}
let currentSecs = new Date().getTime() / 1000;
let docDisplayItem = new DocDisplayItem(itemInfo, currentSecs);
this._updateTimeoutCallback(docDisplayItem, currentSecs);
return docDisplayItem;
},
//// Private Methods ////
// A callback function that redisplays the items, updating their descriptions,
// and sets up a new timeout callback.
_docTimeout: function () {
let currentSecs = new Date().getTime() / 1000;
this._updateTimeoutId = 0;
this._updateTimeoutTargetTime = -1;
for (let docId in this._displayedItems) {
let docDisplayItem = this._displayedItems[docId];
docDisplayItem.redisplay(currentSecs);
this._updateTimeoutCallback(docDisplayItem, currentSecs);
}
return false;
},
// Updates the timeout callback if the timeout time for the docDisplayItem
// is earlier than the target time for the current timeout callback.
_updateTimeoutCallback: function (docDisplayItem, currentSecs) {
let timeoutTime = docDisplayItem.getUpdateTimeoutTime();
if (this._updateTimeoutTargetTime < 0 || timeoutTime < this._updateTimeoutTargetTime) {
if (this._updateTimeoutId > 0)
Mainloop.source_remove(this._updateTimeoutId);
this._updateTimeoutId = Mainloop.timeout_add_seconds(timeoutTime - currentSecs, Lang.bind(this, this._docTimeout));
this._updateTimeoutTargetTime = timeoutTime;
}
}
};
Signals.addSignalMethods(DocDisplay.prototype);
function DashDocDisplayItem(docInfo) {
this._init(docInfo);
}
DashDocDisplayItem.prototype = {
_init: function(docInfo) {
this._info = docInfo;
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_SPACING,
reactive: true });
this.actor.connect('button-release-event', Lang.bind(this, function () {
docInfo.launch();
Main.overview.hide();
}));
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
let iconBox = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.NONE);
let name = new Clutter.Text({ font_name: "Sans 14px",
color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
ellipsize: Pango.EllipsizeMode.END,
text: docInfo.name });
this.actor.append(name, Big.BoxPackFlags.EXPAND);
let draggable = DND.makeDraggable(this.actor);
this.actor._delegate = this;
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
this.dragActor = this._info.createIcon(DASH_DOCS_ICON_SIZE);
return this.dragActor;
},
//// Drag and drop functions ////
shellWorkspaceLaunch: function () {
this._info.launch();
}
}
/**
* Class used to display two column recent documents in the dash
*/
function DashDocDisplay() {
this._init();
}
DashDocDisplay.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._docManager = DocInfo.getDocManager();
this._docManager.connect('changed', Lang.bind(this, function(mgr) {
this._redisplay();
}));
this._redisplay();
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let children = actor.get_children();
// We use two columns maximum. Just take the min and natural size of the
// first two items, even though strictly speaking it's not correct; we'd
// need to calculate how many items we could fit for the height, then
// take the biggest preferred width for each column.
// In practice the dash gets a fixed width anyways.
// If we have one child, add its minimum and natural size
if (children.length > 0) {
let [minSize, naturalSize] = children[0].get_preferred_width(forHeight);
alloc.min_size += minSize;
alloc.natural_size += naturalSize;
}
// If we have two, add its size, plus DEFAULT_SPACING
if (children.length > 1) {
let [minSize, naturalSize] = children[1].get_preferred_width(forHeight);
alloc.min_size += DEFAULT_SPACING + minSize;
alloc.natural_size += DEFAULT_SPACING + naturalSize;
}
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let children = actor.get_children();
// Two columns, where we go vertically down first. So just take
// the height of half of the children as our preferred height.
let firstColumnChildren = children.length / 2;
alloc.min_size = 0;
for (let i = 0; i < firstColumnChildren; i++) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(forWidth);
alloc.natural_size += naturalSize;
if (i > 0 && i < children.length - 1) {
alloc.min_size += DEFAULT_SPACING;
alloc.natural_size += DEFAULT_SPACING;
}
}
},
_allocate: function(actor, box, flags) {
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
let children = actor.get_children();
// The width of an item is our allocated width, minus spacing, divided in half.
let itemWidth = Math.floor((width - DEFAULT_SPACING) / 2);
let x = box.x1;
let y = box.y1;
let columnIndex = 0;
let i = 0;
// Loop over the children, going vertically down first. When we run
// out of vertical space (our y variable is bigger than box.y2), switch
// to the second column.
for (; i < children.length; i++) {
let child = children[i];
let [minSize, naturalSize] = child.get_preferred_height(-1);
if (y + naturalSize > box.y2) {
// Is this the second column? Ok, break.
if (columnIndex == 1) {
break;
}
// Set x to the halfway point.
columnIndex += 1;
x = x + itemWidth + DEFAULT_SPACING;
// And y is back to the top.
y = box.y1;
}
let childBox = new Clutter.ActorBox();
childBox.x1 = x;
childBox.y1 = y;
childBox.x2 = childBox.x1 + itemWidth;
childBox.y2 = y + naturalSize;
y = childBox.y2 + DEFAULT_SPACING;
child.show();
child.allocate(childBox, flags);
}
// Everything else didn't fit, just hide it.
for (; i < children.length; i++) {
children[i].hide();
}
},
_redisplay: function() {
this.actor.remove_all();
let docs = this._docManager.getItems();
let docUrls = [];
for (let url in docs) {
docUrls.push(url);
}
docUrls.sort(function (urlA, urlB) { return docs[urlB].timestamp - docs[urlA].timestamp; });
let textureCache = Shell.TextureCache.get_default();
for (let i = 0; i < docUrls.length; i++) {
let url = docUrls[i];
let docInfo = docs[url];
let display = new DashDocDisplayItem(docInfo);
this.actor.add_actor(display.actor);
}
}
}

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

@ -0,0 +1,32 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Nbtk = imports.gi.Nbtk;
const Tweener = imports.ui.tweener;
// "monkey patch" in some varargs ClutterContainer methods; we need
// to do this per-container class since there is no representation
// of interfaces in Javascript
function _patchContainerClass(containerClass) {
// This one is a straightforward mapping of the C method
containerClass.prototype.child_set = function(actor, props) {
let meta = this.get_child_meta(actor);
for (prop in props)
meta[prop] = props[prop];
};
// clutter_container_add() actually is a an add-many-actors
// method. We conveniently, but somewhat dubiously, take the
// this opportunity to make it do something more useful.
containerClass.prototype.add = function(actor, props) {
this.add_actor(actor);
if (props)
this.child_set(actor, props);
};
}
_patchContainerClass(Nbtk.BoxLayout);
function init() {
Tweener.init();
}

File diff suppressed because it is too large Load Diff

562
js/ui/lookingGlass.js Normal file
View File

@ -0,0 +1,562 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Pango = imports.gi.Pango;
const Nbtk = imports.gi.Nbtk;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
/* Imports...feel free to add here as needed */
var commandHeader = "const Clutter = imports.gi.Clutter; " +
"const GLib = imports.gi.GLib; " +
"const Gtk = imports.gi.Gtk; " +
"const Mainloop = imports.mainloop; " +
"const Meta = imports.gi.Meta; " +
"const Shell = imports.gi.Shell; " +
"const Main = imports.ui.main; " +
"const Lang = imports.lang; " +
"const Tweener = imports.ui.tweener; " +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
"const stage = global.stage; " +
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
/* Special lookingGlass functions */
"const it = Main.lookingGlass.getIt(); " +
"const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ";
function Notebook() {
this._init();
}
Notebook.prototype = {
_init: function() {
this.actor = new Nbtk.BoxLayout({ vertical: true });
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4, padding: 2 });
this._selectedIndex = -1;
this._tabs = [];
},
appendPage: function(name, child) {
let labelOuterBox = new Big.Box({ padding: 2 });
let labelBox = new Nbtk.BoxLayout({ reactive: true });
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
let label = new Nbtk.Label({ text: name });
labelBox.connect('button-press-event', Lang.bind(this, function () {
this.selectChild(child);
return true;
}));
labelBox.add(label, { expand: true });
this.tabControls.append(labelOuterBox, Big.BoxPackFlags.NONE);
let scrollview = new Nbtk.ScrollView({ x_fill: true, y_fill: true });
scrollview.get_hscroll_bar().hide();
scrollview.add_actor(child);
this._tabs.push([child, labelBox, scrollview]);
scrollview.hide();
this.actor.add(scrollview, { expand: true });
if (this._selectedIndex == -1)
this.selectIndex(0);
},
_unselect: function() {
if (this._selectedIndex < 0)
return;
let [child, labelBox, scrollview] = this._tabs[this._selectedIndex];
labelBox.padding = 2;
labelBox.border = 0;
scrollview.hide();
this._selectedIndex = -1;
},
selectIndex: function(index) {
if (index == this._selectedIndex)
return;
this._unselect();
if (index < 0) {
this.emit('selection', null);
return;
}
let [child, labelBox, scrollview] = this._tabs[index];
labelBox.padding = 1;
labelBox.border = 1;
scrollview.show();
this._selectedIndex = index;
this.emit('selection', child);
},
selectChild: function(child) {
if (child == null)
this.selectIndex(-1);
else {
for (let i = 0; i < this._tabs.length; i++) {
let [tabChild, labelBox, scrollview] = this._tabs[i];
if (tabChild == child) {
this.selectIndex(i);
return;
}
}
}
}
}
Signals.addSignalMethods(Notebook.prototype);
function Result(command, o, index) {
this._init(command, o, index);
}
Result.prototype = {
_init : function(command, o, index) {
this.index = index;
this.o = o;
this.actor = new Big.Box();
let cmdTxt = new Nbtk.Label({ text: command });
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
let resultTxt = new Nbtk.Label({ text: "r(" + index + ") = " + o });
resultTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
let line = new Clutter.Rectangle({ name: "Separator",
height: 1 });
let padBin = new Nbtk.Bin({ name: "Separator", x_fill: true, y_fill: true });
padBin.add_actor(line);
this.actor.append(padBin, Big.BoxPackFlags.NONE);
}
}
function ActorHierarchy() {
this._init();
}
ActorHierarchy.prototype = {
_init : function () {
this._previousTarget = null;
this._target = null;
this._parentList = [];
this.actor = new Nbtk.BoxLayout({ name: "ActorHierarchy", vertical: true });
},
setTarget: function(actor) {
this._previousTarget = this._target;
this.target = actor;
this.actor.get_children().forEach(function (child) { child.destroy(); });
if (!(actor instanceof Clutter.Actor))
return;
if (this.target == null)
return;
this._parentList = [];
let parent = actor;
while ((parent = parent.get_parent()) != null) {
this._parentList.push(parent);
let link = new Nbtk.Label({ reactive: true,
text: "" + parent });
this.actor.add_actor(link);
let parentTarget = parent;
link.connect('button-press-event', Lang.bind(this, function () {
this._selectByActor(parentTarget);
return true;
}));
}
this.emit('selection', actor);
},
_selectByActor: function(actor) {
let idx = this._parentList.indexOf(actor);
let children = this.actor.get_children();
let link = children[idx];
this.emit('selection', actor);
}
}
Signals.addSignalMethods(ActorHierarchy.prototype);
function PropertyInspector() {
this._init();
}
PropertyInspector.prototype = {
_init : function () {
this._target = null;
this._parentList = [];
this.actor = new Nbtk.BoxLayout({ name: "PropertyInspector", vertical: true });
},
setTarget: function(actor) {
this.target = actor;
this.actor.get_children().forEach(function (child) { child.destroy(); });
for (let propName in actor) {
let valueStr;
try {
valueStr = "" + actor[propName];
} catch (e) {
valueStr = '<error>';
}
let propText = propName + ": " + valueStr;
let propDisplay = new Nbtk.Label({ reactive: true,
text: propText });
this.actor.add_actor(propDisplay);
}
}
}
function Inspector() {
this._init();
}
Inspector.prototype = {
_init: function() {
let width = 150;
let eventHandler = new Nbtk.BoxLayout({ name: "LookingGlassDialog",
vertical: false,
y: Math.floor(global.stage.height/2),
reactive: true });
eventHandler.connect('notify::allocation', Lang.bind(this, function () {
eventHandler.x = Math.floor((global.stage.width)/2 - (eventHandler.width)/2);
}));
global.stage.add_actor(eventHandler);
let displayText = new Nbtk.Label();
eventHandler.add(displayText, { expand: true });
let borderPaintTarget = null;
let borderPaintId = null;
eventHandler.connect('destroy', Lang.bind(this, function() {
if (borderPaintTarget != null)
borderPaintTarget.disconnect(borderPaintId);
}));
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
Clutter.ungrab_pointer(eventHandler);
let [stageX, stageY] = event.get_coords();
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
stageX,
stageY);
this.emit('target', target, stageX, stageY);
eventHandler.destroy();
this.emit('closed');
return true;
}));
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
let [stageX, stageY] = event.get_coords();
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
stageX,
stageY);
displayText.text = '<inspect x: ' + stageX + ' y: ' + stageY + '> ' + target;
if (borderPaintTarget != null)
borderPaintTarget.disconnect(borderPaintId);
borderPaintTarget = target;
borderPaintId = Shell.add_hook_paint_red_border(target);
return true;
}));
Clutter.grab_pointer(eventHandler);
}
}
Signals.addSignalMethods(Inspector.prototype);
function LookingGlass() {
this._init();
}
LookingGlass.prototype = {
_init : function() {
this._idleHistorySaveId = 0;
let historyPath = global.configdir + "/lookingglass-history.txt";
this._historyFile = Gio.file_new_for_path(historyPath);
this._savedText = null;
this._historyNavIndex = -1;
this._history = [];
this._readHistory();
this._open = false;
this._offset = 0;
this._results = [];
// Sort of magic, but...eh.
this._maxItems = 150;
this.actor = new Nbtk.BoxLayout({ name: "LookingGlassDialog",
vertical: true,
visible: false });
let gconf = Shell.GConf.get_default();
gconf.watch_directory("/desktop/gnome/interface");
gconf.connect("changed::/desktop/gnome/interface/monospace_font_name",
Lang.bind(this, this._updateFont));
this._updateFont();
global.stage.add_actor(this.actor);
let toolbar = new Nbtk.BoxLayout({ name: "Toolbar" });
this.actor.add_actor(toolbar);
let inspectIcon = Shell.TextureCache.get_default().load_gicon(new Gio.ThemedIcon({ name: 'gtk-color-picker' }),
24);
toolbar.add_actor(inspectIcon);
inspectIcon.reactive = true;
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
let inspector = new Inspector();
inspector.connect('target', Lang.bind(this, function(i, target, stageX, stageY) {
this._pushResult('<inspect x:' + stageX + ' y:' + stageY + '>',
target);
this._hierarchy.setTarget(target);
}));
inspector.connect('closed', Lang.bind(this, function() {
this.actor.show();
global.stage.set_key_focus(this._entry);
}));
this.actor.hide();
return true;
}));
let notebook = new Notebook();
this.actor.add(notebook.actor, { expand: true });
let emptyBox = new Nbtk.Bin();
toolbar.add(emptyBox, { expand: true });
toolbar.add_actor(notebook.tabControls);
this._evalBox = new Nbtk.BoxLayout({ name: "EvalBox", vertical: true });
notebook.appendPage('Evaluator', this._evalBox);
this._resultsArea = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: 4 });
this._evalBox.add(this._resultsArea, { expand: true });
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
this._evalBox.add_actor(entryArea);
let label = new Nbtk.Label({ text: 'js>>> ' });
entryArea.append(label, Big.BoxPackFlags.NONE);
this._entry = new Nbtk.Entry();
/* 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);
}));
entryArea.append(this._entry, Big.BoxPackFlags.EXPAND);
this._hierarchy = new ActorHierarchy();
notebook.appendPage('Hierarchy', this._hierarchy.actor);
this._propInspector = new PropertyInspector();
notebook.appendPage('Properties', this._propInspector.actor);
this._hierarchy.connect('selection', Lang.bind(this, function (h, actor) {
this._pushResult('<parent selection>', actor);
notebook.selectIndex(0);
}));
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
let text = o.get_text();
// Ensure we don't get newlines in the command; the history file is
// newline-separated.
text.replace('\n', ' ');
// Strip leading and trailing whitespace
text = text.replace(/^\s+/g, "").replace(/\s+$/g, "");
if (text == '')
return true;
this._evaluate(text);
this._historyNavIndex = -1;
return true;
}));
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
} else if (symbol == Clutter.Up) {
if (this._historyNavIndex >= this._history.length - 1)
return true;
this._historyNavIndex++;
if (this._historyNavIndex == 0)
this._savedText = this._entry.text;
this._entry.text = this._history[this._history.length - this._historyNavIndex - 1];
return true;
} else if (symbol == Clutter.Down) {
if (this._historyNavIndex <= 0)
return true;
this._historyNavIndex--;
if (this._historyNavIndex < 0)
this._entry.text = this._savedText;
else
this._entry.text = this._history[this._history.length - this._historyNavIndex - 1];
return true;
} else {
this._historyNavIndex = -1;
this._savedText = null;
return false;
}
}));
},
_updateFont: function() {
let gconf = Shell.GConf.get_default();
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
let fontDesc = Pango.Font.description_from_string(fontName);
// We ignore everything but size and style; you'd be crazy to set your system-wide
// monospace font to be bold/oblique/etc. Could easily be added here.
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
},
_readHistory: function () {
if (!this._historyFile.query_exists(null))
return;
let [result, contents, length, etag] = this._historyFile.load_contents(null);
this._history = contents.split('\n').filter(function (e) { return e != ''; });
},
_queueHistorySave: function() {
if (this._idleHistorySaveId > 0)
return;
this._idleHistorySaveId = Mainloop.timeout_add_seconds(5, Lang.bind(this, this._doSaveHistory));
},
_doSaveHistory: function () {
this._idleHistorySaveId = false;
let output = this._historyFile.replace(null, true, Gio.FileCreateFlags.NONE, null);
let dataOut = new Gio.DataOutputStream({ base_stream: output });
dataOut.put_string(this._history.join('\n'), null);
dataOut.put_string('\n', null);
dataOut.close(null);
return false;
},
_pushResult: function(command, obj) {
let index = this._results.length + this._offset;
let result = new Result('>>> ' + command, obj, index);
this._results.push(result);
this._resultsArea.append(result.actor, Big.BoxPackFlags.NONE);
this._propInspector.setTarget(obj);
let children = this._resultsArea.get_children();
if (children.length > this._maxItems) {
this._results.shift();
children[0].destroy();
this._offset++;
}
this._it = obj;
},
_evaluate : function(command) {
this._history.push(command);
this._queueHistorySave();
let fullCmd = commandHeader + command;
let resultObj;
try {
resultObj = eval(fullCmd);
} catch (e) {
resultObj = "<exception " + e + ">";
}
this._pushResult(command, resultObj);
this._hierarchy.setTarget(null);
this._entry.text = '';
},
getIt: function () {
return this._it;
},
getResult: function(idx) {
return this._results[idx - this._offset].o;
},
toggle: function() {
if (this._open)
this.close();
else
this.open();
},
_resizeTo: function(actor) {
let stage = global.stage;
let myWidth = stage.width * 0.7;
let myHeight = stage.height * 0.7;
let [srcX, srcY] = actor.get_transformed_position();
this.actor.x = srcX + (stage.width-myWidth)/2;
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
this.actor.width = myWidth;
this.actor.height = myHeight;
},
slaveTo: function(actor) {
this._slaveTo = actor;
actor.connect('notify::allocation', Lang.bind(this, function () {
this._resizeTo(actor);
}));
this._resizeTo(actor);
},
open : function() {
if (this._open)
return;
this.actor.show();
this.actor.lower(Main.chrome.actor);
this._open = true;
Tweener.removeTweens(this.actor);
Main.pushModal(this.actor);
global.stage.set_key_focus(this._entry);
Tweener.addTween(this.actor, { time: 0.5,
transition: "easeOutQuad",
y: this._targetY
});
},
close : function() {
if (!this._open)
return;
this._historyNavIndex = -1;
this._open = false;
Tweener.removeTweens(this.actor);
Main.popModal(this.actor);
Tweener.addTween(this.actor, { time: 0.5,
transition: "easeOutQuad",
y: this._hiddenY,
onComplete: Lang.bind(this, function () {
this.actor.hide();
})
});
}
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -3,18 +3,21 @@
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Nbtk = imports.gi.Nbtk;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Chrome = imports.ui.chrome;
const Overlay = imports.ui.overlay;
const Environment = imports.ui.environment;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const RunDialog = imports.ui.runDialog;
const LookingGlass = imports.ui.lookingGlass;
const Sidebar = imports.ui.sidebar;
const Tweener = imports.ui.tweener;
const WindowManager = imports.ui.windowManager;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
@ -23,21 +26,35 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let chrome = null;
let panel = null;
let sidebar = null;
let overlay = null;
let overview = null;
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");
global.grab_dbus_service();
global.start_task_panel();
Tweener.init();
Environment.init();
// Ensure ShellAppMonitor is initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
// needs to load all the .desktop files, and ShellAppMonitor
// will use those to associate with windows. Right now
// the Monitor doesn't listen for installed app changes
// and recalculate application associations, so to avoid
// races for now we initialize it here. It's better to
// be predictable anyways.
Shell.AppMonitor.get_default();
// The background color really only matters if there is no desktop
// window (say, nautilus) running. We set it mostly so things look good
@ -45,39 +62,29 @@ function start() {
global.stage.color = DEFAULT_BACKGROUND_COLOR;
// Mutter currently hardcodes putting "Yessir. The compositor is running""
// in the overlay. Clear that out.
// in the Overview. Clear that out.
let children = global.overlay_group.get_children();
for (let i = 0; i < children.length; i++)
children[i].destroy();
let themeContext = Shell.ThemeContext.get_for_stage (global.stage);
let stylesheetPath = global.datadir + "/theme/gnome-shell.css";
let theme = new Shell.Theme ({ application_stylesheet: stylesheetPath });
themeContext.set_theme (theme);
global.connect('panel-run-dialog', function(panel) {
// Make sure not more than one run dialog is shown.
if (!runDialog) {
runDialog = new RunDialog.RunDialog();
let endHandler = function() {
runDialog.destroy();
runDialog = null;
};
runDialog.connect('run', endHandler);
runDialog.connect('cancel', endHandler);
if (!runDialog.show())
endHandler();
}
getRunDialog().open();
});
overlay = new Overlay.Overlay();
overview = new Overview.Overview();
chrome = new Chrome.Chrome();
panel = new Panel.Panel();
sidebar = new Sidebar.Sidebar();
wm = new WindowManager.WindowManager();
global.screen.connect('toggle-recording', function() {
if (recorder == null) {
// We have to initialize GStreamer first. This isn't done
// inside ShellRecorder to make it usable inside projects
// with other usage of GStreamer.
let Gst = imports.gi.Gst;
Gst.init(null, null);
recorder = new Shell.Recorder({ stage: global.stage });
}
@ -88,13 +95,24 @@ function start() {
}
});
_relayout();
panel.startupAnimation();
let display = global.screen.get_display();
display.connect('overlay-key', Lang.bind(overlay, overlay.toggle));
global.connect('panel-main-menu', Lang.bind(overlay, overlay.toggle));
display.connect('overlay-key', Lang.bind(overview, overview.toggle));
global.connect('panel-main-menu', Lang.bind(overview, overview.toggle));
global.stage.connect('captured-event', _globalKeyPressHandler);
Mainloop.idle_add(_removeUnusedWorkspaces);
}
function _relayout() {
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
overview.relayout();
}
// metacity-clutter currently uses the same prefs as plain metacity,
// which probably means we'll be starting out with multiple workspaces;
// remove any unused ones. (We do this from an idle handler, because
@ -102,8 +120,6 @@ function start() {
// 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++) {
@ -125,31 +141,154 @@ function _removeUnusedWorkspaces() {
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 startModal() {
let global = Shell.Global.get();
if (!global.grab_keyboard())
// This function encapsulates hacks to make certain global keybindings
// work even when we are in one of our modes where global keybindings
// are disabled with a global grab. (When there is a global grab, then
// all key events will be delivered to the stage, so ::captured-event
// on the stage can be used for global keybindings.)
//
// We expect to need to conditionally enable just a few keybindings
// depending on circumstance; the main hackiness here is that we are
// assuming that keybindings have their default values; really we
// should be asking Mutter to resolve the key into an action and then
// base our handling based on the action.
function _globalKeyPressHandler(actor, event) {
if (modalCount == 0)
return false;
global.set_stage_input_mode(Shell.StageInputMode.FULLSCREEN);
inModal = true;
let type = event.type();
return true;
if (type == Clutter.EventType.KEY_PRESS) {
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();
let command = gconf.get_string("/apps/metacity/keybinding_commands/command_screenshot");
if (command != null && command != "") {
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
p.run();
}
return true;
}
} else if (type == Clutter.EventType.KEY_RELEASE) {
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.
if (overview.visible)
overview.hide();
return true;
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
getRunDialog().open();
}
}
return false;
}
function endModal() {
let global = Shell.Global.get();
function _findModal(actor) {
for (let i = 0; i < modalActorFocusStack.length; i++) {
let [stackActor, stackFocus] = modalActorFocusStack[i];
if (stackActor == actor) {
return i;
}
}
return -1;
}
global.ungrab_keyboard();
/**
* 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() {
if (lookingGlass == null) {
lookingGlass = new LookingGlass.LookingGlass();
lookingGlass.slaveTo(panel.actor);
}
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

@ -1,975 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay;
const GenericDisplay = imports.ui.genericDisplay;
const Link = imports.ui.link;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Tweener = imports.ui.tweener;
const Workspaces = imports.ui.workspaces;
const ROOT_OVERLAY_COLOR = new Clutter.Color();
ROOT_OVERLAY_COLOR.from_pixel(0x000000bb);
// The factor to scale the overlay wallpaper with. This should not be less
// than 3/2, because the rule of thirds is used for positioning (see below).
const BACKGROUND_SCALE = 2;
const LABEL_HEIGHT = 16;
// We use SIDESHOW_PAD for the padding on the left side of the sideshow and as a gap
// between sideshow columns.
const SIDESHOW_PAD = 6;
const SIDESHOW_MIN_WIDTH = 250;
const SIDESHOW_SECTION_PADDING_TOP = 6;
const SIDESHOW_SECTION_SPACING = 6;
const SIDESHOW_COLUMNS = 1;
const DETAILS_CORNER_RADIUS = 5;
const DETAILS_BORDER_WIDTH = 1;
const DETAILS_PADDING = 6;
// This is the height of section components other than the item display.
const SIDESHOW_SECTION_MISC_HEIGHT = (LABEL_HEIGHT + SIDESHOW_SECTION_SPACING) * 2 + SIDESHOW_SECTION_PADDING_TOP;
const SIDESHOW_SEARCH_BG_COLOR = new Clutter.Color();
SIDESHOW_SEARCH_BG_COLOR.from_pixel(0xffffffff);
const SIDESHOW_TEXT_COLOR = new Clutter.Color();
SIDESHOW_TEXT_COLOR.from_pixel(0xffffffff);
const DETAILS_BORDER_COLOR = new Clutter.Color();
DETAILS_BORDER_COLOR.from_pixel(0xffffffff);
// Time for initial animation going into overlay mode
const ANIMATION_TIME = 0.25;
// We divide the screen into a grid of rows and columns, which we use
// to help us position the overlay components, such as the side panel
// that lists applications and documents, the workspaces display, and
// the button for adding additional workspaces.
// In the regular mode, the side panel takes up one column on the left,
// and the workspaces display takes up the remaining columns.
// In the expanded side panel display mode, the side panel takes up two
// columns, and the workspaces display slides all the way to the right,
// being visible only in the last quarter of the right-most column.
// In the future, this mode will have more components, such as a display
// of documents which were recently opened with a given application, which
// will take up the remaining sections of the display.
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
const COLUMNS_REGULAR_SCREEN = 4;
const ROWS_REGULAR_SCREEN = 8;
const COLUMNS_WIDE_SCREEN = 5;
const ROWS_WIDE_SCREEN = 10;
// Padding around workspace grid / Spacing between Sideshow and Workspaces
const WORKSPACE_GRID_PADDING = 12;
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
const WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN = 4 - 0.25;
const EXPANDED_SIDESHOW_COLUMNS_REGULAR_SCREEN = 2;
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
const WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN = 5 - 0.25;
const EXPANDED_SIDESHOW_COLUMNS_WIDE_SCREEN = 3;
// A multi-state; PENDING is used during animations
const STATE_ACTIVE = true;
const STATE_PENDING_INACTIVE = false;
const STATE_INACTIVE = false;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
function SearchEntry(width) {
this._init(width);
}
SearchEntry.prototype = {
_init : function(width) {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
background_color: SIDESHOW_SEARCH_BG_COLOR,
corner_radius: 4,
spacing: 4,
padding_left: 4,
padding_right: 4,
width: width,
height: 24
});
let icontheme = Gtk.IconTheme.get_default();
let searchIconTexture = new Clutter.Texture({});
let searchIconPath = icontheme.lookup_icon('gtk-find', 16, 0).get_filename();
searchIconTexture.set_from_file(searchIconPath);
this.actor.append(searchIconTexture, 0);
// We need to initialize the text for the entry to have the cursor displayed
// in it. See http://bugzilla.openedhand.com/show_bug.cgi?id=1365
this.entry = new Clutter.Text({ font_name: "Sans 14px",
editable: true,
activatable: true,
singleLineMode: true,
text: ""
});
this.entry.connect('text-changed', Lang.bind(this, function (e) {
let text = this.entry.text;
}));
this.actor.append(this.entry, Big.BoxPackFlags.EXPAND);
}
};
function Sideshow() {
this._init();
}
Sideshow.prototype = {
_init : function() {
let me = this;
this._moreAppsMode = STATE_INACTIVE;
this._moreDocsMode = STATE_INACTIVE;
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;
this._expandedSideshowColumns = wideScreen ? EXPANDED_SIDESHOW_COLUMNS_WIDE_SCREEN : EXPANDED_SIDESHOW_COLUMNS_REGULAR_SCREEN;
this._width = displayGridColumnWidth;
this._displayWidth = this._width - SIDESHOW_PAD;
this._expandedWidth = displayGridColumnWidth * asideXFactor;
// this figures out the additional width we can give to the display in the 'More' mode,
// assuming that we want to keep the columns the same width in both modes
this._additionalWidth = (this._width / SIDESHOW_COLUMNS) *
(this._expandedSideshowColumns - SIDESHOW_COLUMNS);
let bottomHeight = displayGridRowHeight / 2;
let global = Shell.Global.get();
let previewWidth = this._expandedWidth - this._width -
this._additionalWidth - SIDESHOW_SECTION_SPACING;
let previewHeight = global.screen_height - Panel.PANEL_HEIGHT - SIDESHOW_PAD - bottomHeight;
this.actor = new Clutter.Group();
this.actor.height = global.screen_height;
this._searchEntry = new SearchEntry(this._displayWidth);
this.actor.add_actor(this._searchEntry.actor);
this._searchEntry.actor.set_position(SIDESHOW_PAD, Panel.PANEL_HEIGHT + SIDESHOW_PAD);
this._searchQueued = false;
this._searchEntry.entry.connect('text-changed', function (se, prop) {
if (me._searchQueued)
return;
me._searchQueued = true;
Mainloop.timeout_add(250, function() {
// Strip leading and trailing whitespace
let text = me._searchEntry.entry.text.replace(/^\s+/g, "").replace(/\s+$/g, "");
me._searchQueued = false;
me._appDisplay.setSearch(text);
me._docDisplay.setSearch(text);
return false;
});
});
this._searchEntry.entry.connect('activate', function (se) {
// only one of the displays will have an item selected, so it's ok to
// call activateSelected() on both of them
me._appDisplay.activateSelected();
me._docDisplay.activateSelected();
return true;
});
this._searchEntry.entry.connect('key-press-event', function (se, e) {
let symbol = Shell.get_event_key_symbol(e);
if (symbol == Clutter.Escape) {
// We always want to hide the previews when the user hits Escape.
// If something that should have a preview gets displayed under
// the mouse pointer afterwards the preview will get redisplayed.
me._appDisplay.hidePreview();
me._docDisplay.hidePreview();
// Escape will keep clearing things back to the desktop. First, if
// we have active text, we remove it.
if (me._searchEntry.text != '')
me._searchEntry.text = '';
// Next, if we're in one of the "more" modes, close it
else if (me._moreAppsMode)
me._unsetMoreAppsMode();
else if (me._moreDocsMode)
me._unsetMoreDocsMode();
else
// Finally, just close the overlay entirely
me.emit('activated');
return true;
} else if (symbol == Clutter.Up) {
// selectUp and selectDown wrap around in their respective displays
// 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 (me._moreAppsMode)
me._appDisplay.selectUp();
else if (me._moreDocsMode)
me._docDisplay.selectUp();
else if (me._appDisplay.hasSelected() && !me._appDisplay.selectUp() && me._docDisplay.hasItems()) {
me._appDisplay.unsetSelected();
me._docDisplay.selectLastItem();
} else if (me._docDisplay.hasSelected() && !me._docDisplay.selectUp() && me._appDisplay.hasItems()) {
me._docDisplay.unsetSelected();
me._appDisplay.selectLastItem();
}
return true;
} else if (symbol == Clutter.Down) {
if (me._moreAppsMode)
me._appDisplay.selectDown();
else if (me._moreDocsMode)
me._docDisplay.selectDown();
else if (me._appDisplay.hasSelected() && !me._appDisplay.selectDown() && me._docDisplay.hasItems()) {
me._appDisplay.unsetSelected();
me._docDisplay.selectFirstItem();
} else if (me._docDisplay.hasSelected() && !me._docDisplay.selectDown() && me._appDisplay.hasItems()) {
me._docDisplay.unsetSelected();
me._appDisplay.selectFirstItem();
}
return true;
} else if (me._moreAppsMode && me._searchEntry.text == '') {
if (symbol == Clutter.Right) {
me._appDisplay.moveRight();
return true;
} else if (symbol == Clutter.Left) {
me._appDisplay.moveLeft();
return true;
}
return false;
} else if (symbol == Clutter.Right && me._searchEntry.text == '') {
if (me._appDisplay.hasSelected())
me._setMoreAppsMode();
else
me._setMoreDocsMode();
return true;
}
return false;
});
this._appsSection = new Big.Box({ x: SIDESHOW_PAD,
y: this._searchEntry.actor.y + this._searchEntry.actor.height,
padding_top: SIDESHOW_SECTION_PADDING_TOP,
spacing: SIDESHOW_SECTION_SPACING});
this._appsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
font_name: "Sans Bold 14px",
text: "Applications",
height: LABEL_HEIGHT});
this._appsSection.append(this._appsText, Big.BoxPackFlags.EXPAND);
this._itemDisplayHeight = global.screen_height - this._appsSection.y - SIDESHOW_SECTION_MISC_HEIGHT * 2 - bottomHeight;
this._appsContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
this._appsSection.append(this._appsContent, Big.BoxPackFlags.EXPAND);
this._appDisplay = new AppDisplay.AppDisplay(this._displayWidth, this._itemDisplayHeight / 2, SIDESHOW_COLUMNS, SIDESHOW_PAD);
let sideArea = this._appDisplay.getSideArea();
sideArea.hide();
this._appsContent.append(sideArea, Big.BoxPackFlags.NONE);
this._appsContent.append(this._appDisplay.actor, Big.BoxPackFlags.EXPAND);
let moreAppsBox = new Big.Box({x_align: Big.BoxAlignment.END});
this._moreAppsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
font_name: "Sans Bold 14px",
text: "More...",
height: LABEL_HEIGHT });
moreAppsBox.append(this._moreAppsLink.actor, Big.BoxPackFlags.EXPAND);
this._appsSection.append(moreAppsBox, Big.BoxPackFlags.EXPAND);
this.actor.add_actor(this._appsSection);
this._appsSectionDefaultHeight = this._appsSection.height;
this._appsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
this._appsDisplayControlBox.append(this._appDisplay.displayControl, Big.BoxPackFlags.NONE);
this._docsSection = new Big.Box({ x: SIDESHOW_PAD,
y: this._appsSection.y + this._appsSection.height,
padding_top: SIDESHOW_SECTION_PADDING_TOP,
spacing: SIDESHOW_SECTION_SPACING});
this._docsText = new Clutter.Text({ color: SIDESHOW_TEXT_COLOR,
font_name: "Sans Bold 14px",
text: "Recent Documents",
height: LABEL_HEIGHT});
this._docsSection.append(this._docsText, Big.BoxPackFlags.EXPAND);
this._docDisplay = new DocDisplay.DocDisplay(this._displayWidth, this._itemDisplayHeight - this._appsContent.height, SIDESHOW_COLUMNS, SIDESHOW_PAD);
this._docsSection.append(this._docDisplay.actor, Big.BoxPackFlags.EXPAND);
let moreDocsBox = new Big.Box({x_align: Big.BoxAlignment.END});
this._moreDocsLink = new Link.Link({ color: SIDESHOW_TEXT_COLOR,
font_name: "Sans Bold 14px",
text: "More...",
height: LABEL_HEIGHT });
moreDocsBox.append(this._moreDocsLink.actor, Big.BoxPackFlags.EXPAND);
this._docsSection.append(moreDocsBox, Big.BoxPackFlags.EXPAND);
this.actor.add_actor(this._docsSection);
this._docsSectionDefaultHeight = this._docsSection.height;
this._docsDisplayControlBox = new Big.Box({x_align: Big.BoxAlignment.CENTER});
this._docsDisplayControlBox.append(this._docDisplay.displayControl, Big.BoxPackFlags.NONE);
this._details = new Big.Box({ x: this._width + this._additionalWidth + SIDESHOW_SECTION_SPACING,
y: Panel.PANEL_HEIGHT + SIDESHOW_PAD,
width: previewWidth,
height: previewHeight,
corner_radius: DETAILS_CORNER_RADIUS,
border: DETAILS_BORDER_WIDTH,
border_color: DETAILS_BORDER_COLOR,
padding: DETAILS_PADDING});
this._appDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
this._docDisplay.setAvailableDimensionsForItemDetails(previewWidth - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2,
previewHeight - DETAILS_PADDING * 2 - DETAILS_BORDER_WIDTH * 2);
/* Proxy the activated signals */
this._appDisplay.connect('activated', function(appDisplay) {
me.emit('activated');
});
this._docDisplay.connect('activated', function(docDisplay) {
me.emit('activated');
});
this._appDisplay.connect('selected', function(appDisplay) {
// We allow clicking on any item to select it, so if an
// item in the app display is selected, we need to make sure that
// no item in the doc display has the selection.
me._docDisplay.unsetSelected();
me._docDisplay.hidePreview();
});
this._docDisplay.connect('selected', function(docDisplay) {
// We allow clicking on any item to select it, so if an
// item in the doc display is selected, we need to make sure that
// no item in the app display has the selection.
me._appDisplay.unsetSelected();
me._appDisplay.hidePreview();
});
this._appDisplay.connect('redisplayed', function(appDisplay) {
me._ensureItemSelected();
});
this._docDisplay.connect('redisplayed', function(docDisplay) {
me._ensureItemSelected();
});
this._moreAppsLink.connect('clicked',
function(o, event) {
if (me._moreAppsMode) {
me._unsetMoreAppsMode();
} else {
me._setMoreAppsMode();
}
});
this._moreDocsLink.connect('clicked',
function(o, event) {
if (me._moreDocsMode) {
me._unsetMoreDocsMode();
} else {
me._setMoreDocsMode();
}
});
},
show: function() {
let global = Shell.Global.get();
this._appDisplay.show();
this._appsContent.show();
this._docDisplay.show();
this._appDisplay.selectFirstItem();
if (!this._appDisplay.hasSelected())
this._docDisplay.selectFirstItem();
else
this._docDisplay.unsetSelected();
global.stage.set_key_focus(this._searchEntry.entry);
},
hide: function() {
this._appsContent.hide();
this._docDisplay.hide();
this._searchEntry.entry.text = '';
this._unsetMoreAppsMode();
this._unsetMoreDocsMode();
},
// Ensures that one of the displays has the selection if neither owns it after the
// latest redisplay. This can be applicable if the display that earlier had the
// selection no longer has any items, or if their is a single section being shown
// in the expanded view and it went from having no matching items to having some.
// We first try to place the selection in the applications section, because it is
// displayed above the documents section.
_ensureItemSelected: function() {
if (!this._appDisplay.hasSelected() && !this._docDisplay.hasSelected()) {
if (this._appDisplay.hasItems()) {
this._appDisplay.selectFirstItem();
} else if (this._docDisplay.hasItems()) {
this._docDisplay.selectFirstItem();
}
}
},
// Sets the 'More' mode for browsing applications. Updates the applications section to have more items.
// Slides down the documents section to reveal the additional applications.
_setMoreAppsMode: function() {
if (this._moreAppsMode)
return;
// No corresponding STATE_PENDING_ACTIVE, because we call updateAppsSection
// immediately below.
this._moreAppsMode = STATE_ACTIVE;
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
this._moreAppsLink.actor.hide();
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
// Move the selection to the applications section if it was in the docs section.
this._docDisplay.unsetSelected();
// Because we have menus in applications, we want to reset the selection for applications
// as well. The default is no menu.
this._appDisplay.unsetSelected();
this._updateAppsSection();
Tweener.addTween(this._docsSection,
{ y: this._docsSection.y + this._docsSection.height,
clipHeightBottom: 0,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
// We need to expand the clip on the applications section so that the first additional
// application to be displayed does not appear abruptly.
Tweener.addTween(this._appsSection,
{ clipHeightBottom: this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT * 2 - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onAppsSectionExpanded,
onCompleteScope: this
});
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
Tweener.addTween(this.actor,
{ clipWidthRight: this._expandedWidth,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this.emit('more-activated');
},
// Unsets the 'More' mode for browsing applications. Slides in the documents section.
_unsetMoreAppsMode: function() {
if (!this._moreAppsMode)
return;
this._moreAppsMode = STATE_PENDING_INACTIVE;
this._moreAppsLink.actor.hide();
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
this._docDisplay.show();
// We need to be reducing the clip on the applications section so that the last application to
// be removed does not disappear abruptly.
Tweener.addTween(this._appsSection,
{ clipHeightBottom: this._appsSectionDefaultHeight - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onAppsSectionReduced,
onCompleteScope: this
});
Tweener.addTween(this._docsSection,
{ y: this._docsSection.y - this._docsSection.height,
clipHeightBottom: this._docsSection.height,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
Tweener.addTween(this.actor,
{ clipWidthRight: this._width,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this.emit('less-activated');
},
// Removes the clip from the applications section to reveal the 'Less...' text.
// Hides the documents section so that it doesn't get updated on new searches.
_onAppsSectionExpanded: function() {
this._appsSection.remove_clip();
this._docDisplay.hide();
this.actor.remove_clip();
},
// Updates the applications section to contain fewer items. Selects the first item in the
// documents section if applications section has no items.
// Removes the clip from the applications section to reveal the 'More...' text.
// Removes the clip from the documents section, so that the clip does not limit the size of
// the section if it is expanded later.
_onAppsSectionReduced: function() {
this.actor.remove_clip();
if (this._moreAppsMode != STATE_PENDING_INACTIVE)
return;
this._moreAppsMode = STATE_INACTIVE;
this._updateAppsSection();
if (!this._appDisplay.hasItems())
this._docDisplay.selectFirstItem();
this._appsSection.remove_clip();
this._docsSection.remove_clip();
},
// Updates the applications section display and the 'More...' or 'Less...' control associated with it
// depending on the current mode. This function must only be called once after the 'More' mode has been
// changed, which is ensured by _setMoreAppsMode() and _unsetMoreAppsMode() functions.
_updateAppsSection: function() {
if (this._moreAppsMode) {
// Subtract one from columns since we are displaying menus
this._appDisplay.setExpanded(true, this._displayWidth, this._additionalWidth,
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
this._expandedSideshowColumns - 1);
this._moreAppsLink.setText("Less...");
this._appsSection.insert_after(this._appsDisplayControlBox, this._appsContent, Big.BoxPackFlags.NONE);
this.actor.add_actor(this._details);
this._details.append(this._appDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
} else {
this._appDisplay.setExpanded(false, this._displayWidth, 0,
this._appsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT,
SIDESHOW_COLUMNS);
this._moreAppsLink.setText("More...");
this._appsSection.remove_actor(this._appsDisplayControlBox);
this.actor.remove_actor(this._details);
this._details.remove_all();
}
this._moreAppsLink.actor.show();
},
// Sets the 'More' mode for browsing documents. Updates the documents section to have more items.
// Slides up the applications section and the documents section at the same time to reveal the additional
// documents.
_setMoreDocsMode: function() {
if (this._moreDocsMode)
return;
this._moreDocsMode = true;
if (!this._appsSection.has_clip)
this._appsSection.set_clip(0, 0, this._appsSection.width, this._appsSection.height);
this._moreDocsLink.actor.hide();
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
// Move the selection to the docs section if it was in the apps section.
this._appDisplay.unsetSelected();
if (!this._docDisplay.hasSelected())
this._docDisplay.selectFirstItem();
this._updateDocsSection();
Tweener.addTween(this._appsSection,
{ y: this._appsSection.y - this._appsSection.height,
clipHeightTop: 0,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
// We do not slide in the 'Less...' text along with the documents so that the documents appear from the same
// edge where the last document was displayed, and not have that edge gradually move over to where the 'Less'
// text is displayed.
Tweener.addTween(this._docsSection,
{ y: this._searchEntry.actor.y + this._searchEntry.actor.height,
clipHeightBottom: this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT * 2 - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onDocsSectionExpanded,
onCompleteScope: this
});
Tweener.addTween(this.actor,
{ clipWidthRight: this._expandedWidth,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this.emit('more-activated');
},
// Unsets the 'More' mode for browsing documents. Slides in the applications section
// and slides down the documents section.
_unsetMoreDocsMode: function() {
if (!this._moreDocsMode)
return;
this._moreDocsMode = false;
this._moreDocsLink.actor.hide();
this._docsSection.set_clip(0, 0, this._docsSection.width, this._docsSection.height);
this.actor.set_clip(0, 0, this.actor.width, this.actor.height);
this._appsContent.show();
Tweener.addTween(this._docsSection,
{ y: this._docsSection.y + this._appsSectionDefaultHeight,
clipHeightBottom: this._docsSectionDefaultHeight - LABEL_HEIGHT - SIDESHOW_SECTION_SPACING,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onDocsSectionReduced,
onCompleteScope: this
});
Tweener.addTween(this._appsSection,
{ y: this._appsSection.y + this._appsSection.height,
clipHeightTop: this._appsSection.height,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
Tweener.addTween(this.actor,
{ clipWidthRight: this._width,
time: ANIMATION_TIME,
transition: "easeOutQuad"
});
this.emit('less-activated');
},
// Removes the clip from the documents section to reveal the 'Less...' text.
// Hides the applications section so that it doesn't get updated on new searches.
_onDocsSectionExpanded: function() {
this._docsSection.remove_clip();
this._appsContent.hide();
this.actor.remove_clip();
},
// Updates the documents section to contain fewer items. Selects the first item in the
// applications section if applications section has no items.
// Removes the clip from the documents section to reveal the 'More...' text.
// Removes the clip from the applications section, so that the clip does not limit the size of
// the section if it is expanded later.
_onDocsSectionReduced: function() {
this.actor.remove_clip();
this._updateDocsSection();
if (!this._docDisplay.hasItems())
this._appDisplay.selectFirstItem();
this._docsSection.remove_clip();
this._appsSection.remove_clip();
},
// Updates the documents section display and the 'More...' or 'Less...' control associated with it
// depending on the current mode. This function must only be called once after the 'More' mode has been
// changed, which is ensured by _setMoreDocsMode() and _unsetMoreDocsMode() functions.
_updateDocsSection: function() {
if (this._moreDocsMode) {
this._docDisplay.setExpanded(true, this._displayWidth, this._additionalWidth,
this._itemDisplayHeight + SIDESHOW_SECTION_MISC_HEIGHT,
this._expandedSideshowColumns);
this._moreDocsLink.setText("Less...");
this._docsSection.insert_after(this._docsDisplayControlBox, this._docDisplay.actor, Big.BoxPackFlags.NONE);
this.actor.add_actor(this._details);
this._details.append(this._docDisplay.selectedItemDetails, Big.BoxPackFlags.NONE);
} else {
this._docDisplay.setExpanded(false, this._displayWidth, 0,
this._docsSectionDefaultHeight - SIDESHOW_SECTION_MISC_HEIGHT,
SIDESHOW_COLUMNS);
this._moreDocsLink.setText("More...");
this._docsSection.remove_actor(this._docsDisplayControlBox);
this.actor.remove_actor(this._details);
this._details.remove_all();
}
this._moreDocsLink.actor.show();
}
};
Signals.addSignalMethods(Sideshow.prototype);
function Overlay() {
this._init();
}
Overlay.prototype = {
_init : function() {
let me = this;
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
// different visual components.
if (wideScreen) {
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
} else {
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
}
this._group = new Clutter.Group();
this._group._delegate = this;
this.visible = false;
this._hideInProgress = false;
// A scaled root pixmap actor is used as a background. It is zoomed in
// to the lower right intersection of the lines that divide the image
// evenly in a 3x3 grid. This is based on the rule of thirds, a
// compositional rule of thumb in visual arts. The choice for the
// lower right point is based on a quick survey of GNOME wallpapers.
let background = global.create_root_pixmap_actor();
background.width = global.screen_width * BACKGROUND_SCALE;
background.height = global.screen_height * BACKGROUND_SCALE;
background.x = -global.screen_width * (4 * BACKGROUND_SCALE - 3) / 6;
background.y = -global.screen_height * (4 * BACKGROUND_SCALE - 3) / 6;
this._group.add_actor(background);
// Draw a semitransparent rectangle over the background for readability.
let backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR,
width: global.screen_width,
height: global.screen_height - Panel.PANEL_HEIGHT,
y: Panel.PANEL_HEIGHT });
this._group.add_actor(backOver);
this._group.hide();
global.overlay_group.add_actor(this._group);
// TODO - recalculate everything when desktop size changes
this._sideshow = new Sideshow();
this._group.add_actor(this._sideshow.actor);
this._workspaces = null;
this._sideshow.connect('activated', function(sideshow) {
// TODO - have some sort of animation/effect while
// transitioning to the new app. We definitely need
// startup-notification integration at least.
me.hide();
});
this._sideshow.connect('more-activated', function(sideshow) {
if (me._workspaces != null) {
let asideXFactor = wideScreen ? WORKSPACES_X_FACTOR_ASIDE_MODE_WIDE_SCREEN : WORKSPACES_X_FACTOR_ASIDE_MODE_REGULAR_SCREEN;
let workspacesX = displayGridColumnWidth * asideXFactor + WORKSPACE_GRID_PADDING;
me._workspaces.addButton.hide();
me._workspaces.updatePosition(workspacesX, null);
}
});
this._sideshow.connect('less-activated', function(sideshow) {
if (me._workspaces != null) {
let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
me._workspaces.addButton.show();
me._workspaces.updatePosition(workspacesX, null);
}
});
},
//// Draggable target interface ////
// Unsets the expanded display mode if a GenericDisplayItem is being
// dragged over the overlay, i.e. as soon as it starts being dragged.
// This slides the workspaces back in and allows the user to place
// the item on any workspace.
handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem) {
this._sideshow._unsetMoreAppsMode();
this._sideshow._unsetMoreDocsMode();
return true;
}
return false;
},
//// Public methods ////
show : function() {
if (this.visible)
return;
if (!Main.startModal())
return;
this.visible = true;
let global = Shell.Global.get();
let screenWidth = global.screen_width;
let screenHeight = global.screen_height;
this._sideshow.show();
let columnsUsed = wideScreen ? COLUMNS_FOR_WORKSPACES_WIDE_SCREEN : COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN;
let rowsUsed = wideScreen ? ROWS_FOR_WORKSPACES_WIDE_SCREEN : ROWS_FOR_WORKSPACES_REGULAR_SCREEN;
let workspacesWidth = displayGridColumnWidth * columnsUsed - WORKSPACE_GRID_PADDING * 2;
// We scale the vertical padding by (screenHeight / screenWidth) so that the workspace preserves its aspect ratio.
let workspacesHeight = displayGridRowHeight * rowsUsed - WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
let workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
let workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
// place the 'Add Workspace' button in the bottom row of the grid
let addButtonSize = Math.floor(displayGridRowHeight * 3/5);
let addButtonX = workspacesX + workspacesWidth - addButtonSize;
let addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
this._workspaces = new Workspaces.Workspaces(workspacesWidth, workspacesHeight, workspacesX, workspacesY,
addButtonSize, addButtonX, addButtonY);
this._group.add_actor(this._workspaces.actor);
// All the the actors in the window group are completely obscured,
// hiding the group holding them while the overlay is displayed greatly
// increases performance of the overlay especially when there are many
// windows visible.
//
// If we switched to displaying the actors in the overlay rather than
// clones of them, this would obviously no longer be necessary.
global.window_group.hide();
this._group.show();
// Try to make the menu not too visible behind the empty space between
// the workspace previews by sliding in its clipping rectangle.
// We want to finish drawing the sideshow just before the top workspace fully
// slides in on the top. Which means that we have more time to wait before
// drawing the sideshow if the active workspace is displayed on the bottom of
// the workspaces grid, and almost no time to wait if it is displayed in the top
// row of the workspaces grid. The calculations used below try to roughly
// capture the animation ratio for when workspaces are covering the top of the overlay
// vs. when workspaces are already below the top of the overlay, and apply it
// to clipping the sideshow. The clipping is removed in this._showDone().
this._sideshow.actor.set_clip(0, 0,
this._workspaces.getFullSizeX(),
this._sideshow.actor.height);
Tweener.addTween(this._sideshow.actor,
{ clipWidthRight: this._sideshow._width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._showDone,
onCompleteScope: this
});
this.emit('showing');
},
hide : function() {
if (!this.visible || this._hideInProgress)
return;
let global = Shell.Global.get();
this._hideInProgress = true;
// lower the sideshow, so that workspaces display is on top and covers the sideshow while it is sliding out
this._sideshow.actor.lower(this._workspaces.actor);
this._workspaces.hide();
// Try to make the menu not too visible behind the empty space between
// the workspace previews by sliding in its clipping rectangle.
// The logic used is the same as described in this.show(). If the active workspace
// is displayed in the top row, than almost full animation time is needed for it
// to reach the top of the overlay and cover the sideshow fully, while if the
// active workspace is in the lower row, than the top left workspace reaches the
// top of the overlay sooner as it is moving out of the way.
// The clipping is removed in this._hideDone().
this._sideshow.actor.set_clip(0, 0,
this._sideshow.actor.width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
this._sideshow.actor.height);
Tweener.addTween(this._sideshow.actor,
{ clipWidthRight: this._workspaces.getFullSizeX() + this._workspaces.getWidthToTopActiveWorkspace() - global.screen_width,
time: ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._hideDone,
onCompleteScope: this
});
this.emit('hiding');
},
toggle: function() {
if (this.visible)
this.hide();
else
this.show();
},
//// Private methods ////
// Raises the sideshow to the top, so that we can tell if the pointer is above one of its items.
// We need to do this once the workspaces are shown because the workspaces actor currently covers
// the whole screen, regardless of where the workspaces are actually displayed.
//
// Once we rework the workspaces actor to only cover the area it actually needs, we can
// remove this workaround. Also http://bugzilla.openedhand.com/show_bug.cgi?id=1513 requests being
// able to pick only a reactive actor at a certain position, rather than any actor. Being able
// to do that would allow us to not have to raise the sideshow.
_showDone: function() {
if (this._hideInProgress)
return;
this._sideshow.actor.raise_top();
this._sideshow.actor.remove_clip();
this.emit('shown');
},
_hideDone: function() {
let global = Shell.Global.get();
global.window_group.show();
this._workspaces.destroy();
this._workspaces = null;
this._sideshow.actor.remove_clip();
this._sideshow.hide();
this._group.hide();
this.visible = false;
this._hideInProgress = false;
Main.endModal();
this.emit('hidden');
}
};
Signals.addSignalMethods(Overlay.prototype);
Tweener.registerSpecialProperty("clipHeightBottom", _clipHeightBottomGet, _clipHeightBottomSet);
function _clipHeightBottomGet(actor) {
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
return clipHeight;
}
function _clipHeightBottomSet(actor, clipHeight) {
actor.set_clip(0, 0, actor.width, clipHeight);
}
Tweener.registerSpecialProperty("clipHeightTop", _clipHeightTopGet, _clipHeightTopSet);
function _clipHeightTopGet(actor) {
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
return clipHeight;
}
function _clipHeightTopSet(actor, clipHeight) {
actor.set_clip(0, actor.height - clipHeight, actor.width, clipHeight);
}
Tweener.registerSpecialProperty("clipWidthRight", _clipWidthRightGet, _clipWidthRightSet);
function _clipWidthRightGet(actor) {
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
return clipWidth;
}
function _clipWidthRightSet(actor, clipWidth) {
actor.set_clip(0, 0, clipWidth, actor.height);
}

480
js/ui/overview.js Normal file
View File

@ -0,0 +1,480 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay;
const GenericDisplay = imports.ui.genericDisplay;
const Link = imports.ui.link;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Dash = imports.ui.dash;
const Tweener = imports.ui.tweener;
const Workspaces = imports.ui.workspaces;
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
// Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25;
// We divide the screen into a grid of rows and columns, which we use
// to help us position the Overview components, such as the side panel
// that lists applications and documents, the workspaces display, and
// the button for adding additional workspaces.
// In the regular mode, the side panel takes up one column on the left,
// and the workspaces display takes up the remaining columns.
// In the expanded side panel display mode, the side panel takes up two
// columns, and the workspaces display slides all the way to the right,
// being visible only in the last quarter of the right-most column.
// In the future, this mode will have more components, such as a display
// of documents which were recently opened with a given application, which
// will take up the remaining sections of the display.
const WIDE_SCREEN_CUT_OFF_RATIO = 1.4;
const COLUMNS_REGULAR_SCREEN = 4;
const ROWS_REGULAR_SCREEN = 8;
const COLUMNS_WIDE_SCREEN = 5;
const ROWS_WIDE_SCREEN = 10;
const DEFAULT_PADDING = 4;
// Padding around workspace grid / Spacing between Dash and Workspaces
const WORKSPACE_GRID_PADDING = 12;
const COLUMNS_FOR_WORKSPACES_REGULAR_SCREEN = 3;
const ROWS_FOR_WORKSPACES_REGULAR_SCREEN = 6;
const COLUMNS_FOR_WORKSPACES_WIDE_SCREEN = 4;
const ROWS_FOR_WORKSPACES_WIDE_SCREEN = 8;
// A multi-state; PENDING is used during animations
const STATE_ACTIVE = true;
const STATE_PENDING_INACTIVE = false;
const STATE_INACTIVE = false;
const SHADOW_COLOR = new Clutter.Color();
SHADOW_COLOR.from_pixel(0x00000033);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const SHADOW_WIDTH = 6;
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
let addRemoveButtonSize = null;
function Overview() {
this._init();
}
Overview.prototype = {
_init : function() {
this._group = new Clutter.Group();
this._group._delegate = this;
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
this._recalculateGridSizes();
this._activeDisplayPane = null;
// 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 });
this._group.add_actor(this._transparentBackground);
// Background color for the Overview
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERVIEW_COLOR });
this._group.add_actor(this._backOver);
this._group.hide();
global.overlay_group.add_actor(this._group);
// TODO - recalculate everything when desktop size changes
this._dash = new Dash.Dash();
this._group.add_actor(this._dash.actor);
// Container to hold popup pane chrome.
this._paneContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 6
});
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
// inside the notify::visible handler on panes.
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
this._activeDisplayPane.close();
return true;
}));
this._group.add_actor(this._paneContainer);
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._coverPane.lower_bottom();
this._workspaces = null;
},
_recalculateGridSizes: function () {
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
// different visual components.
if (wideScreen) {
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
} else {
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
}
},
relayout: function () {
let screenHeight = global.screen_height;
let screenWidth = global.screen_width;
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;
this._workspacesWidth = displayGridColumnWidth * workspaceColumnsUsed
- WORKSPACE_GRID_PADDING * 2;
// We scale the vertical padding by (screenHeight / screenWidth)
// so that the workspace preserves its aspect ratio.
this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
- WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
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
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, contentY);
this._backOver.set_size(global.screen_width, contentHeight);
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
contentY);
// Dynamic width
this._paneContainer.height = contentHeight;
this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
this._transparentBackground.set_size(global.screen_width - this._paneContainer.x,
this._paneContainer.height);
if (this._activeDisplayPane != null)
this._activeDisplayPane.actor.width = displayGridColumnWidth * 2;
},
addPane: function (pane) {
this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
// When a pane is displayed, we raise the transparent background to the top
// and connect to button-release-event on it, then raise the pane above that.
// The idea here is that clicking anywhere outside the pane should close it.
// When the active pane is closed, undo the effect.
let backgroundEventId = null;
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (isOpen) {
pane.actor.width = displayGridColumnWidth * 2;
this._activeDisplayPane = pane;
this._transparentBackground.raise_top();
this._paneContainer.raise_top();
if (backgroundEventId != null)
this._transparentBackground.disconnect(backgroundEventId);
backgroundEventId = this._transparentBackground.connect('button-release-event', Lang.bind(this, function () {
this._activeDisplayPane.close();
return true;
}));
} else if (pane == this._activeDisplayPane) {
this._activeDisplayPane = null;
if (backgroundEventId != null) {
this._transparentBackground.disconnect(backgroundEventId);
backgroundEventId = null;
}
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
}
}));
},
//// Draggable target interface ////
// Closes any active panes if a GenericDisplayItem is being
// dragged over the Overview, i.e. as soon as it starts being dragged.
// This allows the user to place the item on any workspace.
handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem
|| source instanceof AppDisplay.BaseWellItem) {
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
return true;
}
return false;
},
//// Public methods ////
// Returns the scale the Overview has when we just start zooming out
// to overview mode. That is, when just the active workspace is showing.
getZoomedInScale : function() {
return 1 / this._workspaces.getScale();
},
// Returns the position the Overview has when we just start zooming out
// to overview mode. That is, when just the active workspace is showing.
getZoomedInPosition : function() {
let [posX, posY] = this._workspaces.getActiveWorkspacePosition();
let scale = this.getZoomedInScale();
return [- posX * scale, - posY * scale];
},
// Returns the current scale of the Overview.
getScale : function() {
return this._group.scaleX;
},
// Returns the current position of the Overview.
getPosition : function() {
return [this._group.x, this._group.y];
},
show : function() {
if (this.visible)
return;
Main.pushModal(this._dash.actor);
this.visible = true;
this.animationInProgress = true;
this._dash.show();
/* TODO: make this stuff dynamic */
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
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
// for drag and drop to work. In the future we should fix the workspaces to not
// 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
// windows visible.
//
// If we switched to displaying the actors in the Overview rather than
// clones of them, this would obviously no longer be necessary.
global.window_group.hide();
this._group.show();
// Create a zoom out effect. First scale the Overview group up and
// position it so that the active workspace fills up the whole screen,
// then transform the group to its normal dimensions and position.
// The opposite transition is used in hide().
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
[this._group.x, this._group.y] = this.getZoomedInPosition();
Tweener.addTween(this._group,
{ x: 0,
y: 0,
scaleX: 1,
scaleY: 1,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._showDone,
onCompleteScope: this
});
// Make Dash fade in so that it doesn't appear to big.
this._dash.actor.opacity = 0;
Tweener.addTween(this._dash.actor,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME
});
this._coverPane.raise_top();
this.emit('showing');
},
hide: function() {
if (!this.visible || this._hideInProgress)
return;
this.animationInProgress = true;
this._hideInProgress = true;
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
this._workspaces.hide();
// Create a zoom in effect by transforming the Overview group so that
// the active workspace fills up the whole screen. The opposite
// transition is used in show().
let scale = this.getZoomedInScale();
let [posX, posY] = this.getZoomedInPosition();
Tweener.addTween(this._group,
{ x: posX,
y: posY,
scaleX: scale,
scaleY: scale,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onCompleteScope: this
});
// Make Dash fade out so that it doesn't appear to big.
Tweener.addTween(this._dash.actor,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME
});
this._coverPane.raise_top();
this.emit('hiding');
},
toggle: function() {
if (this.visible)
this.hide();
else
this.show();
},
/**
* getWorkspacesForWindow:
* @metaWindow: A #MetaWindow
*
* Returns the Workspaces object associated with the given window.
* This method is not be accessible if the overview is not open
* and will return %null.
*/
getWorkspacesForWindow: function(metaWindow) {
return this._workspaces;
},
/**
* activateWindow:
* @metaWindow: A #MetaWindow
* @time: Event timestamp integer
*
* Make the given MetaWindow be the focus window, switching
* to the workspace it's on if necessary. This function
* should only be used when the Overview is currently active;
* outside of that, use the relevant methods on MetaDisplay.
*/
activateWindow: function (metaWindow, time) {
this._workspaces.activateWindowFromOverview(metaWindow, time);
},
//// Private methods ////
_showDone: function() {
if (this._hideInProgress)
return;
this.animationInProgress = false;
this._coverPane.lower_bottom();
this.emit('shown');
},
_hideDone: function() {
global.window_group.show();
this._workspaces.destroy();
this._workspaces = null;
this._dash.hide();
this._group.hide();
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
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

@ -7,35 +7,48 @@ const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Tweener = imports.ui.tweener;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Button = imports.ui.button;
const Main = imports.ui.main;
const PANEL_HEIGHT = 32;
const PANEL_HEIGHT = 26;
const TRAY_HEIGHT = PANEL_HEIGHT - 1;
const SHADOW_HEIGHT = 6;
// The panel has a transparent white background with a gradient.
const PANEL_TOP_COLOR = new Clutter.Color();
PANEL_TOP_COLOR.from_pixel(0xffffff99);
const PANEL_MIDDLE_COLOR = new Clutter.Color();
PANEL_MIDDLE_COLOR.from_pixel(0xffffff88);
const PANEL_BOTTOM_COLOR = new Clutter.Color();
PANEL_BOTTOM_COLOR.from_pixel(0xffffffaa);
const DEFAULT_PADDING = 4;
const PANEL_ICON_SIZE = 24;
const BACKGROUND_TOP = new Clutter.Color();
BACKGROUND_TOP.from_pixel(0x161616ff);
const BACKGROUND_BOTTOM = new Clutter.Color();
BACKGROUND_BOTTOM.from_pixel(0x000000ff);
const PANEL_FOREGROUND_COLOR = new Clutter.Color();
PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
const SN_BACKGROUND_COLOR = new Clutter.Color();
SN_BACKGROUND_COLOR.from_pixel(0xffff00a0);
const SHADOW_COLOR = new Clutter.Color();
SHADOW_COLOR.from_pixel(0x00000033);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
// Darken (pressed) buttons; lightening has no effect on white backgrounds.
// Don't make the mouse hover effect visible to the user for a menu feel.
const PANEL_BUTTON_COLOR = new Clutter.Color();
PANEL_BUTTON_COLOR.from_pixel(0x00000015);
PANEL_BUTTON_COLOR.from_pixel(0x00000000);
// Lighten pressed buttons; darkening has no effect on a black background.
const PRESSED_BUTTON_BACKGROUND_COLOR = new Clutter.Color();
PRESSED_BUTTON_BACKGROUND_COLOR.from_pixel(0x00000030);
PRESSED_BUTTON_BACKGROUND_COLOR.from_pixel(0x324c6ffa);
const DEFAULT_FONT = 'Sans 16px';
const TRAY_PADDING = 0;
const TRAY_SPACING = 2;
// See comments around _recomputeTraySize
const TRAY_SPACING = 14;
const TRAY_SPACING_MIN = 8;
// Used for the tray icon container with gtk pre-2.16, which doesn't
// fully support tray icon transparency
@ -46,84 +59,277 @@ TRAY_BORDER_COLOR.from_pixel(0x00000033);
const TRAY_CORNER_RADIUS = 5;
const TRAY_BORDER_WIDTH = 0;
function AppPanelMenu() {
this._init();
}
AppPanelMenu.prototype = {
_init: function() {
this._metaDisplay = global.screen.get_display();
this._focusedApp = null;
this._activeSequence = null;
this._startupSequences = {};
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_PADDING,
y_align: Big.BoxAlignment.CENTER });
this._iconBox = new Big.Box({ width: PANEL_ICON_SIZE, height: PANEL_ICON_SIZE,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER });
this.actor.append(this._iconBox, Big.BoxPackFlags.NONE);
let labelBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
this._label = new Clutter.Text({ font_name: DEFAULT_FONT,
color: PANEL_FOREGROUND_COLOR,
text: "" });
labelBox.append(this._label, Big.BoxPackFlags.EXPAND);
this.actor.append(labelBox, Big.BoxPackFlags.NONE);
this._startupBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
this.actor.append(this._startupBox, Big.BoxPackFlags.NONE);
Main.overview.connect('hiding', Lang.bind(this, function () {
this.actor.opacity = 255;
}));
Main.overview.connect('showing', Lang.bind(this, function () {
this.actor.opacity = 192;
}));
this._metaDisplay.connect('notify::focus-window', Lang.bind(this, this._sync));
let appMonitor = Shell.AppMonitor.get_default();
appMonitor.connect('startup-sequence-changed', Lang.bind(this, this._sync));
// For now just resync on application add/remove; this is mainly to handle
// cases where the focused window's application changes without the focus
// changing. An example case is how we map Firefox based on the window
// title which is a dynamic property.
appMonitor.connect('app-added', Lang.bind(this, this._sync));
appMonitor.connect('app-removed', Lang.bind(this, this._sync));
this._sync();
},
_sync: function() {
let appMonitor = Shell.AppMonitor.get_default();
let focusWindow = this._metaDisplay.get_focus_window();
let focusedApp;
if (focusWindow == null) {
focusedApp = null;
} else {
focusedApp = appMonitor.get_window_app(focusWindow);
}
let lastSequence = null;
if (focusedApp == null) {
let sequences = appMonitor.get_startup_sequences();
if (sequences.length > 0)
lastSequence = sequences[sequences.length - 1];
}
// If the currently focused app hasn't changed and the current
// startup sequence hasn't changed, we have nothing to do
if (focusedApp == this._focusedApp
&& ((lastSequence == null && this._activeSequence == null)
|| (lastSequence != null && this._activeSequence != null
&& lastSequence.get_id() == this._activeSequence.get_id())))
return;
this._focusedApp = focusedApp;
this._activeSequence = lastSequence;
this._iconBox.remove_all();
this._iconBox.hide();
this._label.text = '';
if (this._focusedApp != null) {
let icon = focusedApp.create_icon_texture(PANEL_ICON_SIZE);
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
this._iconBox.show();
this._label.text = focusedApp.get_name();
} else if (this._activeSequence != null) {
let icon = this._activeSequence.create_icon(PANEL_ICON_SIZE);
this._iconBox.append(icon, Big.BoxPackFlags.NONE);
this._iconBox.show();
this._label.text = this._activeSequence.get_name();
}
this.emit('changed');
}
}
Signals.addSignalMethods(AppPanelMenu.prototype);
function Panel() {
this._init();
}
Panel.prototype = {
_init : function() {
let global = Shell.Global.get();
// Put the background under the panel within a group.
this.actor = new Clutter.Group();
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL
});
let backgroundGradient = Shell.create_vertical_gradient(BACKGROUND_TOP,
BACKGROUND_BOTTOM);
this.actor.connect('notify::allocation', Lang.bind(this, function () {
let [width, height] = this.actor.get_size();
backgroundGradient.set_size(width, height);
}));
this.actor.add_actor(backgroundGradient);
// Create backBox, which contains two boxes, backUpper and backLower,
// for the background gradients and one for the shadow. The shadow at
// the bottom has a fixed height (packing flag NONE), and the rest of
// the height above is divided evenly between backUpper and backLower
// (with packing flag EXPAND).
let backBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x: 0,
y: 0,
width: global.screen_width,
height: PANEL_HEIGHT + SHADOW_HEIGHT });
let backUpper = global.create_vertical_gradient(PANEL_TOP_COLOR,
PANEL_MIDDLE_COLOR);
let backLower = global.create_vertical_gradient(PANEL_MIDDLE_COLOR,
PANEL_BOTTOM_COLOR);
let shadow = global.create_vertical_gradient(SHADOW_COLOR,
TRANSPARENT_COLOR);
shadow.set_height(SHADOW_HEIGHT + 1);
backBox.append(backUpper, Big.BoxPackFlags.EXPAND);
backBox.append(backLower, Big.BoxPackFlags.EXPAND);
backBox.append(shadow, Big.BoxPackFlags.NONE);
this.actor.add_actor(backBox);
this._leftBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
spacing: DEFAULT_PADDING,
padding_right: DEFAULT_PADDING });
this._centerBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER });
this._rightBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER,
padding_left: DEFAULT_PADDING });
let box = new Big.Box({ x: 0,
y: 0,
height: PANEL_HEIGHT,
width: global.screen_width,
orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4 });
/* This box container ensures that the centerBox is positioned in the *absolute*
* center, but can be pushed aside if necessary. */
this._boxContainer = new Shell.GenericContainer();
this.actor.append(this._boxContainer, Big.BoxPackFlags.EXPAND);
this._boxContainer.add_actor(this._leftBox);
this._boxContainer.add_actor(this._centerBox);
this._boxContainer.add_actor(this._rightBox);
this._boxContainer.connect('get-preferred-width', Lang.bind(this, function(box, forHeight, alloc) {
let children = box.get_children();
for (let i = 0; i < children.length; i++) {
let [childMin, childNatural] = children[i].get_preferred_width(forHeight);
alloc.min_size += childMin;
alloc.natural_size += childNatural;
}
}));
this._boxContainer.connect('get-preferred-height', Lang.bind(this, function(box, forWidth, alloc) {
let children = box.get_children();
for (let i = 0; i < children.length; i++) {
let [childMin, childNatural] = children[i].get_preferred_height(forWidth);
if (childMin > alloc.min_size)
alloc.min_size = childMin;
if (childNatural > alloc.natural_size)
alloc.natural_size = childNatural;
}
}));
this._boxContainer.connect('allocate', Lang.bind(this, function(container, box, flags) {
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
let leftWidth, centerWidth, rightWidth;
if (allocWidth < (leftNaturalWidth + centerNaturalWidth + rightNaturalWidth)) {
leftWidth = leftMinWidth;
centerWidth = centerMinWidth;
rightWidth = rightMinWidth;
} else {
leftWidth = leftNaturalWidth;
centerWidth = centerNaturalWidth;
rightWidth = rightNaturalWidth;
}
this.button = new Button.Button("Activities", PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, true, null, PANEL_HEIGHT);
let x;
let childBox = new Clutter.ActorBox();
childBox.x1 = box.x1;
childBox.y1 = box.y1;
childBox.x2 = x = childBox.x1 + leftWidth;
childBox.y2 = box.y2;
this._leftBox.allocate(childBox, flags);
box.append(this.button.button, Big.BoxPackFlags.NONE);
let centerNaturalX = Math.floor((box.x2 - box.x1) / 2 - (centerWidth / 2));
/* Check left side */
if (x < centerNaturalX) {
/* We didn't overflow the left, use the natural. */
x = centerNaturalX;
}
/* Check right side */
if (x + centerWidth > (box.x2 - rightWidth)) {
x = box.x2 - rightWidth - centerWidth;
}
childBox = new Clutter.ActorBox();
childBox.x1 = x;
childBox.y1 = box.y1;
childBox.x2 = x = childBox.x1 + centerWidth;
childBox.y2 = box.y2;
this._centerBox.allocate(childBox, flags);
let statusbox = new Big.Box();
let statusmenu = this._statusmenu = new Shell.StatusMenu();
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
let statusbutton = new Button.Button(statusbox, PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
true, null, PANEL_HEIGHT);
statusbutton.button.connect('button-press-event', function (b, e) {
statusmenu.toggle(e);
return false;
});
box.append(statusbutton.button, Big.BoxPackFlags.END);
// We get a deactivated event when the popup disappears
this._statusmenu.connect('deactivated', function (sm) {
statusbutton.release();
});
childBox = new Clutter.ActorBox();
childBox.x1 = box.x2 - rightWidth;
childBox.y1 = box.y1;
childBox.x2 = box.x2;
childBox.y2 = box.y2;
this._rightBox.allocate(childBox, flags);
}));
this._clock = new Clutter.Text({ font_name: "Sans Bold 16px",
/* left side */
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR, DEFAULT_FONT);
this.button.actor.height = PANEL_HEIGHT;
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE);
// 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
// guard area (the "environs"). This avoids triggering the hot corner
// multiple times due to an accidental jitter.
this._hotCornerEntered = false;
this._hotCornerEnvirons = new Clutter.Rectangle({ width: 3,
height: 3,
opacity: 0,
reactive: true });
this._hotCorner = new Clutter.Rectangle({ width: 1,
height: 1,
opacity: 0,
reactive: true });
this._hotCornerEnvirons.connect('leave-event',
Lang.bind(this, this._onHotCornerEnvironsLeft));
// Clicking on the hot corner environs should result in the same bahavior
// as clicking on the hot corner.
this._hotCornerEnvirons.connect('button-release-event',
Lang.bind(this, this._onHotCornerClicked));
// In addition to being triggered by the mouse enter event, the hot corner
// can be triggered by clicking on it. This is useful if the user wants to
// undo the effect of triggering the hot corner once in the hot corner.
this._hotCorner.connect('enter-event',
Lang.bind(this, this._onHotCornerEntered));
this._hotCorner.connect('button-release-event',
Lang.bind(this, this._onHotCornerClicked));
this._hotCorner.connect('leave-event',
Lang.bind(this, this._onHotCornerLeft));
this._leftBox.append(this._hotCornerEnvirons, Big.BoxPackFlags.FIXED);
this._leftBox.append(this._hotCorner, Big.BoxPackFlags.FIXED);
let appMenu = new AppPanelMenu();
this._leftBox.append(appMenu.actor, Big.BoxPackFlags.NONE);
/* center */
this._clock = new Clutter.Text({ font_name: DEFAULT_FONT,
color: PANEL_FOREGROUND_COLOR,
text: "" });
let pad = (PANEL_HEIGHT - this._clock.height) / 2;
let clockbox = new Big.Box({ padding_top: pad,
padding_bottom: pad,
padding_left: 4,
padding_right: 4 });
clockbox.append(this._clock, Big.BoxPackFlags.NONE);
box.append(clockbox, Big.BoxPackFlags.END);
this._centerBox.append(this._clock, Big.BoxPackFlags.NONE);
/* right */
// The tray icons live in trayBox within trayContainer.
// The trayBox is hidden when there are no tray icons.
let trayContainer = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.START });
box.append(trayContainer, Big.BoxPackFlags.END);
this._rightBox.append(trayContainer, Big.BoxPackFlags.NONE);
let trayBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
height: TRAY_HEIGHT,
padding: TRAY_PADDING,
spacing: TRAY_SPACING });
this._trayBox = trayBox;
// gtk+ < 2.16 doesn't have fully-working icon transparency,
// so we want trayBox to be opaque in that case (the icons
@ -140,42 +346,100 @@ Panel.prototype = {
this._traymanager = new Shell.TrayManager({ bg_color: TRAY_BACKGROUND_COLOR });
this._traymanager.connect('tray-icon-added',
function(o, icon) {
Lang.bind(this, function(o, icon) {
trayBox.append(icon, Big.BoxPackFlags.NONE);
// Make sure the trayBox is shown.
trayBox.show();
});
this._recomputeTraySize();
}));
this._traymanager.connect('tray-icon-removed',
function(o, icon) {
Lang.bind(this, function(o, icon) {
trayBox.remove_actor(icon);
if (trayBox.get_children().length == 0)
trayBox.hide();
});
this._recomputeTraySize();
}));
this._traymanager.manage_stage(global.stage);
// TODO: decide what to do with the rest of the panel in the overlay mode (make it fade-out, become non-reactive, etc.)
// We get into the overlay mode on button-press-event as opposed to button-release-event because eventually we'll probably
// have the overlay act like a menu that allows the user to release the mouse on the activity the user wants
let statusbox = new Big.Box();
let statusmenu = this._statusmenu = new Shell.StatusMenu();
statusmenu.get_icon().hide();
statusmenu.get_name().fontName = DEFAULT_FONT;
statusmenu.get_name().color = PANEL_FOREGROUND_COLOR;
statusbox.append(this._statusmenu, Big.BoxPackFlags.NONE);
let statusbutton = new Button.Button(statusbox,
PANEL_BUTTON_COLOR,
PRESSED_BUTTON_BACKGROUND_COLOR,
PANEL_FOREGROUND_COLOR);
statusbutton.actor.height = PANEL_HEIGHT;
statusbutton.actor.connect('button-press-event', function (b, e) {
if (e.get_button() == 1 && e.get_click_count() == 1) {
statusmenu.toggle(e);
// The statusmenu might not pop up if it couldn't get a pointer grab
if (statusmenu.is_active())
statusbutton.actor.active = true;
return true;
} else {
return false;
}
});
this._rightBox.append(statusbutton.actor, Big.BoxPackFlags.NONE);
// We get a deactivated event when the popup disappears
this._statusmenu.connect('deactivated', function (sm) {
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.overlay, Main.overlay.toggle));
// In addition to pressing the button, the overlay 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 overlay is entered
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.overlay.connect('showing', Lang.bind(this.button, this.button.pressIn));
Main.overlay.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;
}));
this.actor.add_actor(box);
Main.chrome.addActor(this.actor, box);
Main.chrome.setVisibleInOverlay(this.actor, true);
Main.chrome.addActor(this.actor);
Main.chrome.setVisibleInOverview(this.actor, true);
// Start the clock
this._updateClock();
},
startupAnimation: function() {
this.actor.y = -this.actor.height;
Tweener.addTween(this.actor,
{ y: 0,
time: 0.2,
transition: "easeOutQuad"
});
},
// By default, tray icons have a spacing of TRAY_SPACING. However this
// starts to fail if we have too many as can sadly happen; just jump down
// to a spacing of 8 if we're over 6.
// http://bugzilla.gnome.org/show_bug.cgi?id=590495
_recomputeTraySize: function () {
if (this._trayBox.get_children().length > 6)
this._trayBox.spacing = TRAY_SPACING_MIN;
else
this._trayBox.spacing = TRAY_SPACING;
},
_updateClock: function() {
let displayDate = new Date();
let msecRemaining = 60000 - (1000 * displayDate.getSeconds() +
@ -184,8 +448,40 @@ Panel.prototype = {
displayDate.setMinutes(displayDate.getMinutes() + 1);
msecRemaining += 60000;
}
this._clock.set_text(displayDate.toLocaleFormat("%a %b %e, %l:%M %p"));
/* Translators: This is a time format. */
this._clock.set_text(displayDate.toLocaleFormat(_("%a %l:%M %p")));
Mainloop.timeout_add(msecRemaining, Lang.bind(this, this._updateClock));
return false;
},
_onHotCornerEntered : function() {
if (!this._hotCornerEntered) {
this._hotCornerEntered = true;
if (!Main.overview.animationInProgress) {
Main.overview.toggle();
}
}
return false;
},
_onHotCornerClicked : function() {
if (!Main.overview.animationInProgress) {
Main.overview.toggle();
}
return false;
},
_onHotCornerLeft : function(actor, event) {
if (event.get_related() != this._hotCornerEnvirons) {
this._hotCornerEntered = false;
}
return false;
},
_onHotCornerEnvironsLeft : function(actor, event) {
if (event.get_related() != this._hotCorner) {
this._hotCornerEntered = false;
}
return false;
}
};

278
js/ui/places.js Normal file
View File

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

View File

@ -1,8 +1,15 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
@ -15,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();
@ -24,7 +33,33 @@ 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() {
Main.createLookingGlass().open();
}),
'r': Lang.bind(this, function() {
global.reexec_self();
}),
// Developer brain backwards compatibility
'restart': Lang.bind(this, function() {
global.reexec_self();
}),
'debugexit': Lang.bind(this, function() {
Meta.exit(Meta.ExitCode.ERROR);
})
};
// All actors are inside _group. We create it initially
// hidden then show it in show()
@ -38,100 +73,139 @@ 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 Clutter.Rectangle({ color: BOX_BACKGROUND_COLOR,
reactive: false,
width: BOX_WIDTH,
height: BOX_HEIGHT,
border_width: 0 });
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);
text: _("Please enter a command:") });
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 });
let me = this;
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
this._entry.connect('activate', function (o, e) {
me.hide();
me._run(o.get_text());
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());
if (!this._commandError)
this.close();
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
}
return false;
});
}));
},
_run : function(command) {
if (command == 'restart') {
let global = Shell.Global.get();
global.reexec_self();
let f;
if (this._enableInternalCommands)
f = this._internalCommands[command];
else
f = null;
if (f) {
f();
} else if (command) {
var p = new Shell.Process({'args' : [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 + '.');
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();
}
}
this.emit('run');
},
show : function() {
let me = this;
if (this._group.visible) // Already shown
return false;
if (!Main.startModal())
return false;
this._group.show_all();
this._entry.connect('key-press-event', function(o, e) {
if (Shell.get_event_key_symbol(e) == Clutter.Escape) {
me.hide();
me.emit('cancel');
return true;
} else
return false;
});
let global = Shell.Global.get();
global.stage.set_key_focus(this._entry);
return true;
},
hide : function() {
if (!this._group.visible)
open : function() {
if (this._isOpen) // Already shown
return;
this._group.hide();
Main.endModal();
this._isOpen = true;
this._group.show();
Main.pushModal(this._group);
global.stage.set_key_focus(this._entry);
},
destroy : function(){
this.hide();
this._group.destroy();
close : function() {
if (!this._isOpen)
return;
this._isOpen = false;
this._errorBox.hide();
this._commandError = false;
this._group.hide();
this._entry.text = '';
Main.popModal(this._group);
}
};
Signals.addSignalMethods(RunDialog.prototype);

View File

@ -14,24 +14,12 @@ const WidgetBox = imports.ui.widgetBox;
const SIDEBAR_SPACING = 4;
const SIDEBAR_PADDING = 4;
// The total sidebar width is the widget width plus the widget
// padding, plus the sidebar padding
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 2 * WidgetBox.WIDGETBOX_PADDING + 2 * SIDEBAR_PADDING;
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 2 * WidgetBox.WIDGETBOX_PADDING + 2 * 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;
// FIXME, needs to be configurable, obviously
const default_widgets = [
"imports.ui.widget.ClockWidget",
"imports.ui.widget.AppsWidget",
"imports.ui.widget.DocsWidget"
];
// The total sidebar width is the widget width plus the widget padding
// (counted twice for the widget box, and once again for the
// out-of-screen padding), plus the empty space between the border of
// the bar and of the windows
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;
function Sidebar() {
this._init();
@ -39,8 +27,6 @@ function Sidebar() {
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
@ -48,7 +34,6 @@ Sidebar.prototype = {
this.actor = new Clutter.Group({ x: -WidgetBox.WIDGETBOX_PADDING,
y: Panel.PANEL_HEIGHT,
width: SIDEBAR_EXPANDED_WIDTH });
Main.chrome.addActor(this.actor);
// The actual widgets go into a Big.Box inside this.actor. The
// box's width will vary during the expand/collapse animations,
@ -58,23 +43,38 @@ Sidebar.prototype = {
// during the animation.
this.box = new Big.Box ({ padding_top: SIDEBAR_PADDING,
padding_bottom: SIDEBAR_PADDING,
padding_right: SIDEBAR_PADDING,
padding_right: 0,
padding_left: 0,
spacing: SIDEBAR_SPACING });
this.actor.add_actor(this.box);
this._visible = this.expanded = true;
this._gconf = Shell.GConf.get_default();
this._expanded = this._gconf.get_boolean ("sidebar/expanded");
if (!this._expanded)
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
this._visible = this._gconf.get_boolean ("sidebar/visible");
if (this._visible)
Main.chrome.addActor(this.actor);
this._widgets = [];
this.addWidget(new ToggleWidget(this));
this.addWidget(new ToggleWidget());
let default_widgets = this._gconf.get_string_list("sidebar/widgets");
for (let i = 0; i < default_widgets.length; i++)
this.addWidget(default_widgets[i]);
this._gconf.connect('changed::sidebar/expanded',
Lang.bind(this, this._expandedChanged));
this._gconf.connect('changed::sidebar/visible',
Lang.bind(this, this._visibleChanged));
},
addWidget: function(widget) {
let widgetBox;
try {
widgetBox = new WidgetBox.WidgetBox(widget);
widgetBox = new WidgetBox.WidgetBox(widget, this._expanded);
} catch(e) {
logError(e, "Failed to add widget '" + widget + "'");
return;
@ -84,18 +84,32 @@ Sidebar.prototype = {
this._widgets.push(widgetBox);
},
show: function() {
this._visible = true;
this.actor.show();
_visibleChanged: function() {
let visible = this._gconf.get_boolean("sidebar/visible");
if (visible == this._visible)
return;
this._visible = visible;
if (visible)
Main.chrome.addActor(this.actor);
else
Main.chrome.removeActor(this.actor);
},
hide: function() {
this._visible = false;
this.actor.hide();
_expandedChanged: function() {
let expanded = this._gconf.get_boolean("sidebar/expanded");
if (expanded == this._expanded)
return;
this._expanded = expanded;
if (expanded)
this._expand();
else
this._collapse();
},
expand: function() {
this.expanded = true;
_expand: function() {
this._expanded = true;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].expand();
@ -106,8 +120,8 @@ Sidebar.prototype = {
} });
},
collapse: function() {
this.expanded = false;
_collapse: function() {
this._expanded = false;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].collapse();
@ -130,24 +144,33 @@ Sidebar.prototype = {
const LEFT_DOUBLE_ARROW = "\u00AB";
const RIGHT_DOUBLE_ARROW = "\u00BB";
function ToggleWidget(sidebar) {
this._init(sidebar);
function ToggleWidget() {
this._init();
}
ToggleWidget.prototype = {
__proto__ : Widget.Widget.prototype,
_init : function(sidebar) {
this._sidebar = sidebar;
_init : function() {
this._gconf = Shell.GConf.get_default();
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: LEFT_DOUBLE_ARROW,
reactive: true });
this.actor.connect('button-release-event',
Lang.bind(this._sidebar, this._sidebar.collapse));
Lang.bind(this, this._collapse));
this.collapsedActor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: RIGHT_DOUBLE_ARROW,
reactive: true });
this.collapsedActor.connect('button-release-event',
Lang.bind(this._sidebar, this._sidebar.expand));
Lang.bind(this, this._expand));
},
_collapse : function () {
this._gconf.set_boolean ("sidebar/expanded", false);
},
_expand : function () {
this._gconf.set_boolean ("sidebar/expanded", true);
}
};

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

@ -9,9 +9,9 @@ const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppInfo = imports.misc.appInfo;
const DocDisplay = imports.ui.docDisplay;
const DocInfo = imports.misc.docInfo;
const COLLAPSED_WIDTH = 24;
@ -31,12 +31,22 @@ function Widget() {
Widget.prototype = {
// _init():
//
// Your widget constructor. Receives no arguments. Must define a
// field named "actor" containing the Clutter.Actor to show in
// expanded mode. This actor will be clipped to
// Widget.EXPANDED_WIDTH. Most widgets will also define a field
// named "title" containing the title string to show above the
// widget in the sidebar.
// Your widget constructor. Your constructor function should look
// like:
//
// function MyWidgetType() {
// this._init.apply(this, arguments);
// }
//
// and your _init method should start by doing:
//
// Widget.Widget.prototype._init.apply(this, arguments);
//
// The _init method must define a field named "actor" containing
// the Clutter.Actor to show in expanded mode. This actor will be
// clipped to Widget.EXPANDED_WIDTH. Most widgets will also define
// a field named "title" containing the title string to show above
// the widget in the sidebar.
//
// If you want to have a separate collapsed view, you can define a
// field "collapsedActor" containing the Clutter.Actor to show in
@ -51,6 +61,9 @@ Widget.prototype = {
// the sidebar is collapsed, the widget's expanded view will pop
// out of the sidebar until either the cursor moves out of it,
// or else the widget calls this.activated() on itself.
_init: function (initialState) {
this.state = initialState;
},
// destroy():
//
@ -81,23 +94,22 @@ Widget.prototype = {
// state:
//
// A field set on your widget by the sidebar. Will contain one of
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED). Note
// that this will not be set until *after* _init() is called, so
// you cannot rely on it being set at that point. The widget will
// always initially be in STATE_EXPANDED.
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED).
};
Signals.addSignalMethods(Widget.prototype);
function ClockWidget() {
this._init();
this._init.apply(this, arguments);
}
ClockWidget.prototype = {
__proto__ : Widget.prototype,
_init: function() {
Widget.prototype._init.apply(this, arguments);
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: "",
// Give an explicit height to ensure
@ -146,14 +158,14 @@ ClockWidget.prototype = {
},
_updateText: function(time) {
this.actor.set_text(time.toLocaleFormat("%H:%M"));
// Translators: This is a time format.
this.actor.set_text(time.toLocaleFormat(_("%H:%M")));
},
_updateCairo: function(time) {
let global = Shell.Global.get();
global.clutter_cairo_texture_draw_clock(this.collapsedActor,
time.getHours() % 12,
time.getMinutes());
Shell.draw_clock(this.collapsedActor,
time.getHours() % 12,
time.getMinutes());
}
};
@ -168,7 +180,7 @@ const ITEM_NAME_COLOR = new Clutter.Color();
ITEM_NAME_COLOR.from_pixel(0x000000ff);
function LauncherWidget() {
this._init();
this._init.apply(this, arguments);
}
LauncherWidget.prototype = {
@ -182,7 +194,7 @@ LauncherWidget.prototype = {
spacing: ITEM_SPACING,
reactive: true });
item._info = info;
item.append(info.getIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
item.append(new Clutter.Text({ color: ITEM_NAME_COLOR,
font_name: "Sans 14px",
ellipsize: Pango.EllipsizeMode.END,
@ -203,7 +215,7 @@ LauncherWidget.prototype = {
padding: ITEM_PADDING,
reactive: true });
item._info = info;
item.append(info.getIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
Big.BoxPackFlags.NONE);
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
@ -272,33 +284,61 @@ LauncherWidget.prototype = {
}
};
function AppsWidgetInfo(appInfo) {
this._init(appInfo);
}
AppsWidgetInfo.prototype = {
_init : function(appInfo) {
this._info = appInfo;
this.name = appInfo.get_name();
},
createIcon : function(size) {
return this._info.create_icon_texture(size);
},
launch : function() {
this._info.launch();
}
}
function AppsWidget() {
this._init();
this._init.apply(this, arguments);
}
AppsWidget.prototype = {
__proto__ : LauncherWidget.prototype,
_init : function() {
this.title = "Applications";
Widget.prototype._init.apply(this, arguments);
this.title = _("Applications");
this.actor = new Big.Box({ spacing: 2 });
this.collapsedActor = new Big.Box({ spacing: 2});
let apps = AppInfo.getMostUsedApps(5);
for (let i = 0; i < apps.length; i++)
this.addItem(apps[i]);
let appSystem = Shell.AppSystem.get_default();
let apps = appSystem.get_favorites();
for (let i = 0; i < apps.length; i++) {
let app = appSystem.lookup_cached_app(apps[i]);
if (!app)
continue;
this.addItem(new AppsWidgetInfo(app));
}
}
};
function DocsWidget() {
this._init();
function RecentDocsWidget() {
this._init.apply(this, arguments);
}
DocsWidget.prototype = {
RecentDocsWidget.prototype = {
__proto__ : LauncherWidget.prototype,
_init : function() {
this.title = "Recent Docs";
Widget.prototype._init.apply(this, arguments);
this.title = _("Recent Documents");
this.actor = new Big.Box({ spacing: 2 });
this._recentManager = Gtk.RecentManager.get_default();
@ -320,7 +360,7 @@ DocsWidget.prototype = {
items.push(docInfo);
}
items.sort(function (a,b) { return b.lastVisited() - a.lastVisited(); });
items.sort(function (a,b) { return b.timestamp - a.timestamp; });
for (i = 0; i < Math.min(items.length, 5); i++)
this.addItem(items[i]);
}

View File

@ -15,21 +15,24 @@ WIDGETBOX_BG_COLOR.from_pixel(0xf0f0f0ff);
const BLACK = new Clutter.Color();
BLACK.from_pixel(0x000000ff);
const WIDGETBOX_PADDING = 4;
const WIDGETBOX_PADDING = 2;
const ANIMATION_TIME = 0.5;
const POP_IN_LAG = 250; /* milliseconds */
function WidgetBox(widget) {
this._init(widget);
function WidgetBox(widget, expanded) {
this._init(widget, expanded);
}
WidgetBox.prototype = {
_init: function(widget) {
if (widget instanceof Widget.Widget)
_init: function(widget, expanded) {
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
if (widget instanceof Widget.Widget) {
this._widget = widget;
else {
this._widget.state = this.state;
} else {
let ctor = this._ctorFromName(widget);
this._widget = new ctor();
this._widget = new ctor(this.state);
}
if (!this._widget.actor)
@ -37,7 +40,7 @@ WidgetBox.prototype = {
else if (!this._widget.title && !this._widget.collapsedActor)
throw new Error("widget has neither title nor collapsedActor");
this.state = this._widget.state = Widget.STATE_EXPANDED;
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
// The structure of a WidgetBox:
//
@ -77,9 +80,15 @@ WidgetBox.prototype = {
this.actor = new Clutter.Group();
this._hbox = new Big.Box({ background_color: WIDGETBOX_BG_COLOR,
padding: WIDGETBOX_PADDING,
padding_top: WIDGETBOX_PADDING,
padding_bottom: WIDGETBOX_PADDING,
padding_right: WIDGETBOX_PADDING,
// Left padding is here to make up for
// the X offset used for the sidebar
// to hide its rounded corners
padding_left: 2 * WIDGETBOX_PADDING,
spacing: WIDGETBOX_PADDING,
corner_radius: WIDGETBOX_PADDING / 2,
corner_radius: WIDGETBOX_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
reactive: true });
this.actor.add_actor(this._hbox);
@ -122,7 +131,6 @@ WidgetBox.prototype = {
this._activationHandler = this._widget.connect('activated',
Lang.bind(this, this._activationHandler));
}
this._cgroup.hide();
this._egroup = new Clutter.Group({ clip_to_allocation: true });
this._hbox.append(this._egroup, Big.BoxPackFlags.NONE);
@ -142,6 +150,11 @@ WidgetBox.prototype = {
}
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
if (expanded)
this._setWidgetExpanded();
else
this._setWidgetCollapsed();
},
// Given a name like "imports.ui.widget.ClockWidget", turn that
@ -178,16 +191,25 @@ WidgetBox.prototype = {
this.state = this._widget.state = Widget.STATE_EXPANDING;
},
_expandPart1Complete: function() {
_setWidgetExpanded: function() {
this._cgroup.hide();
this._cbox.x = 0;
this._egroup.show();
if (this._singleActor) {
log(this._widget.actor);
this._widget.actor.unparent();
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
}
if (this._htitle) {
this._htitle.show();
this._hline.show();
}
},
_expandPart1Complete: function() {
this._cbox.x = 0;
this._setWidgetExpanded();
if (this._widget.expand) {
try {
this._widget.expand();
@ -196,11 +218,6 @@ WidgetBox.prototype = {
}
}
this._egroup.show();
if (this._htitle) {
this._htitle.show();
this._hline.show();
}
this._ebox.x = -Widget.EXPANDED_WIDTH;
Tweener.addTween(this._ebox, { x: 0,
time: ANIMATION_TIME / 2,
@ -222,19 +239,27 @@ WidgetBox.prototype = {
this.state = this._widget.state = Widget.STATE_COLLAPSING;
},
_collapsePart1Complete: function() {
_setWidgetCollapsed: function() {
this._egroup.hide();
this._ebox.x = 0;
this._cgroup.show();
if (this._singleActor) {
this._widget.actor.unparent();
this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE);
}
if (this._htitle) {
this._htitle.hide();
this._hline.hide();
}
if (this._singleActor) {
log(this._widget.actor);
this._widget.actor.unparent();
this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE);
}
if (this._vtitle)
this._cbox.height = this._ebox.height;
},
_collapsePart1Complete: function() {
this._ebox.x = 0;
this._setWidgetCollapsed();
if (this._widget.collapse) {
try {
@ -244,10 +269,7 @@ WidgetBox.prototype = {
}
}
this._cgroup.show();
this._cbox.x = -Widget.COLLAPSED_WIDTH;
if (this._vtitle)
this._cbox.height = this._ebox.height;
Tweener.addTween(this._cbox, { x: 0,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
@ -274,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,64 +26,24 @@ 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) {
if (Main.overlay.visible)
if (Main.overview.visible)
return false;
if (actor && (actor.get_window_type() != Meta.CompWindowType.NORMAL))
return false;
@ -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,86 +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) {
_maximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
shellwm.completed_maximize(actor);
},
_maximizeWindowDone : function(shellwm, actor) {
},
_maximizeWindowOverwrite : function(shellwm, actor) {
},
_unmaximizeWindow : function(shellwm, actor, targetX, targetY, targetWidth, targetHeight) {
shellwm.completed_unmaximize(actor);
},
_unmaximizeWindowDone : function(shellwm, actor) {
},
_mapWindow : function(shellwm, actor) {
if (!this._shouldAnimate(actor)) {
this._shellwm.completed_maximize(actor);
return;
}
/* this doesn't work very well, as simply scaling up the existing
* window contents doesn't produce anything like the same results as
* actually maximizing the window.
*/
let scaleX = targetWidth / actor.width;
let scaleY = targetHeight / actor.height;
let anchorX = (actor.x - targetX) * actor.width/(targetWidth - actor.width);
let anchorY = (actor.y - targetY) * actor.height/(targetHeight - actor.height);
actor.move_anchor_point(anchorX, anchorY);
this._maximizing.push(actor);
Tweener.addTween(actor,
{ scale_x: scaleX,
scale_y: scaleY,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._maximizeWindowDone,
onCompleteScope: this,
onCompleteParams: [actor],
onOverwrite: this._maximizeWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [actor]
});
},
_maximizeWindowDone : function(actor) {
if (this._removeEffect(this._maximizing, actor)) {
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
this._shellwm.completed_maximize(actor);
}
},
_maximizeWindowOverwrite : function(actor) {
if (this._removeEffect(this._maximizing, actor)) {
this._shellwm.completed_maximize(actor);
}
},
_unmaximizeWindow : function(actor, targetX, targetY, targetWidth, targetHeight) {
this._shellwm.completed_unmaximize(actor);
},
_unmaximizeWindowDone : function(actor) {
},
_mapWindow : function(actor) {
if (!this._shouldAnimate(actor)) {
this._shellwm.completed_map(actor);
shellwm.completed_map(actor);
return;
}
@ -217,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;
}
@ -256,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.
@ -292,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;
@ -313,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);
@ -344,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,
@ -354,7 +278,7 @@ WindowManager.prototype = {
});
},
_switchWorkspaceDone : function() {
_switchWorkspaceDone : function(shellwm) {
let switchData = this._switchData;
if (!switchData)
return;
@ -373,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); });

File diff suppressed because it is too large Load Diff

20
po/LINGUAS Normal file
View File

@ -0,0 +1,20 @@
ca
cs
da
de
en_GB
es
fr
ga
gl
hu
it
ko
nb
nl
pa
pl
pt_BR
sv
tr
zh_CN

9
po/POTFILES.in Normal file
View File

@ -0,0 +1,9 @@
data/gnome-shell.desktop.in.in
js/ui/panel.js
js/ui/dash.js
js/ui/overview.js
js/ui/runDialog.js
src/gdmuser/gdm-user.c
src/shell-global.c
src/shell-status-menu.c
src/shell-uri-util.c

1
po/POTFILES.skip Normal file
View File

@ -0,0 +1 @@
data/gnome-shell.desktop.in

189
po/ca.po Normal file
View File

@ -0,0 +1,189 @@
# Catalan gnome-shell translation.
# Copyright (C) 2009 Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>
# This file is distributed under the same license as the gnome-shell package.
#
# Siegfried-Angel Gevatter Pujals <rainct@ubuntu.com>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-30 18:53+0200\n"
"PO-Revision-Date: 2009-08-30 18:57+0100\n"
"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"
#: ../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:271
msgid "Activities"
msgstr "Activitats"
#. 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 "Cerca..."
#: ../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:633
#: ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "APLICACIONS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "LLOCS"
#. **** 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/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Fa menys d'un minut"
#: ../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: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: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:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Fa %d setmana"
msgstr[1] "Fa %d setmanes"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Desconegut"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
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'estalvi de pantalla a pantalla negra: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "No es pot sortir: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informació del compte..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferències del sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bloca la pantalla"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Canvia d'usuari"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Surt..."
#. Shut down
#: ../src/shell-status-menu.c:557
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."

189
po/cs.po Normal file
View File

@ -0,0 +1,189 @@
# Czech translation of gnome-shell.
# 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\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-30 17:37+0200\n"
"PO-Revision-Date: 2009-08-30 17:33+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Prostředí GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Správa oken a spouštění aplikací"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Činnosti"
#. 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 "Najít..."
#: ../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:633 ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "APLIKACE"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "MÍSTA"
#. **** 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 "Zadejte prosím příkaz:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Před méně než minutou"
#: ../src/shell-global.c:843
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Před %d minutou"
msgstr[1] "Před %d minutami"
msgstr[2] "Před %d minutami"
#: ../src/shell-global.c:846
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Před %d hodinou"
msgstr[1] "Před %d hodinami"
msgstr[2] "Před %d hodinami"
#: ../src/shell-global.c:849
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Před %d dnem"
msgstr[1] "Před %d dny"
msgstr[2] "Před %d dny"
#: ../src/shell-global.c:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Před %d týdnem"
msgstr[1] "Před %d týdny"
msgstr[2] "Před %d týdny"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Neznámé"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nelze uzamknout obrazovku: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Šetřič obrazovky nelze dočasně nastavit na prázdnou obrazovku: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nelze se odhlásit: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informace o účtu..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Postranní lišta"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Předvolby systému..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Uzamknout obrazovku"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Přepnout uživatele"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Odhlásit..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Vypnout..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Domovská složka"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Systém souborů"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Hledat"
#. 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 "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."

182
po/de.po Normal file
View File

@ -0,0 +1,182 @@
# German gnome-shell translation.
# Copyright (C) 2009 Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
#
# Hendrik Brandt <heb@gnome-de.org>, 2009.
# Hendrik Richter <hendrikr@gnome.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-20 16:47+0200\n"
"PO-Revision-Date: 2009-08-20 16:49+0200\n"
"Last-Translator: Hendrik Richter <hendrikr@gnome.org>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: UTF-8\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 "Fenster verwalten und Anwendungen starten"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Aktivitäten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:251
msgid "Find apps or documents"
msgstr "Anwendungen oder Dokumente suchen"
#: ../js/ui/dash.js:369
msgid "Browse"
msgstr "Durchsuchen"
#. **** Applications ****
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
msgid "APPLICATIONS"
msgstr "ANWENDUNGEN"
#. **** Documents ****
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
msgid "RECENT DOCUMENTS"
msgstr "ZULETZT GEÖFFNETE DOKUMENTE"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:598
msgid "PLACES"
msgstr "ORTE"
#: ../js/ui/runDialog.js:75
msgid "Please enter a command:"
msgstr "Bitte geben Sie einen Befehl ein:"
#: ../src/gdmuser/gdm-user.c:243
msgid "Manager"
msgstr "Verwaltung"
#: ../src/gdmuser/gdm-user.c:244
msgid "The user manager object this user is controlled by."
msgstr "Das Benutzerverwaltungsobjekt welches diesen Benutzer überwacht."
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Vor weniger als einer Minute"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "Vor %d Minute"
msgstr[1] "Vor %d Minuten"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "Vor %d Stunde"
msgstr[1] "Vor %d Stunden"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "Vor %d Tag"
msgstr[1] "Vor %d Tagen"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Vor %d Woche"
msgstr[1] "Vor %d Wochen"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Unbekannt"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Bildschirm kann nicht gesperrt werden: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Der Bildschirmschoner kann vorübergehend nicht auf einen leeren Schirm "
"gesetzt werden: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Abmelden ist nicht möglich: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Benutzerinformationen …"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Seitenleiste"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systemeinstellungen …"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bildschirm sperren"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Benutzer wechseln"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Abmelden …"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Ausschalten …"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Persönlicher Ordner"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Dateisystem"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Suchen"
#. 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"

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"

199
po/es.po Normal file
View File

@ -0,0 +1,199 @@
# Spanish translation of gnome-shell.
# Copyright (C) 2009 gnome-shell's COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
#
# Jorge González <jorgegonz@svn.gnome.org>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-11 21:48+0000\n"
"PO-Revision-Date: 2009-09-12 14:40+0200\n"
"Last-Translator: Jorge González <jorgegonz@svn.gnome.org>\n"
"Language-Team: Español <gnome-es-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: UTF-8\n"
"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 "Gestión de ventanas e inicio de aplicaciones"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:452
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:283
msgid "Find..."
msgstr "Buscar…"
#: ../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: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:756
msgid "PLACES"
msgstr "LUGARES"
#. **** Documents ****
#: ../js/ui/dash.js:763 ../js/ui/dash.js:802
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECIENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:782 ../js/ui/dash.js:907
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DE LA BÚSQUEDA"
#: ../js/ui/dash.js:797
msgid "PREFERENCES"
msgstr "PREFERENCIAS"
#: ../js/ui/runDialog.js:90
msgid "Please enter a command:"
msgstr "Introduzca un comando:"
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Hace menos de un minuto"
#: ../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: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: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:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "Hace %d semana"
msgstr[1] "Hace %d semanas"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Desconocido"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "No se puede bloquear la pantalla: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"No se puede establecer temporalmente el salvapantallas a oscurecer pantalla: "
"%s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "No se puede salir de la sesión: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Información de la cuenta…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferencias del sistema…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bloquear la pantalla"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambiar de usuario"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Salir…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Apagar…"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Carpeta personal"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Sistema de archivos"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Buscar"
#. 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 "Encuentre aplicaciones o documentos"
#~| msgid "RECENT DOCUMENTS"
#~ msgid "DOCUMENTS"
#~ msgstr "DOCUMENTOS"
#~ msgid "Manager"
#~ msgstr "Gestor"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "El objeto de gestión de usuarios que controla a este usuario."

182
po/fr.po Normal file
View File

@ -0,0 +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.
#
# Mathieu Bridon <bochecha@fedoraproject.org>, 2009.
#
msgid ""
msgstr ""
"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"
#: ../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"

181
po/ga.po Normal file
View File

@ -0,0 +1,181 @@
# Irish translations for gnome-shell package.
# Copyright (C) 2009 Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
# Seán de Búrca <leftmostcat@gmail.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell.master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-15 06:01-0600\n"
"PO-Revision-Date: 2009-08-15 06:01-0600\n"
"Last-Translator: Seán de Búrca <leftmostcat@gmail.com>\n"
"Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=5; plural=n==1 ? 0 : (n%10==1 || n%10==2) ? 1 : (n%"
"10>=3 && n%10<= 6) ? 2 : ((n%10>=7 && n%10<=9) || n==10) ? 3 : 4;\n"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Gníomhartha"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Aimsigh feidhmchláir nó cáipéisí"
#: ../js/ui/dash.js:336
msgid "Browse"
msgstr "Brabhsáil"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
msgid "APPLICATIONS"
msgstr "FEIDHMCHLÁIR"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "CÁIPÉISÍ IS DÉANAÍ"
#. **** Places ****
#: ../js/ui/dash.js:563
msgid "PLACES"
msgstr "ÁITEANNA"
#: ../js/ui/runDialog.js:74
msgid "Please enter a command:"
msgstr "Iontráil ordú, le do thoil:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Bainisteoir"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "An réad bhainisteoir úsáideoirí a rialaíonn an t-úsáideoir seo."
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Níos lú ná nóiméad ó shin"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d nóiméad ó shin"
msgstr[1] "%d nóiméad ó shin"
msgstr[2] "%d nóiméad ó shin"
msgstr[3] "%d nóiméad ó shin"
msgstr[4] "%d nóiméad ó shin"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d uair ó shin"
msgstr[1] "%d uair ó shin"
msgstr[2] "%d uaire ó shin"
msgstr[3] "%d n-uaire ó shin"
msgstr[4] "%d uair ó shin"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d lá ó shin"
msgstr[1] "%d lá ó shin"
msgstr[2] "%d lá ó shin"
msgstr[3] "%d lá ó shin"
msgstr[4] "%d lá ó shin"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d seachtain ó shin"
msgstr[1] "%d sheachtain ó shin"
msgstr[2] "%d sheachtain ó shin"
msgstr[3] "%d seachtain ó shin"
msgstr[4] "%d seachtain ó shin"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Anaithnid"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Ní féidir scáileán a chur faoi ghlas: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Ní féidir spárálaí scáileáin a shocrú chun scáileán a bhánú: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Ní féidir logáil amach: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Eolas Cuntais..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra Taoibh"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Sainroghanna an Chórais..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Cuir Scáileán Faoi Ghlas"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Athraigh Úsáideoir"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Logáil Amach..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Múch..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Fillteán Baile"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Córas Comhad"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Cuardaigh"
#. 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"

194
po/gl.po Normal file
View File

@ -0,0 +1,194 @@
# Galician 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.
# Fran Diéguez <fran.dieguez@mabishu.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-15 23:06+0200\n"
"PO-Revision-Date: 2009-09-10 22:32+0100\n"
"Last-Translator: Fran Diéguez <fran.dieguez@glug.es>\n"
"Language-Team: Galician <gnome@mancomun.org>\n"
"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 "Xestor de xanelas e lanzado de aplicativos"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Actividades"
#. 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 "Buscar..."
#: ../js/ui/dash.js:400
msgid "Browse"
msgstr "Explorar"
#: ../js/ui/dash.js:536
msgid "(see all)"
msgstr "(ver todos)"
#. **** Applications ****
#: ../js/ui/dash.js:753 ../js/ui/dash.js:809
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:773
msgid "PLACES"
msgstr "LUGARES"
#. **** Documents ****
#: ../js/ui/dash.js:780 ../js/ui/dash.js:819
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Search Results ****
#: ../js/ui/dash.js:799 ../js/ui/dash.js:931
msgid "SEARCH RESULTS"
msgstr "RESULTADOS DA BÚSQUEDA"
#: ../js/ui/dash.js:814
msgid "PREFERENCES"
msgstr ""
#: ../js/ui/runDialog.js:96
msgid "Please enter a command:"
msgstr "Insira unha orde:"
#: ../src/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Menos de un minuto"
#: ../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: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: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:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "fai %d semana"
msgstr[1] "fai %d semanas"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Descoñecido"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Non foi posíbel bloquear a pantalla: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Non foi posíbel establecer o salvapantallas a unha pantalla en branco: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Non foi posíbel pechar a sesión: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Información da conta..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferenzas do sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Bloquear pantalla"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambiar de usuario"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Pechar sesión..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Apagar..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Cartafol persoal"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Sistema de ficheiros"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Buscar"
#. 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 "Atopar aplicativos ou documentos"
#, fuzzy
#~ msgid "DOCUMENTS"
#~ msgstr "DOCUMENTOS RECENTES"
#~ msgid "Manager"
#~ msgstr "Xestor"

180
po/hu.po Normal file
View File

@ -0,0 +1,180 @@
# Hungarian translation of gnome-shell
# Copyright 2009. Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
#
# Gabor Kelemen <kelemeng at gnome dot hu>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-15 11:35+0200\n"
"PO-Revision-Date: 2009-08-15 11:35+0200\n"
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
"Language-Team: Hungarian <gnome at fsf dot hu>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: KBabel 1.11.4\n"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Tevékenységek"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
msgid "%a %l:%M %p"
msgstr "%a., %k.%M"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Alkalmazások vagy dokumentumok keresése"
#: ../js/ui/dash.js:336
msgid "Browse"
msgstr "Tallózás"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
msgid "APPLICATIONS"
msgstr "ALKALMAZÁSOK"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "LEGUTÓBBI DOKUMENTUMOK"
#. **** Places ****
#: ../js/ui/dash.js:563
msgid "PLACES"
msgstr "HELYEK"
#: ../js/ui/runDialog.js:74
msgid "Please enter a command:"
msgstr "Adjon meg egy parancsot:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Kezelő"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "A felhasználót kezelő felhasználókezelő objektum."
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Kevesebb, mint egy perce"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d perce"
msgstr[1] "%d perce"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d órája"
msgstr[1] "%d órája"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d napja"
msgstr[1] "%d napja"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d hete"
msgstr[1] "%d hete"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Ismeretlen"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nem lehet zárolni a képernyőt: %s "
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Átmenetileg nem lehet beállítani a képernyővédőt a képernyő elsötétítésére: %"
"s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nem lehet kijelentkezni: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Fiókinformációk…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Oldalsáv"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Rendszerbeállítások…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Képernyő zárolása"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Felhasználóváltás"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Kijelentkezés…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Leállítás…"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Shell"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Ablakkezelés és alkalmazásindítás"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Saját mappa"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Fájlrendszer"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Oldalsáv"
#. 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"

197
po/it.po Normal file
View File

@ -0,0 +1,197 @@
# Italian translations for gnome-shell package.
# Copyright (C) 2009 the gnome-shell copyright holder
# This file is distributed under the same license as the gnome-shell package.
# Milo Casagrande <milo@ubuntu.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&component=general\n"
"POT-Creation-Date: 2009-09-05 00:19+0000\n"
"PO-Revision-Date: 2009-09-06 18:31+0200\n"
"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
"Language-Team: Italian <tp@lists.linux.it>\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 "Gestione finestre e avvio applicazioni"
#. left side
#: ../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:454
msgid "%a %l:%M %p"
msgstr "%a %k.%M"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Trova..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Esplora"
#: ../js/ui/dash.js:511
msgid "(see all)"
msgstr "(vedi tutto)"
#. **** Applications ****
#: ../js/ui/dash.js:705 ../js/ui/dash.js:761 ../js/ui/dash.js:893
msgid "APPLICATIONS"
msgstr "Applicazioni"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:725
msgid "PLACES"
msgstr "Risorse"
#. **** Documents ****
#: ../js/ui/dash.js:732 ../js/ui/dash.js:773 ../js/ui/dash.js:867
msgid "RECENT DOCUMENTS"
msgstr "Documenti recenti"
#. **** Search Results ****
#: ../js/ui/dash.js:751 ../js/ui/dash.js:856 ../js/ui/dash.js:882
msgid "SEARCH RESULTS"
msgstr "Risultati ricerca"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Inserire un comando:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Meno di un minuto fa"
#: ../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: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: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:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d settimana fa"
msgstr[1] "%d settimane fa"
# (ndt) valutare se vada al femminile
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Sconosciuto"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Impossibile bloccare lo schermo: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Impossibile impostare temporaneamente il salva schermo a schermo nero: %s "
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Impossibile terminare la sessione: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informazioni account..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra laterale"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferenze di sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Blocca schermo"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Cambia utente"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Termina sessione..."
# (ndt) da valutare... pare che ora anche Windows usi 'Arresta...'...
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Spegni..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Cartella home"
#. 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 "Cerca"
# (ndt) valutare...
#. 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"
# (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"
# (ndt) no idea...
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "L'oggetto user manager che controlla questo utente."

166
po/ko.po Normal file
View File

@ -0,0 +1,166 @@
# gnome-shell korean translation.
# Copyright (C) 2009 THE gnome-shell'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Young-Ho Cha <ganadist@gmail.com>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-21 10:09+0900\n"
"PO-Revision-Date: 2009-08-21 10:10+0900\n"
"Last-Translator: Young-Ho Cha <ganadist@gmail.com>\n"
"Language-Team: GNOME Korea <gnome-kr-hackers@lists.kldp.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "그놈 쉘"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "창 관리와 프로그램 시작"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr ""
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%A %p %l:%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "프로그램과 문서를 찾습니다"
#: ../js/ui/dash.js:368
msgid "Browse"
msgstr "찾아보기"
#. **** Applications ****
#: ../js/ui/dash.js:504 ../js/ui/dash.js:577
msgid "APPLICATIONS"
msgstr "프로그램"
#. **** Documents ****
#: ../js/ui/dash.js:509 ../js/ui/dash.js:604
msgid "RECENT DOCUMENTS"
msgstr "최근 문서"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:597
msgid "PLACES"
msgstr "위치"
#: ../js/ui/runDialog.js:75
msgid "Please enter a command:"
msgstr "명령을 입력하십시오:"
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "1분 이내"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d분 전"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d시간 전"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d일 전"
#: ../src/shell-global.c:853
#, 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 "%s: %s"

170
po/nb.po Normal file
View File

@ -0,0 +1,170 @@
# Norwegian bokmål translation of gnome-shell.
# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the gnome-shell package.
# Kjartan Maraas <kmaraas@broadpark.no>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell 0.4\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-21 12:36+0200\n"
"PO-Revision-Date: 2009-08-21 12:44+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@broadpark.no>\n"
"Language-Team: Norwegian bokmål <i18n-nb@lister.ping.uio.no>\n"
"MIME-Version: 1.0\n"
"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 "Vindushåndtering og oppstart av programmer"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Aktiviteter"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%a %l:%M"
#: ../js/ui/dash.js:250
msgid "Find apps or documents"
msgstr "Finn programmer eller dokumenter"
#: ../js/ui/dash.js:368
msgid "Browse"
msgstr "Bla gjennom"
#. **** Applications ****
#: ../js/ui/dash.js:504 ../js/ui/dash.js:577
msgid "APPLICATIONS"
msgstr "PROGRAMMER"
#. **** Documents ****
#: ../js/ui/dash.js:509 ../js/ui/dash.js:604
msgid "RECENT DOCUMENTS"
msgstr "SISTE DOKUMENTER"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:597
msgid "PLACES"
msgstr "STEDER"
#: ../js/ui/runDialog.js:75
msgid "Please enter a command:"
msgstr "Oppgi en kommando:"
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Mindre enn ett minutt siden"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minutt siden"
msgstr[1] "%d minutter siden"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d time siden"
msgstr[1] "%d timer siden"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dag siden"
msgstr[1] "%d dager siden"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d uke siden"
msgstr[1] "%d uker siden"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Ukjent"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan ikke låse skjermen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan ikke sette skjermsparer midlertidig til blank skjerm: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan ikke logge ut: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Kontoinformasjon..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidelinje"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Brukervalg for systemet..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lås skjerm"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Bytt bruker"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Logg ut..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Slå av..."
#: ../src/shell-uri-util.c:87
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øk"
#. 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"

179
po/nl.po Normal file
View File

@ -0,0 +1,179 @@
# Dutch translation for gnome-shell
#
# This file is distributed under the same license as the gnome-shell package.
#
# Sander Dijkhuis <sander.dijkhuis@gmail.com>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \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"
"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 "Vensterbeheer en toepassingen starten"
#. left side
#: ../js/ui/panel.js:271
msgid "Activities"
msgstr "Activiteiten"
#. Translators: This is a time format.
#: ../js/ui/panel.js:451
msgid "%a %l:%M %p"
msgstr "%a %k:%M"
#: ../js/ui/dash.js:256
msgid "Find..."
msgstr "Zoeken…"
#: ../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: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:654
msgid "PLACES"
msgstr "LOCATIES"
#. **** Documents ****
#: ../js/ui/dash.js:661 ../js/ui/dash.js:694
msgid "RECENT DOCUMENTS"
msgstr "RECENTE DOCUMENTEN"
#. **** Search Results ****
#: ../js/ui/dash.js:680
msgid "SEARCH RESULTS"
msgstr "ZOEKRESULTATEN"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Voer een opdracht in:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Korter dan een minuut geleden"
#: ../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: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: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:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d week geleden"
msgstr[1] "%d weken geleden"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Onbekend"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan het scherm niet vergrendelen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan de schermbeveiliging niet tijdelijk als zwart scherm instellen: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan niet afmelden: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Account-informatie…"
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Zijbalk"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systeemvoorkeuren…"
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Scherm vergrendelen"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Gebruiker wisselen"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Afmelden…"
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Afsluiten…"
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Persoonlijke map"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Bestandssysteem"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Zoeken"
#. 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"

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"

188
po/pl.po Normal file
View File

@ -0,0 +1,188 @@
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Aviary.pl
# Jeśli masz jakiekolwiek uwagi odnoszące się do tłumaczenia lub chcesz
# pomóc w jego rozwijaniu i pielęgnowaniu, napisz do nas:
# gnomepl@aviary.pl
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \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"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
"|| n%100>=20) ? 1 : 2);\n"
"X-Poedit-Language: Polish\n"
"X-Poedit-Country: Poland\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "Powłoka środowiska GNOME"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Zarządzanie oknami i uruchamianiem programów"
#. left side
#: ../js/ui/panel.js:269
msgid "Activities"
msgstr "Czynności"
#. 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 "Znajdź..."
#: ../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:700 ../js/ui/dash.js:756 ../js/ui/dash.js:887
msgid "APPLICATIONS"
msgstr "Programy"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:720
msgid "PLACES"
msgstr "Miejsca"
#. **** 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/shell-global.c:799
msgid "Less than a minute ago"
msgstr "Mniej niż minutę temu"
#: ../src/shell-global.c:802
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuta temu"
msgstr[1] "%d minuty temu"
msgstr[2] "%d minut temu"
#: ../src/shell-global.c:805
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d godzina temu"
msgstr[1] "%d godziny temu"
msgstr[2] "%d godzin temu"
#: ../src/shell-global.c:808
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dzień temu"
msgstr[1] "%d dni temu"
msgstr[2] "%d dni temu"
#: ../src/shell-global.c:811
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d tydzień temu"
msgstr[1] "%d tygodnie temu"
msgstr[2] "%d tygodni temu"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Nieznane"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Nie można zablokować ekranu: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr ""
"Nie można tymczasowo ustawić wygaszacza ekranu na wygaszenie ekranu: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Nie można się wylogować: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informacje o koncie..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Panel boczny"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferencje systemu..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Zablokuj ekran"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Przełącz użytkownika"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Wyloguj się..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Wyłącz komputer..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Katalog domowy"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "System plików"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Wyszukaj"
#. 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"

144
po/pt_BR.po Normal file
View File

@ -0,0 +1,144 @@
# Portuguese 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.
# Og Maciel <ogmaciel@gnome.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-14 17:53-0400\n"
"PO-Revision-Date: 2009-08-14 17:53-0400\n"
"Last-Translator: Og Maciel <ogmaciel@gnome.org>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Atividades"
#. Translators: This is a time format.
#: ../js/ui/panel.js:412
msgid "%a %l:%M %p"
msgstr "%a %l:%M %p"
#: ../js/ui/dash.js:235
msgid "Find apps or documents"
msgstr "Localizar aplicativos ou documentos"
#: ../js/ui/dash.js:336
msgid "Browse"
msgstr "Navegar"
#. **** Applications ****
#: ../js/ui/dash.js:472 ../js/ui/dash.js:545
msgid "APPLICATIONS"
msgstr "APLICATIVOS"
#. **** Documents ****
#: ../js/ui/dash.js:477 ../js/ui/dash.js:570
msgid "RECENT DOCUMENTS"
msgstr "DOCUMENTOS RECENTES"
#. **** Places ****
#: ../js/ui/dash.js:563
msgid "PLACES"
msgstr "LOCAIS"
#: ../js/ui/runDialog.js:74
msgid "Please enter a command:"
msgstr "Por favor digite um comando:"
#: ../src/gdmuser/gdm-user.c:242
msgid "Manager"
msgstr "Gerenciador"
#: ../src/gdmuser/gdm-user.c:243
msgid "The user manager object this user is controlled by."
msgstr "O objeto gerenciador de usuários que controla este usuário."
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Menos de um minuto atrás"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d minuto atrás"
msgstr[1] "%d minutos atrás"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d hora atrás"
msgstr[1] "%d horas atrás"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d dia atrás"
msgstr[1] "%d dias atrás"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d semana atrás"
msgstr[1] "%d semanas atrás"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Desconhecido"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Não foi possível travar a tela: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Não foi possível definir a proteção de tela para uma tela vazia: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Não foi possível encerrar a sessão: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Informação da conta..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Barra lateral"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Preferências do sistema..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Travar a tela"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Alternar usuário"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Encerrar sessão..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Desligar..."

191
po/sv.po Normal file
View File

@ -0,0 +1,191 @@
# Swedish translation for gnome-shell.
# Copyright (C) 2009 Free Software Foundation, Inc.
# This file is distributed under the same license as the gnome-shell package.
# Daniel Nylander <po@danielnylander.se>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-01 00:31+0200\n"
"PO-Revision-Date: 2009-09-01 00:31+0100\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\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-skal"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Fönsterhantering och programstarter"
#. 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 "Sök..."
#: ../js/ui/dash.js:374
msgid "Browse"
msgstr "Bläddra"
#: ../js/ui/dash.js:451
msgid "(see all)"
msgstr "(se alla)"
#. **** Applications ****
#: ../js/ui/dash.js:633
#: ../js/ui/dash.js:681
msgid "APPLICATIONS"
msgstr "PROGRAM"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:653
msgid "PLACES"
msgstr "PLATSER"
#. **** Documents ****
#: ../js/ui/dash.js:660
#: ../js/ui/dash.js:692
msgid "RECENT DOCUMENTS"
msgstr "SENASTE DOKUMENT"
#. **** Search Results ****
#: ../js/ui/dash.js:679
msgid "SEARCH RESULTS"
msgstr "SÖKRESULTAT"
#: ../js/ui/runDialog.js:82
msgid "Please enter a command:"
msgstr "Ange ett kommando:"
#: ../src/shell-global.c:840
msgid "Less than a minute ago"
msgstr "Mindre än en minut sedan"
#: ../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: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: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:852
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d vecka sedan"
msgstr[1] "%d veckor sedan"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Okänt"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Kan inte låsa skärmen: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Kan inte temporärt ställa in skärmsläckaren till blank skärm: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Kan inte logga ut: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Kontoinformation..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Sidopanel"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Systeminställningar..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Lås skärmen"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Växla användare"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Logga ut..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Stäng av..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Hemmapp"
#. 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ök"
#. 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 "Hitta program eller dokument"
#~ msgid "DOCUMENTS"
#~ msgstr "DOKUMENT"
#~ msgid "Manager"
#~ msgstr "Hanterare"
#~ msgid "The user manager object this user is controlled by."
#~ msgstr "Användarhanteringsobjektet som denna användare styrs av."

166
po/tr.po Normal file
View File

@ -0,0 +1,166 @@
# gnome-shell
# Copyright (C) 2009
# This file is distributed under the same license as the gnome-shell package.
#
# Baris Cicek <baris@teamforce.name.tr>, 2009.
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-08-21 00:41+0300\n"
"PO-Revision-Date: 2009-08-21 00:40+0300\n"
"Last-Translator: Baris Cicek <baris@teamforce.name.tr>\n"
"Language-Team: Turkish <gnome-turk@gnome.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../data/gnome-shell.desktop.in.in.h:1
msgid "GNOME Shell"
msgstr "GNOME Kabuğu"
#: ../data/gnome-shell.desktop.in.in.h:2
msgid "Window management and application launching"
msgstr "Pencere yönetimi ve uygulama başlatma"
#. left side
#: ../js/ui/panel.js:266
msgid "Activities"
msgstr "Etkinlikler"
#. Translators: This is a time format.
#: ../js/ui/panel.js:433
msgid "%a %l:%M %p"
msgstr "%a %H:%M"
#: ../js/ui/dash.js:251
msgid "Find apps or documents"
msgstr "Uygulamalar ve belgeler bul"
#: ../js/ui/dash.js:369
msgid "Browse"
msgstr "Göz at"
#. **** Applications ****
#: ../js/ui/dash.js:505 ../js/ui/dash.js:578
msgid "APPLICATIONS"
msgstr "UYGULAMALAR"
#. **** Documents ****
#: ../js/ui/dash.js:510 ../js/ui/dash.js:605
msgid "RECENT DOCUMENTS"
msgstr "SON ERİŞİLEN BELGELER"
#. **** Places ****
#. Translators: This is in the sense of locations for documents,
#. network locations, etc.
#: ../js/ui/dash.js:598
msgid "PLACES"
msgstr "YERLER"
#: ../js/ui/runDialog.js:75
msgid "Please enter a command:"
msgstr "Lütfen bir komut girin:"
#: ../src/shell-global.c:841
msgid "Less than a minute ago"
msgstr "Bir dakikadan daha az süre önce"
#: ../src/shell-global.c:844
#, c-format
msgid "%d minute ago"
msgid_plural "%d minutes ago"
msgstr[0] "%d dakika önce"
#: ../src/shell-global.c:847
#, c-format
msgid "%d hour ago"
msgid_plural "%d hours ago"
msgstr[0] "%d saat önce"
#: ../src/shell-global.c:850
#, c-format
msgid "%d day ago"
msgid_plural "%d days ago"
msgstr[0] "%d gün önce"
#: ../src/shell-global.c:853
#, c-format
msgid "%d week ago"
msgid_plural "%d weeks ago"
msgstr[0] "%d hafta önce"
#: ../src/shell-status-menu.c:156
msgid "Unknown"
msgstr "Bilinmeyen"
#: ../src/shell-status-menu.c:212
#, c-format
msgid "Can't lock screen: %s"
msgstr "Ekran kilitlenemedi: %s"
#: ../src/shell-status-menu.c:227
#, c-format
msgid "Can't temporarily set screensaver to blank screen: %s"
msgstr "Ekran koruyucu geçici olarak boş ekran olarak atanamadı: %s"
#: ../src/shell-status-menu.c:351
#, c-format
msgid "Can't logout: %s"
msgstr "Çıkış yapılamadı: %s"
#: ../src/shell-status-menu.c:492
msgid "Account Information..."
msgstr "Hesap Bilgisi..."
#: ../src/shell-status-menu.c:502
msgid "Sidebar"
msgstr "Kenar Çubuğu"
#: ../src/shell-status-menu.c:510
msgid "System Preferences..."
msgstr "Sistem Tercihleri..."
#: ../src/shell-status-menu.c:525
msgid "Lock Screen"
msgstr "Ekrani Kilitle"
#: ../src/shell-status-menu.c:535
msgid "Switch User"
msgstr "Kullanıcı Değiştir"
#. Only show switch user if there are other users
#. Log Out
#: ../src/shell-status-menu.c:546
msgid "Log Out..."
msgstr "Çıkış..."
#. Shut down
#: ../src/shell-status-menu.c:557
msgid "Shut Down..."
msgstr "Kapat..."
#: ../src/shell-uri-util.c:87
msgid "Home Folder"
msgstr "Ev Klasörü"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-uri-util.c:102
msgid "File System"
msgstr "Dosya Sistemi"
#: ../src/shell-uri-util.c:248
msgid "Search"
msgstr "Arama"
#. 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"

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

@ -33,21 +33,21 @@ big_source_c = \
big-enum-types.h: stamp-big-enum-types.h Makefile
@true
stamp-big-enum-types.h: $(big_source_h) big/big-enum-types.h.in
( cd $(srcdir) && \
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/big/big-enum-types.h.in \
$(big_source_h) ) >> xgen-teth && \
(cmp xgen-teth big-enum-types.h || cp xgen-teth big-enum-types.h) && \
rm -f xgen-teth && \
$(big_source_h) ) >> xgen-beth && \
(cmp -s xgen-beth big-enum-types.h || cp xgen-beth big-enum-types.h) && \
rm -f xgen-beth && \
echo timestamp > $(@F)
big-enum-types.c: stamp-big-enum-types.h big/big-enum-types.c.in
( cd $(srcdir) && \
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/big/big-enum-types.c.in \
$(big_source_h) ) >> xgen-tetc && \
cp xgen-tetc big-enum-types.c && \
rm -f xgen-tetc
$(big_source_h) ) >> xgen-betc && \
cp xgen-betc big-enum-types.c && \
rm -f xgen-betc
noinst_LTLIBRARIES += libbig-1.0.la

117
src/Makefile-nbtk.am Normal file
View File

@ -0,0 +1,117 @@
nbtk_cflags = \
-I$(top_srcdir)/src \
-DPREFIX=\""$(prefix)"\" \
-DLIBDIR=\""$(libdir)"\" \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"Nbtk\" \
-DNBTK_COMPILATION \
$(NBTK_CFLAGS) \
$(NULL)
nbtk_built_sources = \
nbtk-enum-types.h \
nbtk-enum-types.c \
nbtk-marshal.h \
nbtk-marshal.c
BUILT_SOURCES += $(nbtk_built_sources)
EXTRA_DIST += \
nbtk/nbtk-marshal.list \
nbtk/nbtk-enum-types.h.in \
nbtk/nbtk-enum-types.c.in
CLEANFILES += stamp-nbtk-marshal.h stamp-nbtk-enum-types.h
nbtk-marshal.h: stamp-nbtk-marshal.h
@true
stamp-nbtk-marshal.h: Makefile nbtk/nbtk-marshal.list
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_nbtk_marshal \
--header \
$(srcdir)/nbtk/nbtk-marshal.list > $@.tmp && \
(cmp -s $@.tmp nbtk-marshal.h || cp -f $@.tmp nbtk-marshal.h) && \
rm -f $@.tmp && \
echo timestamp > $(@F)
nbtk-marshal.c: Makefile nbtk/nbtk-marshal.list
$(AM_V_GEN) (echo "#include \"nbtk-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_nbtk_marshal \
--body \
$(srcdir)/nbtk/nbtk-marshal.list ) > $@.tmp && \
cp -f $@.tmp nbtk-marshal.c && \
rm -f $@.tmp
nbtk-enum-types.h: stamp-nbtk-enum-types.h Makefile
@true
stamp-nbtk-enum-types.h: $(source_h) nbtk/nbtk-enum-types.h.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template nbtk/nbtk-enum-types.h.in \
$(nbtk_source_h) ) >> $@.tmp && \
(cmp -s $@.tmp nbtk-enum-types.h || cp $@.tmp nbtk-enum-types.h) && \
rm -f $@.tmp && \
echo timestamp > $(@F)
nbtk-enum-types.c: stamp-nbtk-enum-types.h nbtk/nbtk-enum-types.c.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template nbtk/nbtk-enum-types.c.in \
$(nbtk_source_h) ) >> $@.tmp && \
cp $@.tmp $@ && \
rm -f $@.tmp
# please, keep this sorted alphabetically
nbtk_source_h = \
nbtk/nbtk-adjustment.h \
nbtk/nbtk-bin.h \
nbtk/nbtk-box-layout.h \
nbtk/nbtk-box-layout-child.h \
nbtk/nbtk-button.h \
nbtk/nbtk-clipboard.h \
nbtk/nbtk-entry.h \
nbtk/nbtk-label.h \
nbtk/nbtk-private.h \
nbtk/nbtk-scrollable.h \
nbtk/nbtk-scroll-bar.h \
nbtk/nbtk-scroll-view.h \
nbtk/nbtk-subtexture.h \
nbtk/nbtk-texture-cache.h \
nbtk/nbtk-texture-frame.h \
nbtk/nbtk-tooltip.h \
nbtk/nbtk-types.h \
nbtk/nbtk-widget.h \
$(NULL)
# please, keep this sorted alphabetically
nbtk_source_c = \
nbtk/nbtk-adjustment.c \
nbtk/nbtk-bin.c \
nbtk/nbtk-box-layout.c \
nbtk/nbtk-box-layout-child.c \
nbtk/nbtk-button.c \
nbtk/nbtk-clipboard.c \
nbtk/nbtk-entry.c \
nbtk/nbtk-label.c \
nbtk/nbtk-private.c \
nbtk/nbtk-scrollable.c \
nbtk/nbtk-scroll-bar.c \
nbtk/nbtk-scroll-view.c \
nbtk/nbtk-subtexture.c \
nbtk/nbtk-texture-cache.c \
nbtk/nbtk-texture-frame.c \
nbtk/nbtk-tooltip.c \
nbtk/nbtk-widget.c \
$(NULL)
noinst_LTLIBRARIES += libnbtk-1.0.la
libnbtk_1_0_la_LIBADD = $(NBTK_LIBS)
libnbtk_1_0_la_SOURCES = \
$(nbtk_source_c) \
$(nbtk_source_h) \
$(nbtk_built_sources) \
$(NULL)
libnbtk_1_0_la_CPPFLAGS = $(nbtk_cflags)
libnbtk_1_0_la_LDFLAGS = $(LDADD)

View File

@ -1,17 +0,0 @@
gnomeshell_taskpanel_CPPFLAGS = \
-I$(top_srcdir)/src \
-DG_DISABLE_DEPRECATED \
-DWNCK_I_KNOW_THIS_IS_UNSTABLE \
-DG_LOG_DOMAIN=\"gnomeshell-taskpanel\" \
$(TASKPANEL_CFLAGS) \
$(NULL)
gnomeshell_taskpanel_SOURCES = \
gnomeshell-taskpanel.c \
shell-panel-window.c \
shell-panel-window.h \
$(NULL)
gnomeshell_taskpanel_LDADD = $(TASKPANEL_LIBS)
libexec_PROGRAMS += gnomeshell-taskpanel

View File

@ -1,89 +0,0 @@
tidy_cflags = \
-I$(top_srcdir)/src \
-DPREFIX=\""$(prefix)"\" \
-DLIBDIR=\""$(libdir)"\" \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"Tidy\" \
$(MUTTER_PLUGIN_CFLAGS) \
$(NULL)
tidy_built_sources = \
tidy-enum-types.h \
tidy-enum-types.c \
tidy-marshal.h \
tidy-marshal.c
BUILT_SOURCES += $(tidy_built_sources)
TIDY_STAMP_FILES = stamp-tidy-marshal.h stamp-tidy-enum-types.h
# please, keep this sorted alphabetically
tidy_source_h = \
tidy/tidy-grid.h \
$(NULL)
tidy_source_h_priv = \
$(NULL)
# please, keep this sorted alphabetically
tidy_source_c = \
tidy/tidy-grid.c \
$(NULL)
tidy-marshal.h: stamp-tidy-marshal.h
@true
stamp-tidy-marshal.h: Makefile tidy/tidy-marshal.list
$(GLIB_GENMARSHAL) \
--prefix=_tidy_marshal \
--header \
$(srcdir)/tidy/tidy-marshal.list > xgen-tmh && \
(cmp -s xgen-tmh tidy-marshal.h || cp -f xgen-tmh tidy-marshal.h) && \
rm -f xgen-tmh && \
echo timestamp > $(@F)
tidy-marshal.c: Makefile tidy/tidy-marshal.list
(echo "#include \"tidy-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_tidy_marshal \
--body \
$(srcdir)/tidy/tidy-marshal.list ) > xgen-tmc && \
cp -f xgen-tmc tidy-marshal.c && \
rm -f xgen-tmc
tidy-enum-types.h: stamp-tidy-enum-types.h Makefile
@true
stamp-tidy-enum-types.h: $(tidy_source_h) tidy/tidy-enum-types.h.in
( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/tidy/tidy-enum-types.h.in \
$(tidy_source_h) ) >> xgen-teth && \
(cmp xgen-teth tidy-enum-types.h || cp xgen-teth tidy-enum-types.h) && \
rm -f xgen-teth && \
echo timestamp > $(@F)
tidy-enum-types.c: stamp-tidy-enum-types.h tidy/tidy-enum-types.c.in
( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/tidy/tidy-enum-types.c.in \
$(tidy_source_h) ) >> xgen-tetc && \
cp xgen-tetc tidy-enum-types.c && \
rm -f xgen-tetc
noinst_LTLIBRARIES += libtidy-1.0.la
libtidy_1_0_la_LIBADD = $(TIDY_LIBS)
libtidy_1_0_la_SOURCES = \
$(tidy_source_c) \
$(tidy_source_h) \
$(tidy_source_h_priv) \
$(tidy_built_sources) \
$(NULL)
libtidy_1_0_la_CPPFLAGS = $(tidy_cflags)
libtidy_1_0_la_LDFLAGS = $(LDADD)
CLEANFILES += $(TIDY_STAMP_FILES) $(BUILT_SOURCES)
EXTRA_DIST += \
tidy/tidy-enum-types.h.in \
tidy/tidy-enum-types.c.in \
tidy/tidy-marshal.list

36
src/Makefile-toolkit.am Normal file
View File

@ -0,0 +1,36 @@
toolkit_cflags = \
-I$(top_srcdir)/src \
-DPREFIX=\""$(prefix)"\" \
-DLIBDIR=\""$(libdir)"\" \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"Shell\" \
$(TOOLKIT_CFLAGS)
# please, keep this sorted alphabetically
toolkit_sources = \
toolkit/shell-border-image.c \
toolkit/shell-border-image.h \
toolkit/shell-theme.c \
toolkit/shell-theme.h \
toolkit/shell-theme-context.c \
toolkit/shell-theme-context.h \
toolkit/shell-theme-node.c \
toolkit/shell-theme-node.h \
toolkit/shell-theme-private.h
non_gir_toolkit_sources = \
toolkit/shell-theme-private.h
noinst_LTLIBRARIES += libshell-toolkit.la
libshell_toolkit_la_LIBADD = $(TOOLKIT_LIBS)
libshell_toolkit_la_SOURCES = $(toolkit_sources) $(toolkit_built_sources)
libshell_toolkit_la_CPPFLAGS = $(toolkit_cflags)
libshell_toolkit_la_LDFLAGS = $(LDADD)
noinst_PROGRAMS += test-theme
test_theme_CPPFLAGS = $(toolkit_cflags)
test_theme_LDADD = libshell-toolkit.la
test_theme_SOURCES = toolkit/test-theme.c

View File

@ -24,7 +24,7 @@ tray_source = \
na-marshal.h: stamp-na-marshal.h
@true
stamp-na-marshal.h: Makefile tray/na-marshal.list
$(GLIB_GENMARSHAL) \
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_na_marshal \
--header \
$(srcdir)/tray/na-marshal.list > xgen-tmh && \
@ -33,7 +33,7 @@ stamp-na-marshal.h: Makefile tray/na-marshal.list
echo timestamp > $(@F)
na-marshal.c: Makefile tray/na-marshal.list
(echo "#include \"na-marshal.h\"" ; \
$(AM_V_GEN) (echo "#include \"na-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_na_marshal \
--body \

View File

@ -1,34 +1,40 @@
NULL =
BUILT_SOURCES =
CLEANFILES =
EXTRA_DIST =
EXTRA_DIST =
libexec_PROGRAMS =
noinst_LTLIBRARIES =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
.AUTOPARALLEL:
bin_SCRIPTS = gnome-shell
gnome-shell: gnome-shell.in
sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \
$(AM_V_GEN) sed -e "s|@MUTTER_BIN_DIR[@]|$(MUTTER_BIN_DIR)|" \
-e "s|@GJS_JS_DIR[@]|$(GJS_JS_DIR)|" \
-e "s|@GJS_JS_NATIVE_DIR[@]|$(GJS_JS_NATIVE_DIR)|" \
-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
EXTRA_DIST += gnome-shell.in
include Makefile-tidy.am
include Makefile-big.am
include Makefile-gdmuser.am
include Makefile-nbtk.am
include Makefile-toolkit.am
include Makefile-tray.am
include Makefile-taskpanel.am
gnome_shell_cflags = \
$(MUTTER_PLUGIN_CFLAGS) \
$(LIBGNOMEUI_CFLAGS) \
-I$(srcdir)/tray \
-DGETTEXT_PACKAGE=gnome-shell \
-DGETTEXT_PACKAGE=\"gnome-shell\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
-DGNOME_SHELL_DATADIR=\"$(pkgdatadir)\" \
-DGNOME_SHELL_PKGLIBDIR=\"$(pkglibdir)\" \
-DJSDIR=\"$(pkgdatadir)/js\"
@ -57,25 +63,43 @@ libgnome_shell_la_SOURCES = \
shell-app-system.h \
shell-arrow.c \
shell-arrow.h \
shell-button-box.c \
shell-button-box.h \
shell-drawing.c \
shell-drawing.h \
shell-drawing-area.c \
shell-drawing-area.h \
shell-embedded-window.c \
shell-embedded-window.h \
shell-embedded-window-private.h \
shell-gconf.c \
shell-gconf.h \
shell-generic-container.c \
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 \
shell-process.h \
shell-global.c \
shell-global.h \
shell-status-menu.c \
shell-status-menu.h \
shell-stack.c \
shell-stack.h \
shell-tray-manager.c \
shell-tray-manager.h \
shell-texture-cache.c \
shell-texture-cache.h \
shell-uri-util.c \
shell-uri-util.h \
shell-wm.c \
shell-wm.h
non_gir_sources = \
non_gir_sources = \
shell-embedded-window-private.h
shell_recorder_sources = \
@ -93,7 +117,7 @@ if BUILD_RECORDER
libgnome_shell_la_SOURCES += $(shell_recorder_sources)
non_gir_sources += $(shell_recorder_non_gir_sources)
noinst_PROGRAMS = test-recorder
noinst_PROGRAMS += test-recorder
test_recorder_CPPFLAGS = $(TEST_SHELL_RECORDER_CFLAGS)
test_recorder_LDADD = $(TEST_SHELL_RECORDER_LIBS)
@ -104,50 +128,53 @@ test_recorder_SOURCES = \
endif BUILD_RECORDER
libgnome_shell_la_gir_sources = \
$(filter-out $(non_gir_sources), $(libgnome_shell_la_SOURCES))
$(filter-out $(non_gir_sources) $(non_gir_toolkit_sources), $(libgnome_shell_la_SOURCES) $(toolkit_sources))
shell-marshal.h: stamp-shell-marshal.h
@true
stamp-shell-marshal.h: Makefile shell-marshal.list
$(GLIB_GENMARSHAL) \
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_shell_marshal \
--header \
$(srcdir)/shell-marshal.list > xgen-tmh && \
(cmp -s xgen-tmh shell-marshal.h || cp -f xgen-tmh shell-marshal.h) && \
rm -f xgen-tmh && \
$(srcdir)/shell-marshal.list > xgen-smh && \
(cmp -s xgen-smh shell-marshal.h || cp -f xgen-smh shell-marshal.h) && \
rm -f xgen-smh && \
echo timestamp > $(@F)
shell-marshal.c: Makefile shell-marshal.list
(echo "#include \"shell-marshal.h\"" ; \
$(AM_V_GEN) (echo "#include \"shell-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_shell_marshal \
--body \
$(srcdir)/shell-marshal.list ) > xgen-tmc && \
cp -f xgen-tmc shell-marshal.c && \
rm -f xgen-tmc
$(srcdir)/shell-marshal.list ) > xgen-smc && \
cp -f xgen-smc shell-marshal.c && \
rm -f xgen-smc
libgnome_shell_la_LDFLAGS = -avoid-version -module
libgnome_shell_la_LIBADD = \
$(MUTTER_PLUGIN_LIBS) \
$(LIBGNOMEUI_LIBS) \
libbig-1.0.la \
libnbtk-1.0.la \
libgdmuser-1.0.la \
libtidy-1.0.la \
libshell-toolkit.la \
libtray.la
libgnome_shell_la_CPPFLAGS = $(gnome_shell_cflags)
typelibdir = $(pkglibdir)
typelib_DATA = Shell-0.1.typelib Tidy-1.0.typelib Big-1.0.typelib
typelib_DATA = Shell-0.1.typelib Big-1.0.typelib Nbtk-1.0.typelib
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir libgnome-shell.la Makefile
$(G_IR_SCANNER) \
Shell-0.1.gir: $(mutter) $(G_IR_SCANNER) Big-1.0.gir Nbtk-1.0.gir libgnome-shell.la Makefile
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Shell \
--nsversion=0.1 \
--add-include-path=$(MUTTER_LIB_DIR)/mutter/ \
--include=Clutter-0.9 \
--include=Clutter-1.0 \
--include=Meta-2.27 \
--libtool="$(LIBTOOL)" \
--add-include-path=$(builddir) \
--include=Big-1.0 \
--include=Nbtk-1.0 \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(libgnome_shell_la_gir_sources)) \
@ -158,33 +185,20 @@ CLEANFILES += Shell-0.1.gir
# The dependency on libgnome-shell.la here is because g-ir-compiler opens it
# (not the fake library, since we've already done the rewriting)
Shell-0.1.typelib: libgnome-shell.la Shell-0.1.gir Big-1.0.gir
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler --includedir=$(builddir) --includedir=$(MUTTER_LIB_DIR)/mutter/ Shell-0.1.gir -o $@
$(AM_V_GEN) \
$(G_IR_COMPILER) \
--includedir=. \
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
Shell-0.1.gir -o $@
CLEANFILES += Shell-0.1.typelib
Tidy-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libtidy-1.0.la Makefile
$(G_IR_SCANNER) \
--namespace=Tidy \
--nsversion=1.0 \
--include=Clutter-0.9 \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(tidy_source_h)) \
$(addprefix $(srcdir)/,$(tidy_source_c)) \
$(srcdir)/tidy-enum-types.h \
$(tidy_cflags) \
-o $@
CLEANFILES += Tidy-1.0.gir
Tidy-1.0.typelib: libtidy-1.0.la Tidy-1.0.gir
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler Tidy-1.0.gir -o $@
CLEANFILES += Tidy-1.0.typelib
Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
$(G_IR_SCANNER) \
--namespace=Big \
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Big \
--nsversion=1.0 \
--include=Clutter-0.9 \
--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)) \
@ -195,5 +209,54 @@ Big-1.0.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libbig-1.0.la Makefile
CLEANFILES += Big-1.0.gir
Big-1.0.typelib: libbig-1.0.la Big-1.0.gir
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. g-ir-compiler Big-1.0.gir -o $@
$(AM_V_GEN) $(G_IR_COMPILER) Big-1.0.gir -o $@
CLEANFILES += Big-1.0.typelib
toolkit_gir_sources = \
$(filter-out $(non_gir_toolkit_sources), $(toolkit_sources))
# Since the Shell namepace includes both the code in toolkit/ that our fork of
# NBTK depends upon and the code in this directory that depends on NBTK, We have a
# circular dependency when generating the girs and typelibs. We work around this
# by generating a Toolkit gir, using it to build the Nbtk gir then sed'ing the
# reference out of the generated gir.
Toolkit-0.1.gir: $(mutter) $(G_IR_SCANNER) libgnome-shell.la libshell-toolkit.la Makefile
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Shell \
--nsversion=0.1 \
--include=Clutter-1.0 \
--libtool="$(LIBTOOL)" \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(toolkit_gir_sources)) \
$(TOOLKIT_CFLAGS) \
-o $@
CLEANFILES += Toolkit-1.0.gir
Nbtk-1.0.gir: $(mutter) $(G_IR_SCANNER) Toolkit-0.1.gir libgnome-shell.la libnbtk-1.0.la Makefile
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Nbtk \
--nsversion=1.0 \
--include=Clutter-1.0 \
--include=Gtk-2.0 \
--add-include-path=$(builddir) \
--include=Toolkit-0.1 \
--libtool="$(LIBTOOL)" \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
-DNBTK_COMPILATION \
$(addprefix $(srcdir)/,$(nbtk_source_h)) \
$(addprefix $(srcdir)/,$(nbtk_source_c)) \
$(srcdir)/nbtk-enum-types.h \
$(NBTK_CFLAGS) \
-o $@.tmp && \
sed -e '/"Toolkit"/d' < $@.tmp > $@
CLEANFILES += Nbtk-1.0.gir
Nbtk-1.0.typelib: Nbtk-1.0.gir
$(AM_V_GEN) $(G_IR_COMPILER) \
--includedir=. \
--includedir=$(MUTTER_LIB_DIR)/mutter/ \
$< -o $@
CLEANFILES += Nbtk-1.0.typelib

View File

@ -268,6 +268,52 @@ corner_get(guint radius,
return corner;
}
/* To match the CSS specification, we want the border to look like it was
* drawn over the background. But actually drawing the border over the
* background will produce slightly bad antialiasing at the edges, so
* compute the effective border color instead.
*/
#define NORM(x) (t = (x) + 127, (t + (t >> 8)) >> 8)
#define MULT(c,a) NORM(c*a)
static void
premultiply (ClutterColor *color)
{
guint t;
color->red = MULT (color->red, color->alpha);
color->green = MULT (color->green, color->alpha);
color->blue = MULT (color->blue, color->alpha);
}
static void
unpremultiply (ClutterColor *color)
{
if (color->alpha != 0) {
color->red = (color->red * 255 + 127) / color->alpha;
color->green = (color->green * 255 + 127) / color->alpha;
color->blue = (color->blue * 255 + 127) / color->alpha;
}
}
static void
over (const ClutterColor *source,
const ClutterColor *destination,
ClutterColor *result)
{
guint t;
ClutterColor src = *source;
ClutterColor dst = *destination;
premultiply (&src);
premultiply (&dst);
result->alpha = src.alpha + NORM ((255 - src.alpha) * dst.alpha);
result->red = src.red + NORM ((255 - src.alpha) * dst.red);
result->green = src.green + NORM ((255 - src.alpha) * dst.green);
result->blue = src.blue + NORM ((255 - src.alpha) * dst.blue);
unpremultiply (result);
}
static void
big_rectangle_update_corners(BigRectangle *rectangle)
{
@ -278,6 +324,7 @@ big_rectangle_update_corners(BigRectangle *rectangle)
if (rectangle->radius != 0) {
ClutterColor *color;
ClutterColor *border_color;
ClutterColor effective_border;
guint border_width;
g_object_get(rectangle,
@ -286,10 +333,12 @@ big_rectangle_update_corners(BigRectangle *rectangle)
"color", &color,
NULL);
over (border_color, color, &effective_border);
corner = corner_get(rectangle->radius,
color,
border_width,
border_color);
&effective_border);
clutter_color_free(border_color);
clutter_color_free(color);
@ -329,12 +378,10 @@ big_rectangle_paint(ClutterActor *actor)
rectangle = BIG_RECTANGLE(actor);
if (rectangle->radius == 0) {
/* In that case we are no different than our parent class,
* so don't bother */
CLUTTER_ACTOR_CLASS(big_rectangle_parent_class)->paint(actor);
return;
}
/* We can't chain up, even when we the radius is 0, because of the different
* interpretation of the border/background relationship here than for
* ClutterRectangle.
*/
if (rectangle->corners_dirty)
big_rectangle_update_corners(rectangle);
@ -345,6 +392,9 @@ big_rectangle_paint(ClutterActor *actor)
"color", &color,
NULL);
if (border_color->alpha == 0 && color->alpha == 0)
goto out;
actor_opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_allocation_box(actor, &box);
@ -358,6 +408,11 @@ big_rectangle_paint(ClutterActor *actor)
radius = rectangle->radius;
/* Optimization; if the border is transparent, it just looks like part of
* the background */
if (radius == 0 && border_color->alpha == 0)
border_width = 0;
max = MAX(border_width, radius);
if (radius != 0) {
@ -393,33 +448,54 @@ big_rectangle_paint(ClutterActor *actor)
}
if (border_width != 0) {
ClutterColor effective_border;
over (border_color, color, &effective_border);
if (!rectangle->border_material)
rectangle->border_material = cogl_material_new ();
cogl_color_set_from_4ub(&tmp_color,
border_color->red,
border_color->green,
border_color->blue,
actor_opacity * border_color->alpha / 255);
effective_border.red,
effective_border.green,
effective_border.blue,
actor_opacity * effective_border.alpha / 255);
cogl_color_premultiply (&tmp_color);
cogl_material_set_color(rectangle->border_material, &tmp_color);
cogl_set_source(rectangle->border_material);
/* NORTH */
cogl_rectangle(max, 0,
width - max, border_width);
if (radius > 0) { /* skip corners */
/* NORTH */
cogl_rectangle(max, 0,
width - max, border_width);
/* EAST */
cogl_rectangle(width - border_width, max,
width, height - max);
/* EAST */
cogl_rectangle(width - border_width, max,
width, height - max);
/* SOUTH */
cogl_rectangle(max, height - border_width,
width - max, height);
/* SOUTH */
cogl_rectangle(max, height - border_width,
width - max, height);
/* WEST */
cogl_rectangle(0, max,
border_width, height - max);
/* WEST */
cogl_rectangle(0, max,
border_width, height - max);
} else { /* include corners */
/* NORTH */
cogl_rectangle(0, 0,
width, border_width);
/* EAST */
cogl_rectangle(width - border_width, border_width,
width, height - border_width);
/* SOUTH */
cogl_rectangle(0, height - border_width,
width, height);
/* WEST */
cogl_rectangle(0, border_width,
border_width, height - border_width);
}
}
if (!rectangle->background_material)
@ -455,6 +531,7 @@ big_rectangle_paint(ClutterActor *actor)
cogl_rectangle(border_width, max,
width - border_width, height - max);
out:
clutter_color_free(border_color);
clutter_color_free(color);
}

View File

@ -1,208 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gtk/gtk.h>
#include "gdm-user-chooser-widget.h"
#include "gdm-user-chooser-dialog.h"
#define GDM_USER_CHOOSER_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogPrivate))
struct GdmUserChooserDialogPrivate
{
GtkWidget *chooser_widget;
};
enum {
PROP_0,
};
static void gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass);
static void gdm_user_chooser_dialog_init (GdmUserChooserDialog *user_chooser_dialog);
static void gdm_user_chooser_dialog_finalize (GObject *object);
G_DEFINE_TYPE (GdmUserChooserDialog, gdm_user_chooser_dialog, GTK_TYPE_DIALOG)
char *
gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog)
{
char *user_name;
g_return_val_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog), NULL);
user_name = gdm_user_chooser_widget_get_chosen_user_name (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget));
return user_name;
}
void
gdm_user_chooser_dialog_set_show_user_other (GdmUserChooserDialog *dialog,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
gdm_user_chooser_widget_set_show_user_other (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
}
void
gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
gdm_user_chooser_widget_set_show_user_guest (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
}
void
gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (dialog));
gdm_user_chooser_widget_set_show_user_auto (GDM_USER_CHOOSER_WIDGET (dialog->priv->chooser_widget), show_user);
}
static void
gdm_user_chooser_dialog_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_user_chooser_dialog_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GObject *
gdm_user_chooser_dialog_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GdmUserChooserDialog *user_chooser_dialog;
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
return G_OBJECT (user_chooser_dialog);
}
static void
gdm_user_chooser_dialog_dispose (GObject *object)
{
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->dispose (object);
}
static void
gdm_user_chooser_dialog_class_init (GdmUserChooserDialogClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gdm_user_chooser_dialog_get_property;
object_class->set_property = gdm_user_chooser_dialog_set_property;
object_class->constructor = gdm_user_chooser_dialog_constructor;
object_class->dispose = gdm_user_chooser_dialog_dispose;
object_class->finalize = gdm_user_chooser_dialog_finalize;
g_type_class_add_private (klass, sizeof (GdmUserChooserDialogPrivate));
}
static void
on_response (GdmUserChooserDialog *dialog,
gint response_id)
{
switch (response_id) {
default:
break;
}
}
static void
gdm_user_chooser_dialog_init (GdmUserChooserDialog *dialog)
{
dialog->priv = GDM_USER_CHOOSER_DIALOG_GET_PRIVATE (dialog);
dialog->priv->chooser_widget = gdm_user_chooser_widget_new ();
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), dialog->priv->chooser_widget);
gtk_dialog_add_buttons (GTK_DIALOG (dialog),
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OK, GTK_RESPONSE_OK,
NULL);
g_signal_connect (dialog,
"response",
G_CALLBACK (on_response),
dialog);
gtk_widget_show_all (GTK_WIDGET (dialog));
}
static void
gdm_user_chooser_dialog_finalize (GObject *object)
{
GdmUserChooserDialog *user_chooser_dialog;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_USER_CHOOSER_DIALOG (object));
user_chooser_dialog = GDM_USER_CHOOSER_DIALOG (object);
g_return_if_fail (user_chooser_dialog->priv != NULL);
G_OBJECT_CLASS (gdm_user_chooser_dialog_parent_class)->finalize (object);
}
GtkWidget *
gdm_user_chooser_dialog_new (void)
{
GObject *object;
object = g_object_new (GDM_TYPE_USER_CHOOSER_DIALOG,
NULL);
return GTK_WIDGET (object);
}

View File

@ -1,62 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GDM_USER_CHOOSER_DIALOG_H
#define __GDM_USER_CHOOSER_DIALOG_H
#include <glib-object.h>
#include <gtk/gtkdialog.h>
G_BEGIN_DECLS
#define GDM_TYPE_USER_CHOOSER_DIALOG (gdm_user_chooser_dialog_get_type ())
#define GDM_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialog))
#define GDM_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
#define GDM_IS_USER_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_DIALOG))
#define GDM_IS_USER_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_DIALOG))
#define GDM_USER_CHOOSER_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_DIALOG, GdmUserChooserDialogClass))
typedef struct GdmUserChooserDialogPrivate GdmUserChooserDialogPrivate;
typedef struct
{
GtkDialog parent;
GdmUserChooserDialogPrivate *priv;
} GdmUserChooserDialog;
typedef struct
{
GtkDialogClass parent_class;
} GdmUserChooserDialogClass;
GType gdm_user_chooser_dialog_get_type (void);
GtkWidget * gdm_user_chooser_dialog_new (void);
char * gdm_user_chooser_dialog_get_chosen_user_name (GdmUserChooserDialog *dialog);
void gdm_user_chooser_dialog_set_show_other_user (GdmUserChooserDialog *dialog,
gboolean show);
void gdm_user_chooser_dialog_set_show_user_guest (GdmUserChooserDialog *dialog,
gboolean show);
void gdm_user_chooser_dialog_set_show_user_auto (GdmUserChooserDialog *dialog,
gboolean show);
G_END_DECLS
#endif /* __GDM_USER_CHOOSER_DIALOG_H */

View File

@ -1,723 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
* Copyright (C) 2007 Ray Strode <rstrode@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#include <sys/stat.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include <gconf/gconf-client.h>
#include "gdm-user-manager.h"
#include "gdm-user-chooser-widget.h"
#define KEY_DISABLE_USER_LIST "/apps/gdm/simple-greeter/disable_user_list"
enum {
USER_NO_DISPLAY = 1 << 0,
USER_ACCOUNT_DISABLED = 1 << 1,
};
#define DEFAULT_USER_ICON "stock_person"
#define GDM_USER_CHOOSER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetPrivate))
#define MAX_ICON_SIZE 128
struct GdmUserChooserWidgetPrivate
{
GdmUserManager *manager;
GtkIconTheme *icon_theme;
GdkPixbuf *logged_in_pixbuf;
GdkPixbuf *stock_person_pixbuf;
guint loaded : 1;
guint show_user_other : 1;
guint show_user_guest : 1;
guint show_user_auto : 1;
guint show_normal_users : 1;
guint load_idle_id;
};
enum {
PROP_0,
PROP_SHOW_USER_GUEST,
PROP_SHOW_USER_AUTO,
PROP_SHOW_USER_OTHER,
};
static void gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass);
static void gdm_user_chooser_widget_init (GdmUserChooserWidget *user_chooser_widget);
static void gdm_user_chooser_widget_finalize (GObject *object);
G_DEFINE_TYPE (GdmUserChooserWidget, gdm_user_chooser_widget, GDM_TYPE_CHOOSER_WIDGET)
static int
get_font_height_for_widget (GtkWidget *widget)
{
PangoFontMetrics *metrics;
PangoContext *context;
int ascent;
int descent;
int height;
gtk_widget_ensure_style (widget);
context = gtk_widget_get_pango_context (widget);
metrics = pango_context_get_metrics (context,
widget->style->font_desc,
pango_context_get_language (context));
ascent = pango_font_metrics_get_ascent (metrics);
descent = pango_font_metrics_get_descent (metrics);
height = PANGO_PIXELS (ascent + descent);
pango_font_metrics_unref (metrics);
return height;
}
static int
get_icon_height_for_widget (GtkWidget *widget)
{
int font_height;
int height;
font_height = get_font_height_for_widget (widget);
height = 3 * font_height;
if (height > MAX_ICON_SIZE) {
height = MAX_ICON_SIZE;
}
g_debug ("GdmUserChooserWidget: font height %d; using icon size %d", font_height, height);
return height;
}
static void
add_user_other (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_OTHER,
NULL,
_("Other..."),
_("Choose a different account"),
0,
FALSE,
TRUE);
}
static void
add_user_guest (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_GUEST,
widget->priv->stock_person_pixbuf,
_("Guest"),
_("Login as a temporary guest"),
0,
FALSE,
TRUE);
}
static void
add_user_auto (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_AUTO,
NULL,
_("Automatic Login"),
_("Automatically login to the system after selecting options"),
0,
FALSE,
TRUE);
}
static void
remove_user_other (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_OTHER);
}
static void
remove_user_guest (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_GUEST);
}
static void
remove_user_auto (GdmUserChooserWidget *widget)
{
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
GDM_USER_CHOOSER_USER_AUTO);
}
void
gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
if (widget->priv->show_user_other != show_user) {
widget->priv->show_user_other = show_user;
if (show_user) {
add_user_other (widget);
} else {
remove_user_other (widget);
}
}
}
void
gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
if (widget->priv->show_user_guest != show_user) {
widget->priv->show_user_guest = show_user;
if (show_user) {
add_user_guest (widget);
} else {
remove_user_guest (widget);
}
}
}
void
gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
gboolean show_user)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
if (widget->priv->show_user_auto != show_user) {
widget->priv->show_user_auto = show_user;
if (show_user) {
add_user_auto (widget);
} else {
remove_user_auto (widget);
}
}
}
char *
gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget)
{
g_return_val_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget), NULL);
return gdm_chooser_widget_get_active_item (GDM_CHOOSER_WIDGET (widget));
}
void
gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
const char *name)
{
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
gdm_chooser_widget_set_active_item (GDM_CHOOSER_WIDGET (widget), name);
}
void
gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
gboolean show_only) {
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (widget));
gdm_chooser_widget_set_hide_inactive_items (GDM_CHOOSER_WIDGET (widget),
show_only);
}
static void
gdm_user_chooser_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdmUserChooserWidget *self;
self = GDM_USER_CHOOSER_WIDGET (object);
switch (prop_id) {
case PROP_SHOW_USER_AUTO:
gdm_user_chooser_widget_set_show_user_auto (self, g_value_get_boolean (value));
break;
case PROP_SHOW_USER_GUEST:
gdm_user_chooser_widget_set_show_user_guest (self, g_value_get_boolean (value));
break;
case PROP_SHOW_USER_OTHER:
gdm_user_chooser_widget_set_show_user_other (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_user_chooser_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdmUserChooserWidget *self;
self = GDM_USER_CHOOSER_WIDGET (object);
switch (prop_id) {
case PROP_SHOW_USER_AUTO:
g_value_set_boolean (value, self->priv->show_user_auto);
break;
case PROP_SHOW_USER_GUEST:
g_value_set_boolean (value, self->priv->show_user_guest);
break;
case PROP_SHOW_USER_OTHER:
g_value_set_boolean (value, self->priv->show_user_other);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
is_user_list_disabled (GdmUserChooserWidget *widget)
{
GConfClient *client;
GError *error;
gboolean result;
client = gconf_client_get_default ();
error = NULL;
result = gconf_client_get_bool (client, KEY_DISABLE_USER_LIST, &error);
if (error != NULL) {
g_debug ("GdmUserChooserWidget: unable to get disable-user-list configuration: %s", error->message);
g_error_free (error);
}
g_object_unref (client);
return result;
}
static void
add_user (GdmUserChooserWidget *widget,
GdmUser *user)
{
GdkPixbuf *pixbuf;
char *tooltip;
gboolean is_logged_in;
int size;
if (!widget->priv->show_normal_users) {
return;
}
size = get_icon_height_for_widget (widget);
pixbuf = gdm_user_render_icon (user, size);
if (pixbuf == NULL && widget->priv->stock_person_pixbuf != NULL) {
pixbuf = g_object_ref (widget->priv->stock_person_pixbuf);
}
tooltip = g_strdup_printf (_("Log in as %s"),
gdm_user_get_user_name (user));
is_logged_in = gdm_user_get_num_sessions (user) > 0;
g_debug ("GdmUserChooserWidget: User added name:%s logged-in:%d pixbuf:%p",
gdm_user_get_user_name (user),
is_logged_in,
pixbuf);
gdm_chooser_widget_add_item (GDM_CHOOSER_WIDGET (widget),
gdm_user_get_user_name (user),
pixbuf,
gdm_user_get_real_name (user),
tooltip,
gdm_user_get_login_frequency (user),
is_logged_in,
FALSE);
g_free (tooltip);
if (pixbuf != NULL) {
g_object_unref (pixbuf);
}
}
static void
on_user_added (GdmUserManager *manager,
GdmUser *user,
GdmUserChooserWidget *widget)
{
/* wait for all users to be loaded */
if (! widget->priv->loaded) {
return;
}
add_user (widget, user);
}
static void
on_user_removed (GdmUserManager *manager,
GdmUser *user,
GdmUserChooserWidget *widget)
{
const char *user_name;
g_debug ("GdmUserChooserWidget: User removed: %s", gdm_user_get_user_name (user));
/* wait for all users to be loaded */
if (! widget->priv->loaded) {
return;
}
user_name = gdm_user_get_user_name (user);
gdm_chooser_widget_remove_item (GDM_CHOOSER_WIDGET (widget),
user_name);
}
static void
on_user_is_logged_in_changed (GdmUserManager *manager,
GdmUser *user,
GdmUserChooserWidget *widget)
{
const char *user_name;
gboolean is_logged_in;
g_debug ("GdmUserChooserWidget: User logged in changed: %s", gdm_user_get_user_name (user));
user_name = gdm_user_get_user_name (user);
is_logged_in = gdm_user_get_num_sessions (user) > 0;
gdm_chooser_widget_set_item_in_use (GDM_CHOOSER_WIDGET (widget),
user_name,
is_logged_in);
}
static void
on_user_login_frequency_changed (GdmUserManager *manager,
GdmUser *user,
GdmUserChooserWidget *widget)
{
const char *user_name;
gulong freq;
g_debug ("GdmUserChooserWidget: User login frequency changed: %s", gdm_user_get_user_name (user));
user_name = gdm_user_get_user_name (user);
freq = gdm_user_get_login_frequency (user);
gdm_chooser_widget_set_item_priority (GDM_CHOOSER_WIDGET (widget),
user_name,
freq);
}
static void
on_users_loaded (GdmUserManager *manager,
GdmUserChooserWidget *widget)
{
GSList *users;
widget->priv->loaded = TRUE;
g_debug ("GdmUserChooserWidget: Users loaded");
users = gdm_user_manager_list_users (manager);
while (users != NULL) {
add_user (widget, users->data);
users = g_slist_delete_link (users, users);
}
gtk_widget_grab_focus (GTK_WIDGET (widget));
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
}
static gboolean
load_users (GdmUserChooserWidget *widget)
{
if (widget->priv->show_normal_users) {
widget->priv->manager = gdm_user_manager_ref_default ();
g_signal_connect (widget->priv->manager,
"user-added",
G_CALLBACK (on_user_added),
widget);
g_signal_connect (widget->priv->manager,
"user-removed",
G_CALLBACK (on_user_removed),
widget);
g_signal_connect (widget->priv->manager,
"users-loaded",
G_CALLBACK (on_users_loaded),
widget);
g_signal_connect (widget->priv->manager,
"user-is-logged-in-changed",
G_CALLBACK (on_user_is_logged_in_changed),
widget);
g_signal_connect (widget->priv->manager,
"user-login-frequency-changed",
G_CALLBACK (on_user_login_frequency_changed),
widget);
} else {
gdm_chooser_widget_loaded (GDM_CHOOSER_WIDGET (widget));
}
widget->priv->load_idle_id = 0;
return FALSE;
}
static GObject *
gdm_user_chooser_widget_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GdmUserChooserWidget *widget;
widget = GDM_USER_CHOOSER_WIDGET (G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->constructor (type,
n_construct_properties,
construct_properties));
widget->priv->show_normal_users = !is_user_list_disabled (widget);
widget->priv->load_idle_id = g_idle_add ((GSourceFunc)load_users, widget);
return G_OBJECT (widget);
}
static void
gdm_user_chooser_widget_dispose (GObject *object)
{
GdmUserChooserWidget *widget;
widget = GDM_USER_CHOOSER_WIDGET (object);
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->dispose (object);
if (widget->priv->load_idle_id > 0) {
g_source_remove (widget->priv->load_idle_id);
widget->priv->load_idle_id = 0;
}
if (widget->priv->logged_in_pixbuf != NULL) {
g_object_unref (widget->priv->logged_in_pixbuf);
widget->priv->logged_in_pixbuf = NULL;
}
if (widget->priv->stock_person_pixbuf != NULL) {
g_object_unref (widget->priv->stock_person_pixbuf);
widget->priv->stock_person_pixbuf = NULL;
}
}
static void
gdm_user_chooser_widget_class_init (GdmUserChooserWidgetClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gdm_user_chooser_widget_get_property;
object_class->set_property = gdm_user_chooser_widget_set_property;
object_class->constructor = gdm_user_chooser_widget_constructor;
object_class->dispose = gdm_user_chooser_widget_dispose;
object_class->finalize = gdm_user_chooser_widget_finalize;
g_object_class_install_property (object_class,
PROP_SHOW_USER_AUTO,
g_param_spec_boolean ("show-user-auto",
"show user auto",
"show user auto",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_SHOW_USER_GUEST,
g_param_spec_boolean ("show-user-guest",
"show user guest",
"show user guest",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_SHOW_USER_OTHER,
g_param_spec_boolean ("show-user-other",
"show user other",
"show user other",
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GdmUserChooserWidgetPrivate));
}
static GdkPixbuf *
get_stock_person_pixbuf (GdmUserChooserWidget *widget)
{
GdkPixbuf *pixbuf;
int size;
size = get_icon_height_for_widget (widget);
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
DEFAULT_USER_ICON,
size,
0,
NULL);
return pixbuf;
}
static GdkPixbuf *
get_logged_in_pixbuf (GdmUserChooserWidget *widget)
{
GdkPixbuf *pixbuf;
int size;
size = get_icon_height_for_widget (widget);
pixbuf = gtk_icon_theme_load_icon (widget->priv->icon_theme,
"emblem-default",
size / 3,
0,
NULL);
return pixbuf;
}
typedef struct {
GdkPixbuf *old_icon;
GdkPixbuf *new_icon;
} IconUpdateData;
static gboolean
update_icons (GdmChooserWidget *widget,
const char *id,
GdkPixbuf **image,
char **name,
char **comment,
gulong *priority,
gboolean *is_in_use,
gboolean *is_separate,
IconUpdateData *data)
{
if (data->old_icon == *image) {
*image = data->new_icon;
return TRUE;
}
return FALSE;
}
static void
load_icons (GdmUserChooserWidget *widget)
{
GdkPixbuf *old_pixbuf;
IconUpdateData data;
if (widget->priv->logged_in_pixbuf != NULL) {
g_object_unref (widget->priv->logged_in_pixbuf);
}
widget->priv->logged_in_pixbuf = get_logged_in_pixbuf (widget);
old_pixbuf = widget->priv->stock_person_pixbuf;
widget->priv->stock_person_pixbuf = get_stock_person_pixbuf (widget);
/* update the icons in the model */
data.old_icon = old_pixbuf;
data.new_icon = widget->priv->stock_person_pixbuf;
gdm_chooser_widget_update_foreach_item (GDM_CHOOSER_WIDGET (widget),
(GdmChooserUpdateForeachFunc)update_icons,
&data);
if (old_pixbuf != NULL) {
g_object_unref (old_pixbuf);
}
}
static void
on_icon_theme_changed (GtkIconTheme *icon_theme,
GdmUserChooserWidget *widget)
{
g_debug ("GdmUserChooserWidget: icon theme changed");
load_icons (widget);
}
static void
setup_icons (GdmUserChooserWidget *widget)
{
if (gtk_widget_has_screen (GTK_WIDGET (widget))) {
widget->priv->icon_theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (widget)));
} else {
widget->priv->icon_theme = gtk_icon_theme_get_default ();
}
if (widget->priv->icon_theme != NULL) {
g_signal_connect (widget->priv->icon_theme,
"changed",
G_CALLBACK (on_icon_theme_changed),
widget);
}
load_icons (widget);
}
static void
gdm_user_chooser_widget_init (GdmUserChooserWidget *widget)
{
widget->priv = GDM_USER_CHOOSER_WIDGET_GET_PRIVATE (widget);
gdm_chooser_widget_set_separator_position (GDM_CHOOSER_WIDGET (widget),
GDM_CHOOSER_WIDGET_POSITION_BOTTOM);
gdm_chooser_widget_set_in_use_message (GDM_CHOOSER_WIDGET (widget),
_("Currently logged in"));
setup_icons (widget);
}
static void
gdm_user_chooser_widget_finalize (GObject *object)
{
GdmUserChooserWidget *widget;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_USER_CHOOSER_WIDGET (object));
widget = GDM_USER_CHOOSER_WIDGET (object);
g_return_if_fail (widget->priv != NULL);
G_OBJECT_CLASS (gdm_user_chooser_widget_parent_class)->finalize (object);
}
GtkWidget *
gdm_user_chooser_widget_new (void)
{
GObject *object;
object = g_object_new (GDM_TYPE_USER_CHOOSER_WIDGET,
NULL);
return GTK_WIDGET (object);
}

View File

@ -1,70 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#ifndef __GDM_USER_CHOOSER_WIDGET_H
#define __GDM_USER_CHOOSER_WIDGET_H
#include <glib-object.h>
#include "gdm-chooser-widget.h"
G_BEGIN_DECLS
#define GDM_TYPE_USER_CHOOSER_WIDGET (gdm_user_chooser_widget_get_type ())
#define GDM_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidget))
#define GDM_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
#define GDM_IS_USER_CHOOSER_WIDGET(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_USER_CHOOSER_WIDGET))
#define GDM_IS_USER_CHOOSER_WIDGET_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_USER_CHOOSER_WIDGET))
#define GDM_USER_CHOOSER_WIDGET_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_USER_CHOOSER_WIDGET, GdmUserChooserWidgetClass))
typedef struct GdmUserChooserWidgetPrivate GdmUserChooserWidgetPrivate;
typedef struct
{
GdmChooserWidget parent;
GdmUserChooserWidgetPrivate *priv;
} GdmUserChooserWidget;
typedef struct
{
GdmChooserWidgetClass parent_class;
} GdmUserChooserWidgetClass;
#define GDM_USER_CHOOSER_USER_OTHER "__other"
#define GDM_USER_CHOOSER_USER_GUEST "__guest"
#define GDM_USER_CHOOSER_USER_AUTO "__auto"
GType gdm_user_chooser_widget_get_type (void);
GtkWidget * gdm_user_chooser_widget_new (void);
char * gdm_user_chooser_widget_get_chosen_user_name (GdmUserChooserWidget *widget);
void gdm_user_chooser_widget_set_chosen_user_name (GdmUserChooserWidget *widget,
const char *user_name);
void gdm_user_chooser_widget_set_show_only_chosen (GdmUserChooserWidget *widget,
gboolean show_only);
void gdm_user_chooser_widget_set_show_user_other (GdmUserChooserWidget *widget,
gboolean show);
void gdm_user_chooser_widget_set_show_user_guest (GdmUserChooserWidget *widget,
gboolean show);
void gdm_user_chooser_widget_set_show_user_auto (GdmUserChooserWidget *widget,
gboolean show);
G_END_DECLS
#endif /* __GDM_USER_CHOOSER_WIDGET_H */

View File

@ -35,7 +35,8 @@
#endif /* HAVE_PATHS_H */
#include <glib.h>
#include <glib/gi18n.h>
/* Note on sync with gdm; need to use -lib here */
#include <glib/gi18n-lib.h>
#include <glib/gstdio.h>
#include <glib-object.h>
#include <gio/gio.h>

View File

@ -20,12 +20,14 @@
#include <config.h>
#include <float.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib/gi18n.h>
/* Note on sync with gdm; need to use -lib here */
#include <glib/gi18n-lib.h>
#include <gio/gio.h>
#include <gtk/gtk.h>
@ -238,8 +240,8 @@ gdm_user_class_init (GdmUserClass *class)
g_object_class_install_property (gobject_class,
PROP_MANAGER,
g_param_spec_object ("manager",
_("Manager"),
_("The user manager object this user is controlled by."),
"Manager",
"The user manager object this user is controlled by.",
GDM_TYPE_USER_MANAGER,
(G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)));
@ -411,13 +413,16 @@ _gdm_user_update (GdmUser *user,
/* Display Name */
if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0') {
gchar *first_comma;
gchar *real_name_utf8;
first_comma = strchr (pwent->pw_gecos, ',');
real_name_utf8 = g_locale_to_utf8 (pwent->pw_gecos, -1, NULL, NULL, NULL);
first_comma = strchr (real_name_utf8, ',');
if (first_comma) {
real_name = g_strndup (pwent->pw_gecos,
(first_comma - pwent->pw_gecos));
real_name = g_strndup (real_name_utf8, first_comma - real_name_utf8);
g_free (real_name_utf8);
} else {
real_name = g_strdup (pwent->pw_gecos);
real_name = real_name_utf8;
}
if (real_name[0] == '\0') {
@ -881,7 +886,7 @@ curved_rectangle (cairo_t *cr,
x1 = x0 + width;
y1 = y0 + height;
if (!width || !height) {
if (width < FLT_EPSILON || height < FLT_EPSILON) {
return;
}
@ -1156,8 +1161,8 @@ gdm_user_render_icon (GdmUser *user,
} else {
pixbuf = NULL;
}
out:
g_free (path);
out:
if (pixbuf != NULL) {
framed = frame_pixbuf (pixbuf);

View File

@ -153,6 +153,9 @@ gnome_shell_plugin_constructed (GObject *object)
ClutterBackend *backend;
cairo_font_options_t *font_options;
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
/* Disable text mipmapping; it causes problems on pre-GEM Intel
* drivers and we should just be rendering text at the right
* size rather than scaling it. If we do effects where we dynamically

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

@ -1,4 +1,4 @@
#!/usr/bin/python
#!@PYTHON@
import atexit
import optparse
@ -14,43 +14,6 @@ import termios
import time
import errno
def find_cmd (cmd_list):
"""
Takes a list of command candidates and returns the first one that exists.
Raises a system exit if none of the commands exist.
"""
for cmd in cmd_list:
if os.path.exists(cmd):
return cmd
raise SystemExit("None of the commands %s exist" % cmd_list)
def pidof(command):
pidof_cmd = find_cmd(["/sbin/pidof", "/bin/pidof", "/usr/bin/pidof"])
pidof = subprocess.Popen([pidof_cmd, command], stdout=subprocess.PIPE)
pids = pidof.communicate()[0].split()
pidof.wait()
# pidof doesn't have a "current user only" option, so we may have
# gotten the pids of other users' processes. Fix that.
for pid in pids:
try:
os.kill(int(pid), 0)
return pid
except Exception, e:
pass
return None
def kill_gnome_panel(pid):
if options.verbose:
print "Terminating panel process %s" % pid
devnull = open("/dev/null", "w")
subprocess.call(["gdb", "-batch-silent",
"-ex", "call panel_session_do_not_restart()",
"-ex", "call exit(0)",
"-p", pid], stdout=devnull, stderr=devnull)
devnull.close()
def start_xephyr():
tmpdir = tempfile.mkdtemp("", "gnome-shell.")
atexit.register(shutil.rmtree, tmpdir)
@ -122,25 +85,27 @@ def start_shell():
top_dir = os.path.dirname(bin_dir)
plugin = os.path.join(top_dir, 'src', 'libgnome-shell.la')
typelib_dir = os.path.join(top_dir, "src")
taskpanel_dir = os.path.join(top_dir, "src")
js_dir = os.path.join(top_dir, "js")
data_dir = os.path.join(top_dir, "data")
else:
running_from_source_tree = False
plugin = 'libgnome-shell'
js_dir = os.path.join('@pkgdatadir@', 'js')
taskpanel_dir = '@libexecdir@'
# Set up environment
env = dict(os.environ)
env.update({'GNOME_SHELL_JS' : '@GJS_JS_DIR@:@GJS_JS_NATIVE_DIR@:' + js_dir,
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', '') + ':' + taskpanel_dir,
'PATH' : '@MUTTER_BIN_DIR@:' + os.environ.get('PATH', ''),
'GNOME_DISABLE_CRASH_DIALOG' : '1'})
if running_from_source_tree:
env.update({'GNOME_SHELL_DATADIR' : data_dir,
'GI_TYPELIB_PATH' : typelib_dir})
jhbuild_gconf_source = os.path.join('@sysconfdir@', 'gconf/2/path.jhbuild')
if os.path.exists(jhbuild_gconf_source):
env['GCONF_DEFAULT_SOURCE_PATH'] = jhbuild_gconf_source
# Work around Ubuntu xulrunner bug,
# http://bugzilla.gnome.org/show_bug.cgi?id=573413
pkgconfig = subprocess.Popen(['pkg-config', '--variable=sdkdir', 'mozilla-js'],
@ -187,11 +152,47 @@ def start_shell():
else:
args = []
args.extend(['mutter', '--mutter-plugins=' + plugin, '--replace'])
args.extend(['mutter', '--mutter-plugins=' + plugin])
if options.replace:
args.append('--replace')
if options.sync:
args.append('--sync')
return subprocess.Popen(args, env=env)
def restore_gnome():
# Do imports lazily to save time and memory
import gio
import gconf
# We don't want to start the new gnome-panel in the current
# directory; $HOME is better for stuff launched from it
os.chdir(os.path.expanduser("~"))
def launch_component(gconf_path):
client = gconf.client_get_default()
component = client.get_string(gconf_path)
if component == None or component == "":
return
# See gnome-session/gsm-util.c:gsm_util_find_desktop_file_for_app_name()
# The one difference is that we don't search the autostart directories,
# and just search normal application search path. (Gio doesnt' know
# how to search the autostart dirs, so we'd have to do that ourselves.)
appinfo = None
try:
appinfo = gio.unix.DesktopAppInfo(component + ".desktop")
except:
try:
appinfo = gio.unix.DesktopAppInfo("gnome-" + component + ".desktop")
except:
pass
if appinfo:
appinfo.launch()
launch_component("/desktop/gnome/session/required_components/windowmanager")
launch_component("/desktop/gnome/session/required_components/panel")
# Main program
@ -204,6 +205,8 @@ parser.add_option("", "--debug-command", metavar="COMMAND",
help="Command to use for debugging (defaults to 'gdb --args')")
parser.add_option("-v", "--verbose", action="store_true")
parser.add_option("", "--sync", action="store_true")
parser.add_option("", "--xephyr", action="store_true",
help="Run a debugging instance inside Xephyr")
parser.add_option("", "--geometry", metavar="GEOMETRY",
help="Specify Xephyr screen geometry",
default="1024x768");
@ -224,18 +227,6 @@ elif options.debug:
if options.wide:
options.geometry = "1280x800"
metacity_pid = pidof("metacity")
compiz_pid = pidof("compiz.real") or pidof("compiz")
gnome_panel_pid = pidof("gnome-panel")
# Run in Xephyr if gnome-panel is already running and the user didn't
# specify --replace. Otherwise, run fullscreen
if options.replace:
run_in_xephyr = False
else:
run_in_xephyr = (metacity_pid != None or compiz_pid != None or
gnome_panel_pid != None)
# Figure out whether or not to use GL_EXT_texture_from_pixmap. By default
# we use it iff we aren't running Xephyr, but we allow the user to
# explicitly disable it.
@ -246,7 +237,7 @@ if 'GNOME_SHELL_DISABLE_TFP' in os.environ and \
use_tfp = False
else:
# tfp does not work correctly in Xephyr
use_tfp = not run_in_xephyr
use_tfp = not options.xephyr
if options.verbose:
print "Starting shell"
@ -256,21 +247,26 @@ if options.debug:
# later, in case we kill gdb at a bad time
termattrs = termios.tcgetattr(0);
# We only respawn the previous environment on abnormal exit;
# for a clean exit, we assume that gnome-shell was replaced with
# something else.
normal_exit = False
try:
if run_in_xephyr:
shell = start_xephyr()
start_shell()
shell = None
if options.xephyr:
xephyr = start_xephyr()
# This makes us not grab the org.gnome.Panel name
os.environ['GNOME_SHELL_NO_REPLACE_PANEL'] = '1'
shell = start_shell()
else:
if gnome_panel_pid is not None:
kill_gnome_panel(gnome_panel_pid)
xephyr = None
shell = start_shell()
# Wait for shell to exit
if options.verbose:
print "Waiting for shell to exit"
shell.wait()
if options.verbose:
print "Shell is dead"
except KeyboardInterrupt, e:
try:
@ -278,24 +274,31 @@ except KeyboardInterrupt, e:
except:
pass
shell.wait()
if options.verbose:
print "Shell killed"
finally:
# Clean up Xephyr if it outlived the shell
if xephyr:
try:
os.kill(xephyr.pid, signal.SIGKILL)
except OSError:
pass
if shell is None:
print "Failed to start shell"
elif shell.returncode == 0:
normal_exit = True
if options.verbose:
print "Shell exited normally"
elif shell.returncode < 0:
# Python has no mapping for strsignal; not worth using
# ctypes for this.
print "Shell killed with signal %d" % - shell.returncode
else:
# Normal reason here would be losing connection the X server
if options.verbose:
print "Shell exited with return code %d" % shell.returncode
if options.debug:
termios.tcsetattr(0, termios.TCSANOW, termattrs);
if not run_in_xephyr:
# Restart gnome-panel and window manager
if metacity_pid:
if options.verbose:
print "Restarting Metacity"
subprocess.Popen(["/usr/bin/metacity"])
elif compiz_pid:
if options.verbose:
print "Restarting Compiz"
subprocess.Popen(["/usr/bin/compiz"])
if gnome_panel_pid:
if options.verbose:
print "Restarting gnome-panel"
subprocess.Popen(["/usr/bin/gnome-panel"])
if not options.xephyr and options.replace and not normal_exit:
restore_gnome()

View File

@ -1,90 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include "shell-panel-window.h"
#include <libwnck/libwnck.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus-glib.h>
static void
on_name_owner_changed (DBusGProxy *proxy,
const char *name,
const char *prev_owner,
const char *new_owner,
gpointer user_data)
{
if (strcmp (name, "org.gnome.Shell") == 0 && new_owner[0] == '\0')
exit (0);
}
static void
monitor_main_shell (const char *shell_name)
{
DBusGConnection *session;
DBusGProxy *driver;
GError *error = NULL;
gboolean have_shell;
session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
driver = dbus_g_proxy_new_for_name (session,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!dbus_g_proxy_call (driver, "NameHasOwner", &error, G_TYPE_STRING,
shell_name, G_TYPE_INVALID, G_TYPE_BOOLEAN,
&have_shell, G_TYPE_INVALID))
{
/* Shouldn't happen */
exit (1);
}
if (!have_shell)
{
/* Shell doesn't exist; either crashed or was restarted. Just abort. */
exit (0);
}
dbus_g_proxy_add_signal (driver,
"NameOwnerChanged",
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (driver,
"NameOwnerChanged",
G_CALLBACK (on_name_owner_changed),
NULL,
NULL);
}
int
main (int argc, char **argv)
{
ShellPanelWindow *panel;
WnckScreen *screen;
WnckTasklist *tasks;
gtk_init (&argc, &argv);
if (argc != 2) {
g_printerr ("Usage: gnomeshell-taskpanel [PARENT_DBUS_SERVICE]\n");
exit (1);
}
monitor_main_shell (argv[1]);
panel = shell_panel_window_new ();
screen = wnck_screen_get_default();
tasks = WNCK_TASKLIST (wnck_tasklist_new (screen));
gtk_container_add (GTK_CONTAINER (panel), GTK_WIDGET (tasks));
gtk_widget_show_all (GTK_WIDGET (panel));
gtk_main ();
exit (0);
}

View File

@ -1,64 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include <mutter-plugin.h>
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
{
return NULL;
}
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin)
{
return NULL;
}
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
{
return NULL;
}
void
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
{
}
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height)
{
}
MetaScreen *
mutter_plugin_get_screen (MutterPlugin *plugin)
{
return NULL;
}
ClutterActor *
mutter_plugin_get_window_group (MutterPlugin *plugin)
{
return NULL;
}
Display *
meta_display_get_xdisplay (MetaDisplay *display)
{
return NULL;
}
MetaDisplay *
meta_screen_get_display (MetaScreen *display)
{
return NULL;
}
Window
meta_screen_get_xroot (MetaScreen *display)
{
return None;
}

768
src/nbtk/nbtk-adjustment.c Normal file
View File

@ -0,0 +1,768 @@
/*
* nbtk-adjustment.c: Adjustment object
*
* Copyright (C) 2008 OpenedHand
* Copyright (c) 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
* Port to Nbtk by: Robert Staudinger <robsta@openedhand.com>
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <glib-object.h>
#include <clutter/clutter.h>
#include "nbtk-adjustment.h"
#include "nbtk-marshal.h"
#include "nbtk-private.h"
G_DEFINE_TYPE (NbtkAdjustment, nbtk_adjustment, G_TYPE_OBJECT)
#define ADJUSTMENT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentPrivate))
struct _NbtkAdjustmentPrivate
{
/* Do not sanity-check values while constructing,
* not all properties may be set yet. */
gboolean is_constructing : 1;
gdouble lower;
gdouble upper;
gdouble value;
gdouble step_increment;
gdouble page_increment;
gdouble page_size;
/* For interpolation */
ClutterTimeline *interpolation;
gdouble old_position;
gdouble new_position;
/* For elasticity */
gboolean elastic;
guint bounce_source;
ClutterAlpha *bounce_alpha;
};
enum
{
PROP_0,
PROP_LOWER,
PROP_UPPER,
PROP_VALUE,
PROP_STEP_INC,
PROP_PAGE_INC,
PROP_PAGE_SIZE,
PROP_ELASTIC,
};
enum
{
CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
static gboolean nbtk_adjustment_set_lower (NbtkAdjustment *adjustment,
gdouble lower);
static gboolean nbtk_adjustment_set_upper (NbtkAdjustment *adjustment,
gdouble upper);
static gboolean nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment,
gdouble step);
static gboolean nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment,
gdouble page);
static gboolean nbtk_adjustment_set_page_size (NbtkAdjustment *adjustment,
gdouble size);
static void
nbtk_adjustment_constructed (GObject *object)
{
GObjectClass *g_class;
NbtkAdjustment *self = NBTK_ADJUSTMENT (object);
g_class = G_OBJECT_CLASS (nbtk_adjustment_parent_class);
/* The docs say we're suppose to chain up, but would crash without
* some extra care. */
if (g_class && g_class->constructed &&
g_class->constructed != nbtk_adjustment_constructed)
{
g_class->constructed (object);
}
NBTK_ADJUSTMENT (self)->priv->is_constructing = FALSE;
nbtk_adjustment_clamp_page (self, self->priv->lower, self->priv->upper);
}
static void
nbtk_adjustment_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NbtkAdjustmentPrivate *priv = NBTK_ADJUSTMENT (gobject)->priv;
switch (prop_id)
{
case PROP_LOWER:
g_value_set_double (value, priv->lower);
break;
case PROP_UPPER:
g_value_set_double (value, priv->upper);
break;
case PROP_VALUE:
g_value_set_double (value, priv->value);
break;
case PROP_STEP_INC:
g_value_set_double (value, priv->step_increment);
break;
case PROP_PAGE_INC:
g_value_set_double (value, priv->page_increment);
break;
case PROP_PAGE_SIZE:
g_value_set_double (value, priv->page_size);
break;
case PROP_ELASTIC:
g_value_set_boolean (value, priv->elastic);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_adjustment_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NbtkAdjustment *adj = NBTK_ADJUSTMENT (gobject);
switch (prop_id)
{
case PROP_LOWER:
nbtk_adjustment_set_lower (adj, g_value_get_double (value));
break;
case PROP_UPPER:
nbtk_adjustment_set_upper (adj, g_value_get_double (value));
break;
case PROP_VALUE:
nbtk_adjustment_set_value (adj, g_value_get_double (value));
break;
case PROP_STEP_INC:
nbtk_adjustment_set_step_increment (adj, g_value_get_double (value));
break;
case PROP_PAGE_INC:
nbtk_adjustment_set_page_increment (adj, g_value_get_double (value));
break;
case PROP_PAGE_SIZE:
nbtk_adjustment_set_page_size (adj, g_value_get_double (value));
break;
case PROP_ELASTIC:
nbtk_adjustment_set_elastic (adj, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
stop_interpolation (NbtkAdjustment *adjustment)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->interpolation)
{
clutter_timeline_stop (priv->interpolation);
g_object_unref (priv->interpolation);
priv->interpolation = NULL;
if (priv->bounce_alpha)
{
g_object_unref (priv->bounce_alpha);
priv->bounce_alpha = NULL;
}
}
if (priv->bounce_source)
{
g_source_remove (priv->bounce_source);
priv->bounce_source = 0;
}
}
static void
nbtk_adjustment_dispose (GObject *object)
{
stop_interpolation (NBTK_ADJUSTMENT (object));
G_OBJECT_CLASS (nbtk_adjustment_parent_class)->dispose (object);
}
static void
nbtk_adjustment_class_init (NbtkAdjustmentClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NbtkAdjustmentPrivate));
object_class->constructed = nbtk_adjustment_constructed;
object_class->get_property = nbtk_adjustment_get_property;
object_class->set_property = nbtk_adjustment_set_property;
object_class->dispose = nbtk_adjustment_dispose;
g_object_class_install_property (object_class,
PROP_LOWER,
g_param_spec_double ("lower",
"Lower",
"Lower bound",
-G_MAXDOUBLE,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_UPPER,
g_param_spec_double ("upper",
"Upper",
"Upper bound",
-G_MAXDOUBLE,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_VALUE,
g_param_spec_double ("value",
"Value",
"Current value",
-G_MAXDOUBLE,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_STEP_INC,
g_param_spec_double ("step-increment",
"Step Increment",
"Step increment",
0.0,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_PAGE_INC,
g_param_spec_double ("page-increment",
"Page Increment",
"Page increment",
0.0,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_PAGE_SIZE,
g_param_spec_double ("page-size",
"Page Size",
"Page size",
0.0,
G_MAXDOUBLE,
0.0,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_ELASTIC,
g_param_spec_boolean ("elastic",
"Elastic",
"Make interpolation "
"behave in an "
"'elastic' way and "
"stop clamping value.",
FALSE,
NBTK_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
/**
* NbtkAdjustment::changed:
*
* Emitted when any of the adjustment values have changed
*/
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NbtkAdjustmentClass, changed),
NULL, NULL,
_nbtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
nbtk_adjustment_init (NbtkAdjustment *self)
{
self->priv = ADJUSTMENT_PRIVATE (self);
self->priv->is_constructing = TRUE;
}
NbtkAdjustment *
nbtk_adjustment_new (gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
gdouble page_increment,
gdouble page_size)
{
return g_object_new (NBTK_TYPE_ADJUSTMENT,
"value", value,
"lower", lower,
"upper", upper,
"step-increment", step_increment,
"page-increment", page_increment,
"page-size", page_size,
NULL);
}
gdouble
nbtk_adjustment_get_value (NbtkAdjustment *adjustment)
{
NbtkAdjustmentPrivate *priv;
g_return_val_if_fail (NBTK_IS_ADJUSTMENT (adjustment), 0);
priv = adjustment->priv;
if (priv->interpolation)
{
return MAX (priv->lower,
MIN (priv->upper - priv->page_size,
priv->new_position));
}
else
return priv->value;
}
void
nbtk_adjustment_set_value (NbtkAdjustment *adjustment,
gdouble value)
{
NbtkAdjustmentPrivate *priv;
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
priv = adjustment->priv;
stop_interpolation (adjustment);
/* Defer clamp until after construction. */
if (!priv->is_constructing)
{
if (!priv->elastic)
value = CLAMP (value,
priv->lower,
MAX (priv->lower, priv->upper - priv->page_size));
}
if (priv->value != value)
{
priv->value = value;
g_object_notify (G_OBJECT (adjustment), "value");
}
}
void
nbtk_adjustment_clamp_page (NbtkAdjustment *adjustment,
gdouble lower,
gdouble upper)
{
NbtkAdjustmentPrivate *priv;
gboolean changed;
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
priv = adjustment->priv;
stop_interpolation (adjustment);
lower = CLAMP (lower, priv->lower, priv->upper - priv->page_size);
upper = CLAMP (upper, priv->lower + priv->page_size, priv->upper);
changed = FALSE;
if (priv->value + priv->page_size > upper)
{
priv->value = upper - priv->page_size;
changed = TRUE;
}
if (priv->value < lower)
{
priv->value = lower;
changed = TRUE;
}
if (changed)
g_object_notify (G_OBJECT (adjustment), "value");
}
static gboolean
nbtk_adjustment_set_lower (NbtkAdjustment *adjustment,
gdouble lower)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->lower != lower)
{
priv->lower = lower;
g_signal_emit (adjustment, signals[CHANGED], 0);
g_object_notify (G_OBJECT (adjustment), "lower");
/* Defer clamp until after construction. */
if (!priv->is_constructing)
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_adjustment_set_upper (NbtkAdjustment *adjustment,
gdouble upper)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->upper != upper)
{
priv->upper = upper;
g_signal_emit (adjustment, signals[CHANGED], 0);
g_object_notify (G_OBJECT (adjustment), "upper");
/* Defer clamp until after construction. */
if (!priv->is_constructing)
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_adjustment_set_step_increment (NbtkAdjustment *adjustment,
gdouble step)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->step_increment != step)
{
priv->step_increment = step;
g_signal_emit (adjustment, signals[CHANGED], 0);
g_object_notify (G_OBJECT (adjustment), "step-increment");
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_adjustment_set_page_increment (NbtkAdjustment *adjustment,
gdouble page)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->page_increment != page)
{
priv->page_increment = page;
g_signal_emit (adjustment, signals[CHANGED], 0);
g_object_notify (G_OBJECT (adjustment), "page-increment");
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_adjustment_set_page_size (NbtkAdjustment *adjustment,
gdouble size)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
if (priv->page_size != size)
{
priv->page_size = size;
g_signal_emit (adjustment, signals[CHANGED], 0);
g_object_notify (G_OBJECT (adjustment), "page_size");
/* Well explicitely clamp after construction. */
if (!priv->is_constructing)
nbtk_adjustment_clamp_page (adjustment, priv->lower, priv->upper);
return TRUE;
}
return FALSE;
}
void
nbtk_adjustment_set_values (NbtkAdjustment *adjustment,
gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
gdouble page_increment,
gdouble page_size)
{
NbtkAdjustmentPrivate *priv;
gboolean emit_changed = FALSE;
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
g_return_if_fail (page_size >= 0 && page_size <= G_MAXDOUBLE);
g_return_if_fail (step_increment >= 0 && step_increment <= G_MAXDOUBLE);
g_return_if_fail (page_increment >= 0 && page_increment <= G_MAXDOUBLE);
priv = adjustment->priv;
stop_interpolation (adjustment);
emit_changed = FALSE;
g_object_freeze_notify (G_OBJECT (adjustment));
emit_changed |= nbtk_adjustment_set_lower (adjustment, lower);
emit_changed |= nbtk_adjustment_set_upper (adjustment, upper);
emit_changed |= nbtk_adjustment_set_step_increment (adjustment, step_increment);
emit_changed |= nbtk_adjustment_set_page_increment (adjustment, page_increment);
emit_changed |= nbtk_adjustment_set_page_size (adjustment, page_size);
if (value != priv->value)
{
nbtk_adjustment_set_value (adjustment, value);
emit_changed = TRUE;
}
if (emit_changed)
g_signal_emit (G_OBJECT (adjustment), signals[CHANGED], 0);
g_object_thaw_notify (G_OBJECT (adjustment));
}
void
nbtk_adjustment_get_values (NbtkAdjustment *adjustment,
gdouble *value,
gdouble *lower,
gdouble *upper,
gdouble *step_increment,
gdouble *page_increment,
gdouble *page_size)
{
NbtkAdjustmentPrivate *priv;
g_return_if_fail (NBTK_IS_ADJUSTMENT (adjustment));
priv = adjustment->priv;
if (lower)
*lower = priv->lower;
if (upper)
*upper = priv->upper;
if (value)
*value = nbtk_adjustment_get_value (adjustment);
if (step_increment)
*step_increment = priv->step_increment;
if (page_increment)
*page_increment = priv->page_increment;
if (page_size)
*page_size = priv->page_size;
}
static void
interpolation_new_frame_cb (ClutterTimeline *timeline,
guint msecs,
NbtkAdjustment *adjustment)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
priv->interpolation = NULL;
if (priv->elastic)
{
gdouble progress = clutter_alpha_get_alpha (priv->bounce_alpha) / 1.0;
gdouble dx = priv->old_position
+ (priv->new_position - priv->old_position)
* progress;
nbtk_adjustment_set_value (adjustment, dx);
}
else
nbtk_adjustment_set_value (adjustment,
priv->old_position +
(priv->new_position - priv->old_position) *
clutter_timeline_get_progress (timeline));
priv->interpolation = timeline;
}
static void
interpolation_completed_cb (ClutterTimeline *timeline,
NbtkAdjustment *adjustment)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
stop_interpolation (adjustment);
nbtk_adjustment_set_value (adjustment, priv->new_position);
}
/* Note, there's super-optimal code that does a similar thing in
* clutter-alpha.c
*
* Tried this instead of CLUTTER_ALPHA_SINE_INC, but I think SINE_INC looks
* better. Leaving code here in case this is revisited.
*/
/*
static guint32
bounce_alpha_func (ClutterAlpha *alpha,
gpointer user_data)
{
ClutterFixed progress, angle;
ClutterTimeline *timeline = clutter_alpha_get_timeline (alpha);
progress = clutter_timeline_get_progressx (timeline);
angle = clutter_qmulx (CFX_PI_2 + CFX_PI_4/2, progress);
return clutter_sinx (angle) +
(CFX_ONE - clutter_sinx (CFX_PI_2 + CFX_PI_4/2));
}
*/
void
nbtk_adjustment_interpolate (NbtkAdjustment *adjustment,
gdouble value,
guint duration)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
stop_interpolation (adjustment);
if (duration <= 1)
{
nbtk_adjustment_set_value (adjustment, value);
return;
}
priv->old_position = priv->value;
priv->new_position = value;
priv->interpolation = clutter_timeline_new (duration);
if (priv->elastic)
priv->bounce_alpha = clutter_alpha_new_full (priv->interpolation,
CLUTTER_LINEAR);
g_signal_connect (priv->interpolation,
"new-frame",
G_CALLBACK (interpolation_new_frame_cb),
adjustment);
g_signal_connect (priv->interpolation,
"completed",
G_CALLBACK (interpolation_completed_cb),
adjustment);
clutter_timeline_start (priv->interpolation);
}
gboolean
nbtk_adjustment_get_elastic (NbtkAdjustment *adjustment)
{
return adjustment->priv->elastic;
}
void
nbtk_adjustment_set_elastic (NbtkAdjustment *adjustment,
gboolean elastic)
{
adjustment->priv->elastic = elastic;
}
gboolean
nbtk_adjustment_clamp (NbtkAdjustment *adjustment,
gboolean interpolate,
guint duration)
{
NbtkAdjustmentPrivate *priv = adjustment->priv;
gdouble dest = priv->value;
if (priv->value < priv->lower)
dest = priv->lower;
if (priv->value > priv->upper - priv->page_size)
dest = priv->upper - priv->page_size;
if (dest != priv->value)
{
if (interpolate)
nbtk_adjustment_interpolate (adjustment, dest, duration);
else
nbtk_adjustment_set_value (adjustment, dest);
return TRUE;
}
return FALSE;
}

121
src/nbtk/nbtk-adjustment.h Normal file
View File

@ -0,0 +1,121 @@
/*
* nbtk-adjustment.h: Adjustment object
*
* Copyright 2008 OpenedHand
* Copyright 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Chris Lord <chris@openedhand.com>, inspired by GtkAdjustment
* Port to Nbtk by: Robert Staudinger <robsta@openedhand.com>
*
*/
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
#error "Only <nbtk/nbtk.h> can be included directly.h"
#endif
#ifndef __NBTK_ADJUSTMENT_H__
#define __NBTK_ADJUSTMENT_H__
#include <glib-object.h>
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define NBTK_TYPE_ADJUSTMENT (nbtk_adjustment_get_type())
#define NBTK_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustment))
#define NBTK_IS_ADJUSTMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ADJUSTMENT))
#define NBTK_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass))
#define NBTK_IS_ADJUSTMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ADJUSTMENT))
#define NBTK_ADJUSTMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ADJUSTMENT, NbtkAdjustmentClass))
typedef struct _NbtkAdjustment NbtkAdjustment;
typedef struct _NbtkAdjustmentPrivate NbtkAdjustmentPrivate;
typedef struct _NbtkAdjustmentClass NbtkAdjustmentClass;
/**
* NbtkAdjustment:
*
* Class for handling an interval between to values. The contents of
* the #NbtkAdjustment are private and should be accessed using the
* public API.
*/
struct _NbtkAdjustment
{
/*< private >*/
GObject parent_instance;
NbtkAdjustmentPrivate *priv;
};
/**
* NbtkAdjustmentClass
* @changed: Class handler for the ::changed signal.
*
* Base class for #NbtkAdjustment.
*/
struct _NbtkAdjustmentClass
{
/*< private >*/
GObjectClass parent_class;
/*< public >*/
void (* changed) (NbtkAdjustment *adjustment);
};
GType nbtk_adjustment_get_type (void) G_GNUC_CONST;
NbtkAdjustment *nbtk_adjustment_new (gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
gdouble page_increment,
gdouble page_size);
gdouble nbtk_adjustment_get_value (NbtkAdjustment *adjustment);
void nbtk_adjustment_set_value (NbtkAdjustment *adjustment,
gdouble value);
void nbtk_adjustment_clamp_page (NbtkAdjustment *adjustment,
gdouble lower,
gdouble upper);
void nbtk_adjustment_set_values (NbtkAdjustment *adjustment,
gdouble value,
gdouble lower,
gdouble upper,
gdouble step_increment,
gdouble page_increment,
gdouble page_size);
void nbtk_adjustment_get_values (NbtkAdjustment *adjustment,
gdouble *value,
gdouble *lower,
gdouble *upper,
gdouble *step_increment,
gdouble *page_increment,
gdouble *page_size);
void nbtk_adjustment_interpolate (NbtkAdjustment *adjustment,
gdouble value,
guint duration);
gboolean nbtk_adjustment_get_elastic (NbtkAdjustment *adjustment);
void nbtk_adjustment_set_elastic (NbtkAdjustment *adjustment,
gboolean elastic);
gboolean nbtk_adjustment_clamp (NbtkAdjustment *adjustment,
gboolean interpolate,
guint duration);
G_END_DECLS
#endif /* __NBTK_ADJUSTMENT_H__ */

739
src/nbtk/nbtk-bin.c Normal file
View File

@ -0,0 +1,739 @@
/*
* nbtk-bin.c: Basic container actor
*
* Copyright (c) 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
*
*/
/**
* SECTION:nbtk-bin
* @short_description: a simple container with one actor
*
* #NbtkBin is a simple container capable of having only one
* #ClutterActor as a child.
*
* #NbtkBin inherits from #NbtkWidget, so it is fully themable.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <clutter/clutter.h>
#include "nbtk-bin.h"
#include "nbtk-enum-types.h"
#include "nbtk-private.h"
#define NBTK_BIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BIN, NbtkBinPrivate))
struct _NbtkBinPrivate
{
ClutterActor *child;
NbtkAlignment x_align;
NbtkAlignment y_align;
guint x_fill : 1;
guint y_fill : 1;
};
enum
{
PROP_0,
PROP_CHILD,
PROP_X_ALIGN,
PROP_Y_ALIGN,
PROP_X_FILL,
PROP_Y_FILL
};
static void clutter_container_iface_init (ClutterContainerIface *iface);
G_DEFINE_TYPE_WITH_CODE (NbtkBin, nbtk_bin, NBTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
clutter_container_iface_init));
void
_nbtk_bin_get_align_factors (NbtkBin *bin,
gdouble *x_align,
gdouble *y_align)
{
NbtkBinPrivate *priv = bin->priv;
gdouble factor;
switch (priv->x_align)
{
case NBTK_ALIGN_LEFT:
factor = 0.0;
break;
case NBTK_ALIGN_CENTER:
factor = 0.5;
break;
case NBTK_ALIGN_RIGHT:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (x_align)
*x_align = factor;
switch (priv->y_align)
{
case NBTK_ALIGN_TOP:
factor = 0.0;
break;
case NBTK_ALIGN_CENTER:
factor = 0.5;
break;
case NBTK_ALIGN_BOTTOM:
factor = 1.0;
break;
default:
factor = 0.0;
break;
}
if (y_align)
*y_align = factor;
}
static void
nbtk_bin_add (ClutterContainer *container,
ClutterActor *actor)
{
nbtk_bin_set_child (NBTK_BIN (container), actor);
}
static void
nbtk_bin_remove (ClutterContainer *container,
ClutterActor *actor)
{
NbtkBinPrivate *priv = NBTK_BIN (container)->priv;
if (priv->child == actor)
nbtk_bin_set_child (NBTK_BIN (container), NULL);
}
static void
nbtk_bin_foreach (ClutterContainer *container,
ClutterCallback callback,
gpointer user_data)
{
NbtkBinPrivate *priv = NBTK_BIN (container)->priv;
if (priv->child)
callback (priv->child, user_data);
}
static void
clutter_container_iface_init (ClutterContainerIface *iface)
{
iface->add = nbtk_bin_add;
iface->remove = nbtk_bin_remove;
iface->foreach = nbtk_bin_foreach;
}
static void
nbtk_bin_paint (ClutterActor *self)
{
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
/* allow NbtkWidget to paint the background */
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->paint (self);
/* the pain our child */
if (priv->child)
clutter_actor_paint (priv->child);
}
static void
nbtk_bin_pick (ClutterActor *self,
const ClutterColor *pick_color)
{
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
/* get the default pick implementation */
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->pick (self, pick_color);
if (priv->child)
clutter_actor_paint (priv->child);
}
static void
nbtk_bin_allocate (ClutterActor *self,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
CLUTTER_ACTOR_CLASS (nbtk_bin_parent_class)->allocate (self, box,
flags);
if (priv->child)
{
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
gfloat natural_width, natural_height;
gfloat min_width, min_height;
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox content_box;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align;
shell_theme_node_get_content_box (theme_node, box, &content_box);
_nbtk_bin_get_align_factors (NBTK_BIN (self), &x_align, &y_align);
available_width = content_box.x2 - content_box.x1;
available_height = content_box.y2 - content_box.y1;
if (available_width < 0)
available_width = 0;
if (available_height < 0)
available_height = 0;
if (priv->x_fill)
{
allocation.x1 = (int) content_box.x1;
allocation.x2 = (int) content_box.x2;
}
if (priv->y_fill)
{
allocation.y1 = (int) content_box.y1;
allocation.y2 = (int) content_box.y2;
}
/* if we are filling horizontally and vertically then we're done */
if (priv->x_fill && priv->y_fill)
{
clutter_actor_allocate (priv->child, &allocation, flags);
return;
}
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (priv->child), "request-mode", &request, NULL);
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (priv->child, available_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
clutter_actor_get_preferred_height (priv->child, child_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
}
else
{
clutter_actor_get_preferred_height (priv->child, available_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
clutter_actor_get_preferred_width (priv->child, child_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
}
if (!priv->x_fill)
{
allocation.x1 = content_box.x1 + (int) ((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + child_width;
}
if (!priv->y_fill)
{
allocation.y1 = content_box.y1 + (int) ((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + child_height;
}
clutter_actor_allocate (priv->child, &allocation, flags);
}
}
static void
nbtk_bin_get_preferred_width (ClutterActor *self,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
shell_theme_node_adjust_for_height (theme_node, &for_height);
if (priv->child == NULL)
{
if (min_width_p)
*min_width_p = 0;
if (natural_width_p)
*natural_width_p = 0;
}
else
{
clutter_actor_get_preferred_width (priv->child, for_height,
min_width_p,
natural_width_p);
}
shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
}
static void
nbtk_bin_get_preferred_height (ClutterActor *self,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
NbtkBinPrivate *priv = NBTK_BIN (self)->priv;
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (self));
shell_theme_node_adjust_for_width (theme_node, &for_width);
if (priv->child == NULL)
{
if (min_height_p)
*min_height_p = 0;
if (natural_height_p)
*natural_height_p = 0;
}
else
{
clutter_actor_get_preferred_height (priv->child, for_width,
min_height_p,
natural_height_p);
}
shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
}
static void
nbtk_bin_dispose (GObject *gobject)
{
NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv;
if (priv->child)
{
clutter_actor_unparent (priv->child);
priv->child = NULL;
}
G_OBJECT_CLASS (nbtk_bin_parent_class)->dispose (gobject);
}
static void
nbtk_bin_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NbtkBin *bin = NBTK_BIN (gobject);
switch (prop_id)
{
case PROP_CHILD:
nbtk_bin_set_child (bin, g_value_get_object (value));
break;
case PROP_X_ALIGN:
nbtk_bin_set_alignment (bin,
g_value_get_enum (value),
bin->priv->y_align);
break;
case PROP_Y_ALIGN:
nbtk_bin_set_alignment (bin,
bin->priv->x_align,
g_value_get_enum (value));
break;
case PROP_X_FILL:
nbtk_bin_set_fill (bin,
g_value_get_boolean (value),
bin->priv->y_fill);
break;
case PROP_Y_FILL:
nbtk_bin_set_fill (bin,
bin->priv->y_fill,
g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
nbtk_bin_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NbtkBinPrivate *priv = NBTK_BIN (gobject)->priv;
switch (prop_id)
{
case PROP_CHILD:
g_value_set_object (value, priv->child);
break;
case PROP_X_FILL:
g_value_set_boolean (value, priv->x_fill);
break;
case PROP_Y_FILL:
g_value_set_boolean (value, priv->y_fill);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
}
}
static void
nbtk_bin_class_init (NbtkBinClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (klass, sizeof (NbtkBinPrivate));
gobject_class->set_property = nbtk_bin_set_property;
gobject_class->get_property = nbtk_bin_get_property;
gobject_class->dispose = nbtk_bin_dispose;
actor_class->get_preferred_width = nbtk_bin_get_preferred_width;
actor_class->get_preferred_height = nbtk_bin_get_preferred_height;
actor_class->allocate = nbtk_bin_allocate;
actor_class->paint = nbtk_bin_paint;
actor_class->pick = nbtk_bin_pick;
/**
* NbtkBin:child:
*
* The child #ClutterActor of the #NbtkBin container.
*/
pspec = g_param_spec_object ("child",
"Child",
"The child of the Bin",
CLUTTER_TYPE_ACTOR,
NBTK_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_CHILD, pspec);
/**
* NbtkBin:x-align:
*
* The horizontal alignment of the #NbtkBin child.
*/
pspec = g_param_spec_enum ("x-align",
"X Align",
"The horizontal alignment",
NBTK_TYPE_ALIGNMENT,
NBTK_ALIGN_CENTER,
NBTK_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec);
/**
* NbtkBin:y-align:
*
* The vertical alignment of the #NbtkBin child.
*/
pspec = g_param_spec_enum ("y-align",
"Y Align",
"The vertical alignment",
NBTK_TYPE_ALIGNMENT,
NBTK_ALIGN_CENTER,
NBTK_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec);
/**
* NbtkBin:x-fill:
*
* Whether the child should fill the horizontal allocation
*/
pspec = g_param_spec_boolean ("x-fill",
"X Fill",
"Whether the child should fill the "
"horizontal allocation",
FALSE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_X_FILL, pspec);
/**
* NbtkBin:y-fill:
*
* Whether the child should fill the vertical allocation
*/
pspec = g_param_spec_boolean ("y-fill",
"Y Fill",
"Whether the child should fill the "
"vertical allocation",
FALSE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_Y_FILL, pspec);
}
static void
nbtk_bin_init (NbtkBin *bin)
{
bin->priv = NBTK_BIN_GET_PRIVATE (bin);
bin->priv->x_align = NBTK_ALIGN_CENTER;
bin->priv->y_align = NBTK_ALIGN_CENTER;
}
/**
* nbtk_bin_new:
*
* Creates a new #NbtkBin, a simple container for one child.
*
* Return value: the newly created #NbtkBin actor
*/
NbtkWidget *
nbtk_bin_new (void)
{
return g_object_new (NBTK_TYPE_BIN, NULL);
}
/**
* nbtk_bin_set_child:
* @bin: a #NbtkBin
* @child: a #ClutterActor, or %NULL
*
* Sets @child as the child of @bin.
*
* If @bin already has a child, the previous child is removed.
*/
void
nbtk_bin_set_child (NbtkBin *bin,
ClutterActor *child)
{
NbtkBinPrivate *priv;
g_return_if_fail (NBTK_IS_BIN (bin));
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
priv = bin->priv;
if (priv->child == child)
return;
if (priv->child)
{
ClutterActor *old_child = priv->child;
g_object_ref (old_child);
priv->child = NULL;
clutter_actor_unparent (old_child);
g_signal_emit_by_name (bin, "actor-removed", old_child);
g_object_unref (old_child);
}
if (child)
{
priv->child = child;
clutter_actor_set_parent (child, CLUTTER_ACTOR (bin));
g_signal_emit_by_name (bin, "actor-added", priv->child);
}
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
g_object_notify (G_OBJECT (bin), "child");
}
/**
* nbtk_bin_get_child:
* @bin: a #NbtkBin
*
* Retrieves a pointer to the child of @bin.
*
* Return value: (transfer none): a #ClutterActor, or %NULL
*/
ClutterActor *
nbtk_bin_get_child (NbtkBin *bin)
{
g_return_val_if_fail (NBTK_IS_BIN (bin), NULL);
return bin->priv->child;
}
/**
* nbtk_bin_set_alignment:
* @bin: a #NbtkBin
* @x_align: horizontal alignment
* @y_align: vertical alignment
*
* Sets the horizontal and vertical alignment of the child
* inside a #NbtkBin.
*/
void
nbtk_bin_set_alignment (NbtkBin *bin,
NbtkAlignment x_align,
NbtkAlignment y_align)
{
NbtkBinPrivate *priv;
gboolean changed = FALSE;
g_return_if_fail (NBTK_IS_BIN (bin));
priv = bin->priv;
g_object_freeze_notify (G_OBJECT (bin));
if (priv->x_align != x_align)
{
priv->x_align = x_align;
g_object_notify (G_OBJECT (bin), "x-align");
changed = TRUE;
}
if (priv->y_align != y_align)
{
priv->y_align = y_align;
g_object_notify (G_OBJECT (bin), "y-align");
changed = TRUE;
}
if (changed)
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
g_object_thaw_notify (G_OBJECT (bin));
}
/**
* nbtk_bin_get_alignment:
* @bin: a #NbtkBin
* @x_align: return location for the horizontal alignment, or %NULL
* @y_align: return location for the vertical alignment, or %NULL
*
* Retrieves the horizontal and vertical alignment of the child
* inside a #NbtkBin, as set by nbtk_bin_set_alignment().
*/
void
nbtk_bin_get_alignment (NbtkBin *bin,
NbtkAlignment *x_align,
NbtkAlignment *y_align)
{
NbtkBinPrivate *priv;
g_return_if_fail (NBTK_IS_BIN (bin));
priv = bin->priv;
if (x_align)
*x_align = priv->x_align;
if (y_align)
*y_align = priv->y_align;
}
/**
* nbtk_bin_set_fill:
* @bin: a #NbtkBin
* @x_fill: %TRUE if the child should fill horizontally the @bin
* @y_fill: %TRUE if the child should fill vertically the @bin
*
* Sets whether the child of @bin should fill out the horizontal
* and/or vertical allocation of the parent
*/
void
nbtk_bin_set_fill (NbtkBin *bin,
gboolean x_fill,
gboolean y_fill)
{
NbtkBinPrivate *priv;
gboolean changed = FALSE;
g_return_if_fail (NBTK_IS_BIN (bin));
priv = bin->priv;
g_object_freeze_notify (G_OBJECT (bin));
if (priv->x_fill != x_fill)
{
priv->x_fill = x_fill;
changed = TRUE;
g_object_notify (G_OBJECT (bin), "x-fill");
}
if (priv->y_fill != y_fill)
{
priv->y_fill = y_fill;
changed = TRUE;
g_object_notify (G_OBJECT (bin), "y-fill");
}
if (changed)
clutter_actor_queue_relayout (CLUTTER_ACTOR (bin));
g_object_thaw_notify (G_OBJECT (bin));
}
/**
* nbtk_bin_get_fill:
* @bin: a #NbtkBin
* @x_fill: (out): return location for the horizontal fill, or %NULL
* @y_fill: (out): return location for the vertical fill, or %NULL
*
* Retrieves the horizontal and vertical fill settings
*/
void
nbtk_bin_get_fill (NbtkBin *bin,
gboolean *x_fill,
gboolean *y_fill)
{
g_return_if_fail (NBTK_IS_BIN (bin));
if (x_fill)
*x_fill = bin->priv->x_fill;
if (y_fill)
*y_fill = bin->priv->y_fill;
}

92
src/nbtk/nbtk-bin.h Normal file
View File

@ -0,0 +1,92 @@
/*
* nbtk-bin.h: Basic container actor
*
* Copyright 2009, 2008 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* Boston, MA 02111-1307, USA.
*
* Written by: Emmanuele Bassi <ebassi@linux.intel.com>
*
*/
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
#error "Only <nbtk/nbtk.h> can be included directly.h"
#endif
#ifndef __NBTK_BIN_H__
#define __NBTK_BIN_H__
#include <nbtk/nbtk-types.h>
#include <nbtk/nbtk-widget.h>
G_BEGIN_DECLS
#define NBTK_TYPE_BIN (nbtk_bin_get_type ())
#define NBTK_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BIN, NbtkBin))
#define NBTK_IS_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BIN))
#define NBTK_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BIN, NbtkBinClass))
#define NBTK_IS_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BIN))
#define NBTK_BIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BIN, NbtkBinClass))
typedef struct _NbtkBin NbtkBin;
typedef struct _NbtkBinPrivate NbtkBinPrivate;
typedef struct _NbtkBinClass NbtkBinClass;
/**
* NbtkBin:
*
* The #NbtkBin struct contains only private data
*/
struct _NbtkBin
{
/*< private >*/
NbtkWidget parent_instance;
NbtkBinPrivate *priv;
};
/**
* NbtkBinClass:
*
* The #NbtkBinClass struct contains only private data
*/
struct _NbtkBinClass
{
/*< private >*/
NbtkWidgetClass parent_class;
};
GType nbtk_bin_get_type (void) G_GNUC_CONST;
NbtkWidget *nbtk_bin_new (void);
void nbtk_bin_set_child (NbtkBin *bin,
ClutterActor *child);
ClutterActor *nbtk_bin_get_child (NbtkBin *bin);
void nbtk_bin_set_alignment (NbtkBin *bin,
NbtkAlignment x_align,
NbtkAlignment y_align);
void nbtk_bin_get_alignment (NbtkBin *bin,
NbtkAlignment *x_align,
NbtkAlignment *y_align);
void nbtk_bin_set_fill (NbtkBin *bin,
gboolean x_fill,
gboolean y_fill);
void nbtk_bin_get_fill (NbtkBin *bin,
gboolean *x_fill,
gboolean *y_fill);
G_END_DECLS
#endif /* __NBTK_BIN_H__ */

View File

@ -0,0 +1,176 @@
/*
* nbtk-box-layout-child.c: box layout child actor
*
* Copyright 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Thomas Wood <thomas.wood@intel.com>
*/
#include "nbtk-box-layout-child.h"
#include "nbtk-private.h"
G_DEFINE_TYPE (NbtkBoxLayoutChild, nbtk_box_layout_child, CLUTTER_TYPE_CHILD_META)
#define BOX_LAYOUT_CHILD_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildPrivate))
enum
{
PROP_0,
PROP_EXPAND,
PROP_X_FILL,
PROP_Y_FILL,
PROP_X_ALIGN,
PROP_Y_ALIGN
};
static void
nbtk_box_layout_child_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object);
switch (property_id)
{
case PROP_EXPAND:
g_value_set_boolean (value, child->expand);
break;
case PROP_X_FILL:
g_value_set_boolean (value, child->x_fill);
break;
case PROP_Y_FILL:
g_value_set_boolean (value, child->y_fill);
break;
case PROP_X_ALIGN:
g_value_set_enum (value, child->x_align);
break;
case PROP_Y_ALIGN:
g_value_set_enum (value, child->y_align);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
nbtk_box_layout_child_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
NbtkBoxLayoutChild *child = NBTK_BOX_LAYOUT_CHILD (object);
NbtkBoxLayout *box = NBTK_BOX_LAYOUT (CLUTTER_CHILD_META (object)->container);
switch (property_id)
{
case PROP_EXPAND:
child->expand = g_value_get_boolean (value);
break;
case PROP_X_FILL:
child->x_fill = g_value_get_boolean (value);
break;
case PROP_Y_FILL:
child->y_fill = g_value_get_boolean (value);
break;
case PROP_X_ALIGN:
child->x_align = g_value_get_enum (value);
break;
case PROP_Y_ALIGN:
child->y_align = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
clutter_actor_queue_relayout ((ClutterActor*) box);
}
static void
nbtk_box_layout_child_dispose (GObject *object)
{
G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->dispose (object);
}
static void
nbtk_box_layout_child_finalize (GObject *object)
{
G_OBJECT_CLASS (nbtk_box_layout_child_parent_class)->finalize (object);
}
static void
nbtk_box_layout_child_class_init (NbtkBoxLayoutChildClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GParamSpec *pspec;
object_class->get_property = nbtk_box_layout_child_get_property;
object_class->set_property = nbtk_box_layout_child_set_property;
object_class->dispose = nbtk_box_layout_child_dispose;
object_class->finalize = nbtk_box_layout_child_finalize;
pspec = g_param_spec_boolean ("expand", "Expand",
"Allocate the child extra space",
FALSE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_EXPAND, pspec);
pspec = g_param_spec_boolean ("x-fill", "x-fill",
"Whether the child should receive priority "
"when the container is allocating spare space "
"on the horizontal axis",
TRUE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_X_FILL, pspec);
pspec = g_param_spec_boolean ("y-fill", "y-fill",
"Whether the child should receive priority "
"when the container is allocating spare space "
"on the vertical axis",
TRUE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_Y_FILL, pspec);
pspec = g_param_spec_enum ("x-align",
"X Alignment",
"X alignment of the widget within the cell",
NBTK_TYPE_ALIGN,
NBTK_ALIGN_MIDDLE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_X_ALIGN, pspec);
pspec = g_param_spec_enum ("y-align",
"Y Alignment",
"Y alignment of the widget within the cell",
NBTK_TYPE_ALIGN,
NBTK_ALIGN_MIDDLE,
NBTK_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_Y_ALIGN, pspec);
}
static void
nbtk_box_layout_child_init (NbtkBoxLayoutChild *self)
{
self->expand = FALSE;
self->x_fill = TRUE;
self->y_fill = TRUE;
self->x_align = NBTK_ALIGN_CENTER;
self->y_align = NBTK_ALIGN_CENTER;
}

View File

@ -0,0 +1,84 @@
/*
* nbtk-box-layout-child.h: box layout child actor
*
* Copyright 2009 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Thomas Wood <thomas.wood@intel.com>
*/
#ifndef _NBTK_BOX_LAYOUT_CHILD_H
#define _NBTK_BOX_LAYOUT_CHILD_H
#include <clutter/clutter.h>
#include "nbtk-enum-types.h"
#include "nbtk-box-layout.h"
G_BEGIN_DECLS
#define NBTK_TYPE_BOX_LAYOUT_CHILD nbtk_box_layout_child_get_type()
#define NBTK_BOX_LAYOUT_CHILD(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChild))
#define NBTK_BOX_LAYOUT_CHILD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass))
#define NBTK_IS_BOX_LAYOUT_CHILD(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
NBTK_TYPE_BOX_LAYOUT_CHILD))
#define NBTK_IS_BOX_LAYOUT_CHILD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
NBTK_TYPE_BOX_LAYOUT_CHILD))
#define NBTK_BOX_LAYOUT_CHILD_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
NBTK_TYPE_BOX_LAYOUT_CHILD, NbtkBoxLayoutChildClass))
typedef struct _NbtkBoxLayoutChild NbtkBoxLayoutChild;
typedef struct _NbtkBoxLayoutChildClass NbtkBoxLayoutChildClass;
typedef struct _NbtkBoxLayoutChildPrivate NbtkBoxLayoutChildPrivate;
/**
* NbtkBoxLayoutChild:
*
* The contents of this structure are private and should only be accessed
* through the public API.
*/
struct _NbtkBoxLayoutChild
{
/*< private >*/
ClutterChildMeta parent;
gboolean expand;
gboolean x_fill : 1;
gboolean y_fill : 1;
NbtkAlign x_align;
NbtkAlign y_align;
};
struct _NbtkBoxLayoutChildClass
{
ClutterChildMetaClass parent_class;
};
GType nbtk_box_layout_child_get_type (void);
G_END_DECLS
#endif /* _NBTK_BOX_LAYOUT_CHILD_H */

1252
src/nbtk/nbtk-box-layout.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
/*
* nbtk-box-layout.h: box layout actor
*
* Copyright 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Thomas Wood <thomas.wood@intel.com>
*
*/
#ifndef _NBTK_BOX_LAYOUT_H
#define _NBTK_BOX_LAYOUT_H
#include <nbtk/nbtk-widget.h>
G_BEGIN_DECLS
#define NBTK_TYPE_BOX_LAYOUT nbtk_box_layout_get_type()
#define NBTK_BOX_LAYOUT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayout))
#define NBTK_BOX_LAYOUT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass))
#define NBTK_IS_BOX_LAYOUT(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
NBTK_TYPE_BOX_LAYOUT))
#define NBTK_IS_BOX_LAYOUT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
NBTK_TYPE_BOX_LAYOUT))
#define NBTK_BOX_LAYOUT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
NBTK_TYPE_BOX_LAYOUT, NbtkBoxLayoutClass))
typedef struct _NbtkBoxLayout NbtkBoxLayout;
typedef struct _NbtkBoxLayoutClass NbtkBoxLayoutClass;
typedef struct _NbtkBoxLayoutPrivate NbtkBoxLayoutPrivate;
/**
* NbtkBoxLayout:
*
* The contents of this structure are private and should only be accessed
* through the public API.
*/
struct _NbtkBoxLayout
{
/*< private >*/
NbtkWidget parent;
NbtkBoxLayoutPrivate *priv;
};
struct _NbtkBoxLayoutClass
{
NbtkWidgetClass parent_class;
};
GType nbtk_box_layout_get_type (void);
NbtkWidget *nbtk_box_layout_new (void);
void nbtk_box_layout_set_vertical (NbtkBoxLayout *box, gboolean vertical);
gboolean nbtk_box_layout_get_vertical (NbtkBoxLayout *box);
void nbtk_box_layout_set_pack_start (NbtkBoxLayout *box, gboolean pack_start);
gboolean nbtk_box_layout_get_pack_start (NbtkBoxLayout *box);
void nbtk_box_layout_set_spacing (NbtkBoxLayout *box, guint spacing);
guint nbtk_box_layout_get_spacing (NbtkBoxLayout *box);
G_END_DECLS
#endif /* _NBTK_BOX_LAYOUT_H */

690
src/nbtk/nbtk-button.c Normal file
View File

@ -0,0 +1,690 @@
/*-button.c: Plain button actor
* Copyright 2007 OpenedHand
* Copyright , 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
* Thomas Wood <thomas@linux.intel.com>
*
*/
/**
* SECTION:nbtk-button
* @short_description: Button widget
*
* A button widget with support for either a text label or icon, toggle mode
* and transitions effects between states.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <clutter/clutter.h>
#include "nbtk-button.h"
#include "nbtk-marshal.h"
#include "nbtk-texture-frame.h"
#include "nbtk-texture-cache.h"
#include "nbtk-private.h"
enum
{
PROP_0,
PROP_LABEL,
PROP_TOGGLE,
PROP_ACTIVE,
PROP_TRANSITION
};
enum
{
CLICKED,
LAST_SIGNAL
};
#define NBTK_BUTTON_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_BUTTON, NbtkButtonPrivate))
struct _NbtkButtonPrivate
{
gchar *text;
ClutterActor *old_bg;
gboolean old_bg_parented; /* TRUE if we have adopted old_bg */
guint8 old_opacity;
guint is_pressed : 1;
guint is_hover : 1;
guint is_checked : 1;
guint is_toggle : 1;
gint transition_duration;
ClutterAnimation *animation;
gint spacing;
};
static guint button_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (NbtkButton, nbtk_button, NBTK_TYPE_BIN);
static void
nbtk_button_update_label_style (NbtkButton *button)
{
ClutterActor *label;
ShellThemeNode *theme_node;
ClutterColor color;
const PangoFontDescription *font;
gchar *font_string = NULL;
label = nbtk_bin_get_child ((NbtkBin*) button);
/* check the child is really a label */
if (!CLUTTER_IS_TEXT (label))
return;
theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
shell_theme_node_get_foreground_color (theme_node, &color);
clutter_text_set_color (CLUTTER_TEXT (label), &color);
font = shell_theme_node_get_font (theme_node);
font_string = pango_font_description_to_string (font);
clutter_text_set_font_name (CLUTTER_TEXT (label), font_string);
g_free (font_string);
}
static void
nbtk_button_dispose_old_bg (NbtkButton *button)
{
NbtkButtonPrivate *priv = button->priv;
if (priv->old_bg)
{
if (priv->old_bg_parented)
{
clutter_actor_unparent (priv->old_bg);
priv->old_bg_parented = FALSE;
}
g_object_unref (priv->old_bg);
priv->old_bg = NULL;
}
}
static void
nbtk_animation_completed (ClutterAnimation *animation,
NbtkButton *button)
{
nbtk_button_dispose_old_bg (button);
}
static void
nbtk_button_style_changed (NbtkWidget *widget)
{
NbtkButton *button = NBTK_BUTTON (widget);
NbtkButtonPrivate *priv = button->priv;
NbtkButtonClass *button_class = NBTK_BUTTON_GET_CLASS (button);
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (button));
ClutterActor *bg_image;
double spacing;
nbtk_button_dispose_old_bg (button);
bg_image = nbtk_widget_get_border_image ((NbtkWidget*) button);
if (bg_image)
button->priv->old_bg = g_object_ref (bg_image);
NBTK_WIDGET_CLASS (nbtk_button_parent_class)->style_changed (widget);
spacing = 6;
shell_theme_node_get_length (theme_node, "border-spacing", FALSE, &spacing);
priv->spacing = round (spacing);
/* update the label styling */
nbtk_button_update_label_style (button);
/* run a transition if applicable */
if (button_class->transition)
{
button_class->transition (button, priv->old_bg);
}
else
{
if (priv->old_bg &&
(!nbtk_widget_get_style_pseudo_class (widget)))
{
ClutterAnimation *animation;
if (!clutter_actor_get_parent (priv->old_bg))
{
clutter_actor_set_parent (priv->old_bg, (ClutterActor*) widget);
priv->old_bg_parented = TRUE;
}
if (priv->transition_duration > 0)
{
animation = clutter_actor_animate (priv->old_bg,
CLUTTER_LINEAR,
priv->transition_duration,
"opacity", 0,
NULL);
g_signal_connect (animation, "completed",
G_CALLBACK (nbtk_animation_completed), button);
}
else
{
nbtk_button_dispose_old_bg (button);
}
}
}
}
static void
nbtk_button_real_pressed (NbtkButton *button)
{
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "active");
}
static void
nbtk_button_real_released (NbtkButton *button)
{
NbtkButtonPrivate *priv = button->priv;
if (priv->is_checked)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
else if (!priv->is_hover)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
else
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
}
static gboolean
nbtk_button_button_press (ClutterActor *actor,
ClutterButtonEvent *event)
{
nbtk_widget_hide_tooltip (NBTK_WIDGET (actor));
if (event->button == 1)
{
NbtkButton *button = NBTK_BUTTON (actor);
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
button->priv->is_pressed = TRUE;
clutter_grab_pointer (actor);
if (klass->pressed)
klass->pressed (button);
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_button_button_release (ClutterActor *actor,
ClutterButtonEvent *event)
{
if (event->button == 1)
{
NbtkButton *button = NBTK_BUTTON (actor);
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
if (!button->priv->is_pressed)
return FALSE;
clutter_ungrab_pointer ();
if (button->priv->is_toggle)
{
nbtk_button_set_checked (button, !button->priv->is_checked);
}
button->priv->is_pressed = FALSE;
if (klass->released)
klass->released (button);
g_signal_emit (button, button_signals[CLICKED], 0);
return TRUE;
}
return FALSE;
}
static gboolean
nbtk_button_enter (ClutterActor *actor,
ClutterCrossingEvent *event)
{
NbtkButton *button = NBTK_BUTTON (actor);
if (!button->priv->is_checked)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
button->priv->is_hover = 1;
return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->enter_event (actor, event);
}
static gboolean
nbtk_button_leave (ClutterActor *actor,
ClutterCrossingEvent *event)
{
NbtkButton *button = NBTK_BUTTON (actor);
button->priv->is_hover = 0;
if (button->priv->is_pressed)
{
NbtkButtonClass *klass = NBTK_BUTTON_GET_CLASS (button);
clutter_ungrab_pointer ();
button->priv->is_pressed = FALSE;
if (klass->released)
klass->released (button);
}
if (button->priv->is_checked)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
else
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
return CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->leave_event (actor, event);
}
static void
nbtk_button_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NbtkButton *button = NBTK_BUTTON (gobject);
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
switch (prop_id)
{
case PROP_LABEL:
nbtk_button_set_label (button, g_value_get_string (value));
break;
case PROP_TOGGLE:
nbtk_button_set_toggle_mode (button, g_value_get_boolean (value));
break;
case PROP_ACTIVE:
nbtk_button_set_checked (button, g_value_get_boolean (value));
break;
case PROP_TRANSITION:
priv->transition_duration = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_button_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
switch (prop_id)
{
case PROP_LABEL:
g_value_set_string (value, priv->text);
break;
case PROP_TOGGLE:
g_value_set_boolean (value, priv->is_toggle);
break;
case PROP_ACTIVE:
g_value_set_boolean (value, priv->is_checked);
break;
case PROP_TRANSITION:
g_value_set_int (value, priv->transition_duration);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_button_finalize (GObject *gobject)
{
NbtkButtonPrivate *priv = NBTK_BUTTON (gobject)->priv;
g_free (priv->text);
G_OBJECT_CLASS (nbtk_button_parent_class)->finalize (gobject);
}
static void
nbtk_button_dispose (GObject *gobject)
{
nbtk_button_dispose_old_bg (NBTK_BUTTON (gobject));
G_OBJECT_CLASS (nbtk_button_parent_class)->dispose (gobject);
}
static void
nbtk_button_map (ClutterActor *self)
{
NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv;
CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->map (self);
if (priv->old_bg && priv->old_bg_parented)
clutter_actor_map (priv->old_bg);
}
static void
nbtk_button_unmap (ClutterActor *self)
{
NbtkButtonPrivate *priv = NBTK_BUTTON (self)->priv;
CLUTTER_ACTOR_CLASS (nbtk_button_parent_class)->unmap (self);
if (priv->old_bg && priv->old_bg_parented)
clutter_actor_unmap (priv->old_bg);
}
static void
nbtk_button_draw_background (NbtkWidget *widget)
{
NbtkButtonPrivate *priv;
NBTK_WIDGET_CLASS (nbtk_button_parent_class)->draw_background (widget);
priv = NBTK_BUTTON (widget)->priv;
if (priv->old_bg && priv->old_bg_parented)
clutter_actor_paint (priv->old_bg);
}
static void
nbtk_button_class_init (NbtkButtonClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
NbtkWidgetClass *widget_class = NBTK_WIDGET_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (klass, sizeof (NbtkButtonPrivate));
klass->pressed = nbtk_button_real_pressed;
klass->released = nbtk_button_real_released;
gobject_class->set_property = nbtk_button_set_property;
gobject_class->get_property = nbtk_button_get_property;
gobject_class->dispose = nbtk_button_dispose;
gobject_class->finalize = nbtk_button_finalize;
actor_class->button_press_event = nbtk_button_button_press;
actor_class->button_release_event = nbtk_button_button_release;
actor_class->enter_event = nbtk_button_enter;
actor_class->leave_event = nbtk_button_leave;
actor_class->map = nbtk_button_map;
actor_class->unmap = nbtk_button_unmap;
widget_class->draw_background = nbtk_button_draw_background;
widget_class->style_changed = nbtk_button_style_changed;
pspec = g_param_spec_string ("label",
"Label",
"Label of the button",
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
pspec = g_param_spec_boolean ("toggle-mode",
"Toggle Mode",
"Enable or disable toggling",
FALSE, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TOGGLE, pspec);
pspec = g_param_spec_boolean ("checked",
"Checked",
"Indicates if a toggle button is \"on\""
" or \"off\"",
FALSE, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_ACTIVE, pspec);
pspec = g_param_spec_int ("transition-duration",
"Transition Duration",
"Duration of the state transition effect",
0, G_MAXINT, 120, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TRANSITION, pspec);
/**
* NbtkButton::clicked:
* @button: the object that received the signal
*
* Emitted when the user activates the button, either with a mouse press and
* release or with the keyboard.
*/
button_signals[CLICKED] =
g_signal_new ("clicked",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NbtkButtonClass, clicked),
NULL, NULL,
_nbtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
nbtk_button_init (NbtkButton *button)
{
button->priv = NBTK_BUTTON_GET_PRIVATE (button);
button->priv->transition_duration = 120;
button->priv->spacing = 6;
clutter_actor_set_reactive ((ClutterActor *) button, TRUE);
}
/**
* nbtk_button_new:
*
* Create a new button
*
* Returns: a new #NbtkButton
*/
NbtkWidget *
nbtk_button_new (void)
{
return g_object_new (NBTK_TYPE_BUTTON, NULL);
}
/**
* nbtk_button_new_with_label:
* @text: text to set the label to
*
* Create a new #NbtkButton with the specified label
*
* Returns: a new #NbtkButton
*/
NbtkWidget *
nbtk_button_new_with_label (const gchar *text)
{
return g_object_new (NBTK_TYPE_BUTTON, "label", text, NULL);
}
/**
* nbtk_button_get_label:
* @button: a #NbtkButton
*
* Get the text displayed on the button
*
* Returns: the text for the button. This must not be freed by the application
*/
G_CONST_RETURN gchar *
nbtk_button_get_label (NbtkButton *button)
{
g_return_val_if_fail (NBTK_IS_BUTTON (button), NULL);
return button->priv->text;
}
/**
* nbtk_button_set_label:
* @button: a #Nbtkbutton
* @text: text to set the label to
*
* Sets the text displayed on the button
*/
void
nbtk_button_set_label (NbtkButton *button,
const gchar *text)
{
NbtkButtonPrivate *priv;
ClutterActor *label;
g_return_if_fail (NBTK_IS_BUTTON (button));
priv = button->priv;
g_free (priv->text);
if (text)
priv->text = g_strdup (text);
else
priv->text = g_strdup ("");
label = nbtk_bin_get_child ((NbtkBin*) button);
if (label && CLUTTER_IS_TEXT (label))
{
clutter_text_set_text (CLUTTER_TEXT (label), priv->text);
}
else
{
label = g_object_new (CLUTTER_TYPE_TEXT,
"text", priv->text,
"line-alignment", PANGO_ALIGN_CENTER,
"ellipsize", PANGO_ELLIPSIZE_END,
"use-markup", TRUE,
NULL);
nbtk_bin_set_child ((NbtkBin*) button, label);
}
/* Fake a style change so that we reset the style properties on the label */
nbtk_widget_style_changed (NBTK_WIDGET (button));
g_object_notify (G_OBJECT (button), "label");
}
/**
* nbtk_button_get_toggle_mode:
* @button: a #NbtkButton
*
* Get the toggle mode status of the button.
*
* Returns: #TRUE if toggle mode is set, otherwise #FALSE
*/
gboolean
nbtk_button_get_toggle_mode (NbtkButton *button)
{
g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE);
return button->priv->is_toggle;
}
/**
* nbtk_button_set_toggle_mode:
* @button: a #Nbtkbutton
* @toggle: #TRUE or #FALSE
*
* Enables or disables toggle mode for the button. In toggle mode, the active
* state will be "toggled" when the user clicks the button.
*/
void
nbtk_button_set_toggle_mode (NbtkButton *button,
gboolean toggle)
{
g_return_if_fail (NBTK_IS_BUTTON (button));
button->priv->is_toggle = toggle;
g_object_notify (G_OBJECT (button), "toggle-mode");
}
/**
* nbtk_button_get_checked:
* @button: a #NbtkButton
*
* Get the state of the button that is in toggle mode.
*
* Returns: #TRUE if the button is checked, or #FALSE if not
*/
gboolean
nbtk_button_get_checked (NbtkButton *button)
{
g_return_val_if_fail (NBTK_IS_BUTTON (button), FALSE);
return button->priv->is_checked;
}
/**
* nbtk_button_set_checked:
* @button: a #Nbtkbutton
* @checked: #TRUE or #FALSE
*
* Sets the pressed state of the button. This is only really useful if the
* button has #toggle-mode mode set to #TRUE.
*/
void
nbtk_button_set_checked (NbtkButton *button,
gboolean checked)
{
g_return_if_fail (NBTK_IS_BUTTON (button));
if (button->priv->is_checked != checked)
{
button->priv->is_checked = checked;
if (checked)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "checked");
else
if (button->priv->is_hover)
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, "hover");
else
nbtk_widget_set_style_pseudo_class ((NbtkWidget*) button, NULL);
}
g_object_notify (G_OBJECT (button), "checked");
}

90
src/nbtk/nbtk-button.h Normal file
View File

@ -0,0 +1,90 @@
/*
* nbtk-button.h: Plain button actor
*
* Copyright 2007 OpenedHand
* Copyright 2008, 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* Boston, MA 02111-1307, USA.
*
* Written by: Emmanuele Bassi <ebassi@openedhand.com>
* Thomas Wood <thomas@linux.intel.com>
*
*/
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
#error "Only <nbtk/nbtk.h> can be included directly.h"
#endif
#ifndef __NBTK_BUTTON_H__
#define __NBTK_BUTTON_H__
G_BEGIN_DECLS
#include <nbtk/nbtk-bin.h>
#define NBTK_TYPE_BUTTON (nbtk_button_get_type ())
#define NBTK_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_BUTTON, NbtkButton))
#define NBTK_IS_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_BUTTON))
#define NBTK_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_BUTTON, NbtkButtonClass))
#define NBTK_IS_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_BUTTON))
#define NBTK_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_BUTTON, NbtkButtonClass))
typedef struct _NbtkButton NbtkButton;
typedef struct _NbtkButtonPrivate NbtkButtonPrivate;
typedef struct _NbtkButtonClass NbtkButtonClass;
/**
* NbtkButton:
*
* The contents of this structure is private and should only be accessed using
* the provided API.
*/
struct _NbtkButton
{
/*< private >*/
NbtkBin parent_instance;
NbtkButtonPrivate *priv;
};
struct _NbtkButtonClass
{
NbtkBinClass parent_class;
/* vfuncs, not signals */
void (* pressed) (NbtkButton *button);
void (* released) (NbtkButton *button);
void (* transition) (NbtkButton *button, ClutterActor *old_bg);
/* signals */
void (* clicked) (NbtkButton *button);
};
GType nbtk_button_get_type (void) G_GNUC_CONST;
NbtkWidget * nbtk_button_new (void);
NbtkWidget * nbtk_button_new_with_label (const gchar *text);
G_CONST_RETURN gchar *nbtk_button_get_label (NbtkButton *button);
void nbtk_button_set_label (NbtkButton *button,
const gchar *text);
void nbtk_button_set_toggle_mode (NbtkButton *button, gboolean toggle);
gboolean nbtk_button_get_toggle_mode (NbtkButton *button);
void nbtk_button_set_checked (NbtkButton *button, gboolean checked);
gboolean nbtk_button_get_checked (NbtkButton *button);
G_END_DECLS
#endif /* __NBTK_BUTTON_H__ */

367
src/nbtk/nbtk-clipboard.c Normal file
View File

@ -0,0 +1,367 @@
/*
* nbtk-clipboard.c: clipboard object
*
* Copyright 2009 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU Lesser General Public License,
* version 2.1, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
* more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Written by: Thomas Wood <thomas.wood@intel.com>
*
*/
#include "nbtk-clipboard.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <clutter/x11/clutter-x11.h>
#include <string.h>
G_DEFINE_TYPE (NbtkClipboard, nbtk_clipboard, G_TYPE_OBJECT)
#define CLIPBOARD_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), NBTK_TYPE_CLIPBOARD, NbtkClipboardPrivate))
struct _NbtkClipboardPrivate
{
Window clipboard_window;
gchar *clipboard_text;
Atom *supported_targets;
gint n_targets;
};
typedef struct _EventFilterData EventFilterData;
struct _EventFilterData
{
NbtkClipboard *clipboard;
NbtkClipboardCallbackFunc callback;
gpointer user_data;
};
static Atom __atom_clip = None;
static Atom __utf8_string = None;
static Atom __atom_targets = None;
static void
nbtk_clipboard_get_property (GObject *object, guint property_id,
GValue *value, GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
nbtk_clipboard_set_property (GObject *object, guint property_id,
const GValue *value, GParamSpec *pspec)
{
switch (property_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
nbtk_clipboard_dispose (GObject *object)
{
G_OBJECT_CLASS (nbtk_clipboard_parent_class)->dispose (object);
}
static void
nbtk_clipboard_finalize (GObject *object)
{
NbtkClipboardPrivate *priv = ((NbtkClipboard *) object)->priv;
g_free (priv->clipboard_text);
priv->clipboard_text = NULL;
g_free (priv->supported_targets);
priv->supported_targets = NULL;
priv->n_targets = 0;
G_OBJECT_CLASS (nbtk_clipboard_parent_class)->finalize (object);
}
static ClutterX11FilterReturn
nbtk_clipboard_provider (XEvent *xev,
ClutterEvent *cev,
NbtkClipboard *clipboard)
{
XSelectionEvent notify_event;
XSelectionRequestEvent *req_event;
if (xev->type != SelectionRequest)
return CLUTTER_X11_FILTER_CONTINUE;
req_event = &xev->xselectionrequest;
clutter_x11_trap_x_errors ();
if (req_event->target == __atom_targets)
{
XChangeProperty (req_event->display,
req_event->requestor,
req_event->property,
XA_ATOM,
32,
PropModeReplace,
(guchar*) clipboard->priv->supported_targets,
clipboard->priv->n_targets);
}
else
{
XChangeProperty (req_event->display,
req_event->requestor,
req_event->property,
req_event->target,
8,
PropModeReplace,
(guchar*) clipboard->priv->clipboard_text,
strlen (clipboard->priv->clipboard_text));
}
notify_event.type = SelectionNotify;
notify_event.display = req_event->display;
notify_event.requestor = req_event->requestor;
notify_event.selection = req_event->selection;
notify_event.target = req_event->target;
notify_event.time = req_event->time;
if (req_event->property == None)
notify_event.property = req_event->target;
else
notify_event.property = req_event->property;
/* notify the requestor that they have a copy of the selection */
XSendEvent (req_event->display, req_event->requestor, False, 0,
(XEvent *) &notify_event);
/* Make it happen non async */
XSync (clutter_x11_get_default_display(), FALSE);
clutter_x11_untrap_x_errors (); /* FIXME: Warn here on fail ? */
return CLUTTER_X11_FILTER_REMOVE;
}
static void
nbtk_clipboard_class_init (NbtkClipboardClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NbtkClipboardPrivate));
object_class->get_property = nbtk_clipboard_get_property;
object_class->set_property = nbtk_clipboard_set_property;
object_class->dispose = nbtk_clipboard_dispose;
object_class->finalize = nbtk_clipboard_finalize;
}
static void
nbtk_clipboard_init (NbtkClipboard *self)
{
Display *dpy;
NbtkClipboardPrivate *priv;
priv = self->priv = CLIPBOARD_PRIVATE (self);
priv->clipboard_window =
XCreateSimpleWindow (clutter_x11_get_default_display (),
clutter_x11_get_root_window (),
-1, -1, 1, 1, 0, 0, 0);
dpy = clutter_x11_get_default_display ();
/* Only create once */
if (__atom_clip == None)
__atom_clip = XInternAtom (dpy, "CLIPBOARD", 0);
if (__utf8_string == None)
__utf8_string = XInternAtom (dpy, "UTF8_STRING", 0);
if (__atom_targets == None)
__atom_targets = XInternAtom (dpy, "TARGETS", 0);
priv->n_targets = 2;
priv->supported_targets = g_new (Atom, priv->n_targets);
priv->supported_targets[0] = __utf8_string;
priv->supported_targets[1] = __atom_targets;
clutter_x11_add_filter ((ClutterX11FilterFunc) nbtk_clipboard_provider,
self);
}
static ClutterX11FilterReturn
nbtk_clipboard_x11_event_filter (XEvent *xev,
ClutterEvent *cev,
EventFilterData *filter_data)
{
Atom actual_type;
int actual_format, result;
unsigned long nitems, bytes_after;
unsigned char *data = NULL;
if(xev->type != SelectionNotify)
return CLUTTER_X11_FILTER_CONTINUE;
if (xev->xselection.property == None)
{
/* clipboard empty */
filter_data->callback (filter_data->clipboard,
NULL,
filter_data->user_data);
clutter_x11_remove_filter ((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
filter_data);
g_free (filter_data);
return CLUTTER_X11_FILTER_REMOVE;
}
clutter_x11_trap_x_errors ();
result = XGetWindowProperty (xev->xselection.display,
xev->xselection.requestor,
xev->xselection.property,
0L, G_MAXINT,
True,
AnyPropertyType,
&actual_type,
&actual_format,
&nitems,
&bytes_after,
&data);
if (clutter_x11_untrap_x_errors () || result != Success)
{
/* FIXME: handle failure better */
g_warning ("Clipboard: prop retrival failed");
}
filter_data->callback (filter_data->clipboard, (char*) data,
filter_data->user_data);
clutter_x11_remove_filter
((ClutterX11FilterFunc) nbtk_clipboard_x11_event_filter,
filter_data);
g_free (filter_data);
if (data)
XFree (data);
return CLUTTER_X11_FILTER_REMOVE;
}
/**
* nbtk_clipboard_get_default:
*
* Get the global #NbtkClipboard object that represents the clipboard.
*
* Returns: (transfer none): a #NbtkClipboard owned by Nbtk and must not be
* unrefferenced or freed.
*/
NbtkClipboard*
nbtk_clipboard_get_default (void)
{
static NbtkClipboard *default_clipboard = NULL;
if (!default_clipboard)
{
default_clipboard = g_object_new (NBTK_TYPE_CLIPBOARD, NULL);
}
return default_clipboard;
}
/**
* nbtk_clipboard_get_text:
* @clipboard: A #NbtkCliboard
* @callback: function to be called when the text is retreived
* @user_data: data to be passed to the callback
*
* Request the data from the clipboard in text form. @callback is executed
* when the data is retreived.
*
*/
void
nbtk_clipboard_get_text (NbtkClipboard *clipboard,
NbtkClipboardCallbackFunc callback,
gpointer user_data)
{
EventFilterData *data;
Display *dpy;
g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
g_return_if_fail (callback != NULL);
data = g_new0 (EventFilterData, 1);
data->clipboard = clipboard;
data->callback = callback;
data->user_data = user_data;
clutter_x11_add_filter ((ClutterX11FilterFunc)nbtk_clipboard_x11_event_filter,
data);
dpy = clutter_x11_get_default_display ();
clutter_x11_trap_x_errors (); /* safety on */
XConvertSelection (dpy,
__atom_clip,
__utf8_string, __utf8_string,
clipboard->priv->clipboard_window,
CurrentTime);
clutter_x11_untrap_x_errors ();
}
/**
* nbtk_clipboard_set_text:
* @clipboard: A #NbtkClipboard
* @text: text to copy to the clipboard
*
* Sets text as the current contents of the clipboard.
*
*/
void
nbtk_clipboard_set_text (NbtkClipboard *clipboard,
const gchar *text)
{
NbtkClipboardPrivate *priv;
Display *dpy;
g_return_if_fail (NBTK_IS_CLIPBOARD (clipboard));
g_return_if_fail (text != NULL);
priv = clipboard->priv;
/* make a copy of the text */
g_free (priv->clipboard_text);
priv->clipboard_text = g_strdup (text);
/* tell X we own the clipboard selection */
dpy = clutter_x11_get_default_display ();
clutter_x11_trap_x_errors ();
XSetSelectionOwner (dpy, __atom_clip, priv->clipboard_window, CurrentTime);
XSync (dpy, FALSE);
clutter_x11_untrap_x_errors ();
}

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