Compare commits

...

228 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
161 changed files with 26800 additions and 3569 deletions

11
.gitignore vendored
View File

@ -18,7 +18,15 @@ 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
@ -30,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,8 +1,8 @@
AC_INIT(gnome-shell, 2.27.0)
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])],)
@ -22,9 +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
@ -43,15 +50,18 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
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)
# 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)
# 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
@ -120,4 +130,6 @@ AC_OUTPUT([
js/misc/Makefile
js/ui/Makefile
src/Makefile
tests/Makefile
po/Makefile.in
])

View File

@ -12,15 +12,25 @@ gnome-shell.desktop.in: gnome-shell.desktop.in.in
gnome-shell.desktop: gnome-shell.desktop.in
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
imagedir = $(pkgdatadir)/images
imagesdir = $(pkgdatadir)/images
dist_images_DATA = \
add-workspace.svg \
app-well-glow.png \
back.svg \
close.svg \
close-black.svg \
info.svg \
magnifier.svg \
remove-workspace.svg
dist_image_DATA = \
add-workspace.svg \
close.svg \
info.svg \
remove-workspace.svg \
view-more-activated.svg \
view-more.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

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

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>
@ -35,7 +50,7 @@
<applyto>/desktop/gnome/shell/sidebar/visible</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<default>false</default>
<locale name="C">
<short>Whether or not to display the sidebar</short>
<long>

View File

@ -1,5 +1,6 @@
<?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#"
@ -8,22 +9,22 @@
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"
version="1.0"
id="Foreground"
x="0px"
y="0px"
width="29px"
height="18px"
viewBox="0 0 29 18"
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"
sodipodi:docname="search_1.svg"
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" /></cc:Work></rdf:RDF></metadata><defs
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"
@ -34,46 +35,46 @@
inkscape:window-height="728"
inkscape:window-width="1103"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pageopacity="1"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
pagecolor="#000000"
id="base"
showgrid="false"
inkscape:zoom="19.275862"
inkscape:cx="14.5"
inkscape:cy="9"
inkscape:window-x="40"
inkscape:window-y="40"
inkscape:current-layer="Foreground"><inkscape:grid
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" /></sodipodi:namedview>
<path
d="M0,3c0-1.657,1.343-3,3-3h17c0.515,0,1.027,0.195,1.42,0.588l6.992,6.992c0.784,0.784,0.784,2.056,0,2.84l-6.992,6.992 C21.028,17.804,20.514,18,20,18H3c-1.657,0-3-1.343-3-3V3z"
id="path3"
style="fill:#151e2f;fill-opacity:1" />
id="grid2391"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" /></sodipodi:namedview>
<g
id="g5"
style="fill:#4669a9;fill-opacity:1">
style="fill:#ffffff;fill-opacity:1"
transform="translate(-4,-0.023114)">
<path
fill="#FFFFFF"
d="M6.246,13.98c-0.319-0.319-0.319-0.837,0-1.157l3.717-3.717c0.319-0.319,0.837-0.319,1.157,0l0.786,0.787 c0.32,0.319,0.32,0.837,0,1.157l-3.717,3.717c-0.32,0.319-0.838,0.319-1.157,0L6.246,13.98L6.246,13.98z"
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:#4669a9;fill-opacity:1" />
style="fill:#ffffff;fill-opacity:1" />
<path
fill="#FFFFFF"
d="M9.076,11.937"
d="M 9.076,11.937"
id="path9"
style="fill:#4669a9;fill-opacity:1" />
style="fill:#ffffff;fill-opacity:1" />
</g>
<path
fill-rule="evenodd"
clip-rule="evenodd"
fill="#FFFFFF"
d="M11.25,7.5c0-1.243,1.007-2.25,2.25-2.25s2.25,1.007,2.25,2.25 s-1.007,2.25-2.25,2.25S11.25,8.743,11.25,7.5z M9,7.5C9,5.015,11.015,3,13.5,3S18,5.015,18,7.5S15.985,12,13.5,12S9,9.985,9,7.5z"
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:#4669a9;fill-opacity:1" />
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd" />
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

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

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns: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="29px"
height="18px"
viewBox="0 0 29 18"
enable-background="new 0 0 29 18"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="search_2.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" /></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="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
showgrid="false"
inkscape:zoom="19.275862"
inkscape:cx="14.5"
inkscape:cy="9"
inkscape:window-x="40"
inkscape:window-y="40"
inkscape:current-layer="Foreground"><inkscape:grid
type="xygrid"
id="grid2391" /></sodipodi:namedview>
<path
style="fill:#4669a9;fill-opacity:1"
id="path9"
d="" />
<path
id="path3"
style="fill:#3d5a93;fill-opacity:1"
d="M 0,3 C 0,1.343 1.343,0 3,0 L 20,0 C 20.515,0 21.027,0.195 21.42,0.588 L 28.412,7.58 C 29.196,8.364 29.196,9.636 28.412,10.42 L 21.42,17.412 C 21.028,17.804 20.514,18 20,18 L 3,18 C 1.343,18 0,16.657 0,15 L 0,3 zM 13.5,3 C 11.015,3 9,5.015 9,7.5 C 9,8.2423219 9.1815696,8.9452421 9.5,9.5625 L 6.25,12.8125 C 5.931,13.1325 5.9310002,13.64975 6.25,13.96875 L 7.03125,14.78125 C 7.35025,15.10025 7.8674999,15.10025 8.1875,14.78125 L 11.46875,11.5 C 12.080227,11.810879 12.767137,12 13.5,12 C 15.985,12 18,9.985 18,7.5 C 18,5.015 15.985,3 13.5,3 z M 11.25,7.5 C 11.25,6.257 12.257,5.25 13.5,5.25 C 14.743,5.25 15.75,6.257 15.75,7.5 C 15.75,8.743 14.743,9.75 13.5,9.75 C 12.257,9.75 11.25,8.743 11.25,7.5 z" />
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

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

@ -85,19 +85,18 @@ DocInfo.prototype = {
var docManagerInstance = null;
function getDocManager(size) {
function getDocManager() {
if (docManagerInstance == null)
docManagerInstance = new DocManager(size);
docManagerInstance = new DocManager();
return docManagerInstance;
}
function DocManager(size) {
this._init(size);
function DocManager() {
this._init();
}
DocManager.prototype = {
_init: function(iconSize) {
this._iconSize = iconSize;
_init: function() {
this._recentManager = Gtk.RecentManager.get_default();
this._items = {};
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
@ -112,6 +111,9 @@ DocManager.prototype = {
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
@ -126,7 +128,7 @@ DocManager.prototype = {
dump them here */
let texCache = Shell.TextureCache.get_default();
for (var uri in deleted) {
texCache.evict_recent_thumbnail(this._iconSize, this._items[uri]);
texCache.evict_recent_thumbnail(this._items[uri]);
}
this._items = newItems;
},

View File

@ -3,16 +3,18 @@ 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 \

View File

@ -36,18 +36,14 @@ function AltTabPopup() {
AltTabPopup.prototype = {
_init : function() {
let global = Shell.Global.get();
this.actor = new Big.Box({ background_color : POPUP_BG_COLOR,
corner_radius: POPUP_GRID_SPACING,
padding: POPUP_GRID_SPACING,
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.
// 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,
@ -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();
@ -164,8 +156,6 @@ AltTabPopup.prototype = {
destroy : function() {
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

View File

@ -6,12 +6,14 @@ const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Tidy = imports.gi.Tidy;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppIcon = imports.ui.appIcon;
const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
@ -20,16 +22,31 @@ const Workspaces = imports.ui.workspaces;
const ENTERED_MENU_COLOR = new Clutter.Color();
ENTERED_MENU_COLOR.from_pixel(0x00ff0022);
const GLOW_COLOR = new Clutter.Color();
GLOW_COLOR.from_pixel(0x4f6ba4ff);
const GLOW_PADDING = 5;
const APP_ICON_SIZE = 48;
const WELL_DEFAULT_COLUMNS = 4;
const WELL_ITEM_HSPACING = 0;
const WELL_ITEM_VSPACING = 4;
const WELL_MENU_POPUP_TIMEOUT_MS = 600;
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const WELL_MENU_BACKGROUND_COLOR = new Clutter.Color();
WELL_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
const WELL_MENU_FONT = 'Sans 14px';
const WELL_MENU_COLOR = new Clutter.Color();
WELL_MENU_COLOR.from_pixel(0xffffffff);
const WELL_MENU_SELECTED_COLOR = new Clutter.Color();
WELL_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
const WELL_MENU_BORDER_COLOR = new Clutter.Color();
WELL_MENU_BORDER_COLOR.from_pixel(0x787878ff);
const WELL_MENU_SEPARATOR_COLOR = new Clutter.Color();
WELL_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
const WELL_MENU_BORDER_WIDTH = 1;
const WELL_MENU_ARROW_SIZE = 12;
const WELL_MENU_CORNER_RADIUS = 4;
const WELL_MENU_PADDING = 4;
const MENU_ICON_SIZE = 24;
const MENU_SPACING = 15;
@ -61,7 +78,13 @@ AppDisplayItem.prototype = {
// Opens an application represented by this display item.
launch : function() {
this._appInfo.launch();
let windows = Shell.AppMonitor.get_default().get_windows_for_app(this._appInfo.get_id());
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
} else {
this._appInfo.launch();
}
},
//// Protected method overrides ////
@ -74,6 +97,10 @@ AppDisplayItem.prototype = {
// Returns a preview icon for the item.
_createPreviewIcon : function() {
return this._appInfo.create_icon_texture(GenericDisplay.PREVIEW_ICON_SIZE);
},
shellWorkspaceLaunch: function() {
this.launch();
}
};
@ -161,21 +188,25 @@ MenuItem.prototype = {
}
Signals.addSignalMethods(MenuItem.prototype);
/* This class represents a display containing a collection of application items.
* The applications are sorted based on their popularity by default, and based on
* their name if some search filter is applied.
*
* showPrefs - a boolean indicating if this AppDisplay should contain preference
* applets, rather than applications
*/
function AppDisplay() {
this._init();
function AppDisplay(showPrefs) {
this._init(showPrefs);
}
AppDisplay.prototype = {
__proto__: GenericDisplay.GenericDisplay.prototype,
_init : function() {
_init : function(showPrefs) {
GenericDisplay.GenericDisplay.prototype._init.call(this);
this._showPrefs = showPrefs;
this._menus = [];
this._menuDisplays = [];
@ -193,12 +224,15 @@ AppDisplay.prototype = {
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
this._redisplay(false);
}));
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
this._appMonitor.connect('app-added', Lang.bind(this, function(monitor) {
this._redisplay(false);
}));
this._appMonitor.connect('app-removed', Lang.bind(this, function(monitor) {
this._redisplay(false);
}));
// Load the apps now so it doesn't slow down the first
// transition into the overlay
// transition into the Overview
this._refreshCache();
this._focusInMenus = true;
@ -308,7 +342,7 @@ AppDisplay.prototype = {
_redisplayMenus: function() {
this._menuDisplay.remove_all();
this._addMenuItem('Frequent', null, 'gtk-select-all');
this._addMenuItem(_("Frequent"), null, 'gtk-select-all');
for (let i = 0; i < this._menus.length; i++) {
let menu = this._menus[i];
this._addMenuItem(menu.name, menu.id, menu.icon, i+1);
@ -324,30 +358,37 @@ AppDisplay.prototype = {
// Gets information about all applications by calling Gio.app_info_get_all().
_refreshCache : function() {
let me = this;
if (!this._appsStale)
return;
this._allItems = {};
this._appCategories = {};
this._menus = this._appSystem.get_menus();
// Loop over the toplevel menu items, load the set of desktop file ids
// associated with each one
for (let i = 0; i < this._menus.length; i++) {
let menu = this._menus[i];
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
for (let j = 0; j < menuApps.length; j++) {
let app = menuApps[j];
if (this._showPrefs) {
// Get the desktop file ids for settings/preferences.
// These are used for search results, but not in the app menus.
let settings = this._appSystem.get_all_settings();
for (let i = 0; i < settings.length; i++) {
let app = settings[i];
this._addApp(app);
}
}
// Now grab the desktop file ids for settings/preferences.
// These show up in search, but not with the rest of apps.
let settings = this._appSystem.get_all_settings();
for (let i = 0; i < settings.length; i++) {
let app = settings[i];
this._addApp(app);
} else {
// Loop over the toplevel menu items, load the set of desktop file ids
// associated with each one, skipping empty menus
let allMenus = this._appSystem.get_menus();
this._menus = [];
for (let i = 0; i < allMenus.length; i++) {
let menu = allMenus[i];
let menuApps = this._appSystem.get_applications_for_menu(menu.id);
let hasVisibleApps = menuApps.some(function (app) { return !app.get_is_nodisplay(); });
if (!hasVisibleApps) {
continue;
}
this._menus.push(menu);
for (let j = 0; j < menuApps.length; j++) {
let app = menuApps[j];
this._addApp(app);
}
}
}
this._appsStale = false;
@ -439,124 +480,438 @@ AppDisplay.prototype = {
Signals.addSignalMethods(AppDisplay.prototype);
function WellDisplayItem(appInfo, isFavorite) {
function WellMenu(source) {
this._init(source);
}
WellMenu.prototype = {
_init: function(source) {
this._source = source;
// Whether or not we successfully picked a window
this.didActivateWindow = false;
this.actor = new Shell.GenericContainer({ reactive: true });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
border_color: WELL_MENU_BORDER_COLOR,
border: WELL_MENU_BORDER_WIDTH,
background_color: WELL_MENU_BACKGROUND_COLOR,
padding: 4,
corner_radius: WELL_MENU_CORNER_RADIUS,
width: Main.overview._dash.actor.width * 0.75 });
this._windowContainer.connect('unselected', Lang.bind(this, this._onWindowUnselected));
this._windowContainer.connect('selected', Lang.bind(this, this._onWindowSelected));
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
this._windowContainer.connect('activate', Lang.bind(this, this._onWindowActivate));
this.actor.add_actor(this._windowContainer);
// Stay popped up on release over application icon
this._windowContainer.set_persistent_source(this._source.actor);
// Intercept events while the menu has the pointer grab to do window-related effects
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
this._arrow = new Shell.DrawingArea();
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
Shell.draw_box_pointer(texture, WELL_MENU_BORDER_COLOR, WELL_MENU_BACKGROUND_COLOR);
}));
this.actor.add_actor(this._arrow);
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
if (!source.actor.mapped)
this._windowContainer.popdown();
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
global.stage.add_actor(this.actor);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
alloc.min_size = min + WELL_MENU_ARROW_SIZE;
alloc.natural_size = natural + WELL_MENU_ARROW_SIZE;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
alloc.min_size = min;
alloc.natural_size = natural;
},
_allocate: function(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
childBox.x1 = 0;
childBox.x2 = WELL_MENU_ARROW_SIZE;
childBox.y1 = Math.floor((height / 2) - (WELL_MENU_ARROW_SIZE / 2));
childBox.y2 = childBox.y1 + WELL_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
/* overlap by one pixel to hide the border */
childBox.x1 = WELL_MENU_ARROW_SIZE - 1;
childBox.x2 = width;
childBox.y1 = 0;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
},
_redisplay: function() {
this._windowContainer.remove_all();
this.didActivateWindow = false;
let windows = this._source.windows;
this._windowContainer.show();
let iconsDiffer = false;
let texCache = Shell.TextureCache.get_default();
let firstIcon = windows[0].mini_icon;
for (let i = 1; i < windows.length; i++) {
if (!texCache.pixbuf_equal(windows[i].mini_icon, firstIcon)) {
iconsDiffer = true;
break;
}
}
let activeWorkspace = global.screen.get_active_workspace();
let currentWorkspaceWindows = windows.filter(function (w) {
return w.get_workspace() == activeWorkspace;
});
let otherWorkspaceWindows = windows.filter(function (w) {
return w.get_workspace() != activeWorkspace;
});
this._appendWindows(currentWorkspaceWindows, iconsDiffer);
if (currentWorkspaceWindows.length > 0 && otherWorkspaceWindows.length > 0) {
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
box.append(new Clutter.Rectangle({ height: 1,
color: WELL_MENU_SEPARATOR_COLOR }),
Big.BoxPackFlags.EXPAND);
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
}
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
},
_appendWindows: function (windows, iconsDiffer) {
for (let i = 0; i < windows.length; i++) {
let metaWindow = windows[i];
/* Use padding here rather than spacing in the box above so that
* we have a larger reactive area.
*/
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: 4,
padding_bottom: 4,
spacing: 4,
reactive: true });
box._window = metaWindow;
let vCenter;
if (iconsDiffer) {
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
vCenter.append(icon, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
}
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let label = new Clutter.Text({ text: metaWindow.title,
font_name: WELL_MENU_FONT,
ellipsize: Pango.EllipsizeMode.END,
color: WELL_MENU_COLOR });
vCenter.append(label, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
}
},
popup: function() {
let [stageX, stageY] = this._source.actor.get_transformed_position();
let [stageWidth, stageHeight] = this._source.actor.get_transformed_size();
this._redisplay();
this._windowContainer.popup(0, Clutter.get_current_event_time());
this.emit('popup', true);
let x = Math.floor(stageX + stageWidth);
let y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
this.actor.set_position(x, y);
this.actor.show();
},
_findWindowCloneForActor: function (actor) {
if (actor._delegate instanceof Workspaces.WindowClone)
return actor._delegate;
return null;
},
// This function is called while the menu has a pointer grab; what we want
// to do is see if the mouse was released over a window clone actor
_onMenuButtonRelease: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this.didActivateWindow = true;
Main.overview.activateWindow(clone.metaWindow, event.get_time());
}
},
_setHighlightWindow: function (metaWindow) {
let children = this._windowContainer.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
let menuMetaWindow = child._window;
if (metaWindow != null && menuMetaWindow == metaWindow) {
child.background_color = WELL_MENU_SELECTED_COLOR;
} else {
child.background_color = TRANSPARENT_COLOR;
}
}
this.emit('highlight-window', metaWindow);
},
// Called while menu has a pointer grab
_onMenuEnter: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this._setHighlightWindow(clone.metaWindow);
}
},
// Called while menu has a pointer grab
_onMenuLeave: function (actor, event) {
let clone = this._findWindowCloneForActor(event.get_source());
if (clone) {
this._setHighlightWindow(null);
}
},
_onWindowUnselected: function (actor, child) {
this._setHighlightWindow(null);
},
_onWindowSelected: function (actor, child) {
this._setHighlightWindow(child._window);
},
_onWindowActivate: function (actor, child) {
let metaWindow = child._window;
this.didActivateWindow = true;
Main.overview.activateWindow(metaWindow, Clutter.get_current_event_time());
this.emit('popup', false);
this.actor.hide();
},
_onWindowSelectionCancelled: function () {
this.emit('highlight-window', null);
this.emit('popup', false);
this.actor.hide();
}
}
Signals.addSignalMethods(WellMenu.prototype);
function BaseWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
WellDisplayItem.prototype = {
_init : function(appInfo, isFavorite) {
BaseWellItem.prototype = {
_init: function(appInfo, isFavorite) {
this.appInfo = appInfo;
this.isFavorite = isFavorite;
this.icon = new AppIcon.AppIcon(appInfo);
this.windows = this.icon.windows;
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
border: WELL_MENU_BORDER_WIDTH,
corner_radius: WELL_MENU_CORNER_RADIUS,
reactive: true });
this.icon.actor._delegate = this;
this._draggable = DND.makeDraggable(this.icon.actor, true);
this.actor = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
corner_radius: 2,
border: 0,
padding: 1,
border_color: GenericDisplay.ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR,
reactive: true });
this.actor._delegate = this;
this.actor.connect('button-release-event', Lang.bind(this, function (b, e) {
this._handleActivate();
// Do these as anonymous functions to avoid conflict with handlers in subclasses
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
this._dragStartY = stageY;
return false;
}));
let draggable = DND.makeDraggable(this.actor);
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x_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.NONE);
this._windows = Shell.AppMonitor.get_default().get_windows_for_app(appInfo.get_id());
let nameBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER });
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.append(this._name, Big.BoxPackFlags.NONE);
if (this._windows.length > 0) {
let glow = new Shell.DrawingArea({});
glow.connect('redraw', Lang.bind(this, function (e, tex) {
Shell.draw_glow(tex,
GLOW_COLOR.red / 255,
GLOW_COLOR.green / 255,
GLOW_COLOR.blue / 255,
GLOW_COLOR.alpha / 255);
}));
this._name.connect('notify::allocation', Lang.bind(this, function () {
let x = this._name.x;
let y = this._name.y;
let width = this._name.width;
let height = this._name.height;
// If we're smaller than the allocated box width, pad out the glow a bit
// to make it more visible
if ((width + GLOW_PADDING * 2) < this._nameBox.width) {
width += GLOW_PADDING * 2;
x -= GLOW_PADDING;
this.actor.connect('notify::hover', Lang.bind(this, function () {
let hover = this.actor.hover;
if (!hover) {
if (this.actor.pressed && this._dragStartX != null) {
this.actor.fake_release();
this._draggable.startDrag(this.icon.actor, this._dragStartX, this._dragStartY,
Clutter.get_current_event_time());
} else {
this._dragStartX = null;
this._dragStartY = null;
}
glow.set_size(width, height);
glow.set_position(x, y);
}));
nameBox.add_actor(glow);
glow.lower(this._name);
}
this.actor.append(nameBox, Big.BoxPackFlags.NONE);
}
}));
this.actor.append(this.icon.actor, Big.BoxPackFlags.NONE);
},
_handleActivate: function () {
if (this._windows.length == 0)
this.launch();
else {
/* Pick the first window and activate it;
* In the future, we want to have a menu dropdown here. */
let first = this._windows[0];
Main.overlay.activateWindow (first, Clutter.get_current_event_time());
}
this.emit('activated');
},
// Opens an application represented by this display item.
launch : function() {
shellWorkspaceLaunch : function() {
// Here we just always launch the application again, even if we know
// it was already running. For most applications this
// should have the effect of creating a new window, whether that's
// a second process (in the case of Calculator) or IPC to existing
// instance (Firefox). There are a few less-sensical cases such
// as say Pidgin, but ideally what we do there is have the app
// express to us that it doesn't do relaunch=new-window in the
// .desktop file.
this.appInfo.launch();
},
// Draggable interface - FIXME deduplicate with GenericDisplay
getDragActor: function(stageX, stageY) {
this.dragActor = this.appInfo.create_icon_texture(APP_ICON_SIZE);
// If the user dragged from the icon itself, then position
// the dragActor over the original icon. Otherwise center it
// around the pointer
let [iconX, iconY] = this._icon.get_transformed_position();
let [iconWidth, iconHeight] = this._icon.get_transformed_size();
if (stageX > iconX && stageX <= iconX + iconWidth &&
stageY > iconY && stageY <= iconY + iconHeight)
this.dragActor.set_position(iconX, iconY);
else
this.dragActor.set_position(stageX - this.dragActor.width / 2, stageY - this.dragActor.height / 2);
return this.dragActor;
return this.icon.getDragActor(stageX, stageY);
},
// Returns the original icon that is being used as a source for the cloned texture
// that represents the item as it is being dragged.
getDragActorSource: function() {
return this._icon;
return this.icon.getDragActorSource();
}
}
function RunningWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
RunningWellItem.prototype = {
__proto__: BaseWellItem.prototype,
_init: function(appInfo, isFavorite) {
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
this._menuTimeoutId = 0;
this._menu = null;
this._dragStartX = 0;
this._dragStartY = 0;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._onActivate));
},
setWidth: function(width) {
this._nameBox.width = width + GLOW_PADDING * 2;
_onActivate: function (actor, event) {
let modifiers = event.get_state();
if (this._menuTimeoutId > 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
if (modifiers & Clutter.ModifierType.CONTROL_MASK) {
this.appInfo.launch();
} else {
this.activateMostRecentWindow();
}
},
activateMostRecentWindow: function () {
// The _get_windows_for_app sorts them for us
let mostRecentWindow = this.windows[0];
Main.overview.activateWindow(mostRecentWindow, Clutter.get_current_event_time());
},
_onHoverChanged: function() {
let hover = this.actor.hover;
if (!hover && this._menuTimeoutId > 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
},
_onButtonPress: function(actor, event) {
if (this._menuTimeoutId > 0)
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = Mainloop.timeout_add(WELL_MENU_POPUP_TIMEOUT_MS,
Lang.bind(this, this._popupMenu));
return false;
},
_popupMenu: function() {
this._menuTimeoutId = 0;
this.actor.fake_release();
if (this._menu == null) {
this._menu = new WellMenu(this);
this._menu.connect('highlight-window', Lang.bind(this, function (menu, metaWindow) {
Main.overview.getWorkspacesForWindow(metaWindow).setHighlightWindow(metaWindow);
}));
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
let id;
// If we successfully picked a window, don't reset the workspace
// state, since picking a window already did that.
if (!isPoppedUp && menu.didActivateWindow)
return;
if (isPoppedUp)
id = this.appInfo.get_id();
else
id = null;
Main.overview.getWorkspacesForWindow(null).setApplicationWindowSelection(id);
}));
}
this._menu.popup();
return false;
}
}
function InactiveWellItem(appInfo, isFavorite) {
this._init(appInfo, isFavorite);
}
InactiveWellItem.prototype = {
__proto__: BaseWellItem.prototype,
_init : function(appInfo, isFavorite) {
BaseWellItem.prototype._init.call(this, appInfo, isFavorite);
this.actor.connect('notify::pressed', Lang.bind(this, this._onPressedChanged));
this.actor.connect('notify::hover', Lang.bind(this, this._onHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._onActivate));
},
_onPressedChanged: function() {
let pressed = this.actor.pressed;
if (pressed) {
this.actor.border_color = WELL_MENU_BORDER_COLOR;
} else {
this.actor.border_color = TRANSPARENT_COLOR;
}
},
_onHoverChanged: function() {
let hover = this.actor.hover;
},
_onActivate: function() {
if (this.windows.length == 0) {
this.appInfo.launch();
Main.overview.hide();
return true;
}
return false;
}
};
Signals.addSignalMethods(WellDisplayItem.prototype);
function WellGrid() {
this._init();
}
@ -565,9 +920,7 @@ WellGrid.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this._separator = new Big.Box({ border_color: GenericDisplay.ITEM_DISPLAY_NAME_COLOR,
border_top: 1,
height: 1 });
this._separator = new Big.Box({ height: 1 });
this.actor.add_actor(this._separator);
this._separatorIndex = 0;
this._cachedSeparatorY = 0;
@ -611,20 +964,17 @@ WellGrid.prototype = {
let y = box.y1;
let columnIndex = 0;
for (let i = 0; i < children.length; i++) {
let [childMinWidth, childMinHeight,
childNaturalWidth, childNaturalHeight] = children[i].get_preferred_size();
let [childMinWidth, childNaturalWidth] = children[i].get_preferred_width(-1);
/* Center the item in its allocation */
/* Center the item in its allocation horizontally */
let width = Math.min(itemWidth, childNaturalWidth);
let height = Math.min(itemHeight, childNaturalHeight);
let horizSpacing = (itemWidth - width) / 2;
let vertSpacing = (itemHeight - height) / 2;
let childBox = new Clutter.ActorBox();
childBox.x1 = Math.floor(x + horizSpacing);
childBox.y1 = Math.floor(y + vertSpacing);
childBox.y1 = y;
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
childBox.y2 = childBox.y1 + itemHeight;
children[i].allocate(childBox, flags);
let atSeparator = (i == this._separatorIndex - 1);
@ -763,7 +1113,10 @@ AppWell.prototype = {
this._appSystem.connect('favorites-changed', Lang.bind(this, function(appSys) {
this._redisplay();
}));
this._appMonitor.connect('changed', Lang.bind(this, function(monitor) {
this._appMonitor.connect('window-added', Lang.bind(this, function(monitor) {
this._redisplay();
}));
this._appMonitor.connect('window-removed', Lang.bind(this, function(monitor) {
this._redisplay();
}));
@ -796,11 +1149,10 @@ AppWell.prototype = {
/* hardcode here pending some design about how exactly desktop contexts behave */
let contextId = "";
let runningIds = this._appMonitor.get_running_app_ids(contextId).filter(function (e) {
return !(e in favoriteIdsHash);
let running = this._appMonitor.get_running_apps(contextId).filter(function (e) {
return !(e.get_id() in favoriteIdsHash);
});
let favorites = this._lookupApps(favoriteIds);
let running = this._lookupApps(runningIds);
let displays = []
this._addApps(favorites, true);
@ -809,37 +1161,40 @@ AppWell.prototype = {
this._displays = displays;
},
_addApps: function(apps) {
_addApps: function(apps, isFavorite) {
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
let display = new WellDisplayItem(app, this.isFavorite);
display.connect('activated', Lang.bind(this, function (display) {
Main.overlay.hide();
}));
let windows = this._appMonitor.get_windows_for_app(app.get_id());
let display;
if (windows.length > 0)
display = new RunningWellItem(app, isFavorite);
else
display = new InactiveWellItem(app, isFavorite);
this._grid.actor.add_actor(display.actor);
}
},
// Draggable target interface
acceptDrop : function(source, actor, x, y, time) {
let global = Shell.Global.get();
let appSystem = Shell.AppSystem.get_default();
let id = null;
if (source instanceof WellDisplayItem) {
id = source.appInfo.get_id();
let app = null;
if (source instanceof BaseWellItem) {
app = source.appInfo;
} else if (source instanceof AppDisplayItem) {
id = source.getId();
app = appSystem.lookup_cached_app(source.getId());
} else if (source instanceof Workspaces.WindowClone) {
let appMonitor = Shell.AppMonitor.get_default();
let app = appMonitor.get_window_app(source.metaWindow);
id = app.get_id();
app = appMonitor.get_window_app(source.metaWindow);
}
if (id == null) {
// Don't allow favoriting of transient apps
if (app == null || app.is_transient()) {
return false;
}
let appSystem = Shell.AppSystem.get_default();
let id = app.get_id();
let favoriteIds = this._appSystem.get_favorites();
let favoriteIdsObject = this._arrayValues(favoriteIds);

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

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

View File

@ -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,8 +124,8 @@ Chrome.prototype = {
//
// Removes @actor from the chrome layer
removeActor: function(actor) {
if (actor.get_parent() == this.nonOverlayActor)
this.nonOverlayActor.remove_actor(actor);
if (actor.get_parent() == this.nonOverviewActor)
this.nonOverviewActor.remove_actor(actor);
else
this.actor.remove_actor(actor);
this._untrackActor(actor, true, true);
@ -172,7 +170,7 @@ Chrome.prototype = {
this._trackedActors.push(actorData);
actor = actor.get_parent();
if (actor != this.actor && actor != this.nonOverlayActor)
if (actor != this.actor && actor != this.nonOverviewActor)
this._trackActor(actor, false, false);
if (inputRegion || strut)
@ -200,7 +198,7 @@ Chrome.prototype = {
actor.disconnect(actorData.parentSetId);
actor = actor.get_parent();
if (actor && actor != this.actor && actor != this.nonOverlayActor)
if (actor && actor != this.actor && actor != this.nonOverviewActor)
this._untrackActor(actor, false, false);
}
@ -211,23 +209,23 @@ Chrome.prototype = {
_actorReparented: function(actor, oldParent) {
if (this._verifyAncestry(actor, this.actor)) {
let newParent = actor.get_parent();
if (newParent != this.actor && newParent != this.nonOverlayActor)
if (newParent != this.actor && newParent != this.nonOverviewActor)
this._trackActor(newParent, false, false);
}
if (oldParent != this.actor && oldParent != this.nonOverlayActor)
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();
},
@ -238,7 +236,6 @@ Chrome.prototype = {
},
_windowsRestacked: function() {
let global = Shell.Global.get();
let windows = global.get_windows();
// The chrome layer should be visible unless there is a window
@ -272,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();
@ -280,7 +277,6 @@ Chrome.prototype = {
},
_updateRegions: function() {
let global = Shell.Global.get();
let rects = [], struts = [], i;
delete this._updateRegionIdle;

File diff suppressed because it is too large Load Diff

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
@ -138,7 +178,7 @@ _Draggable.prototype = {
event.get_time());
}
target = target.get_parent();
}
}
}
return true;
@ -214,6 +254,13 @@ _Draggable.prototype = {
Signals.addSignalMethods(_Draggable.prototype);
function makeDraggable(actor) {
return new _Draggable(actor);
/**
* makeDraggable:
* @actor: Source actor
* @manualMode: If given, do not automatically start drag and drop on click
*
* Create an object which controls drag and drop for the given actor.
*/
function makeDraggable(actor, manualMode) {
return new _Draggable(actor, manualMode);
}

View File

@ -1,17 +1,24 @@
/* -*- 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.
@ -68,21 +75,34 @@ DocDisplayItem.prototype = {
// 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(Shell.TextureCachePolicy.NONE,
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.
// 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] = Shell.Global.get().format_time_relative_pretty(timeDelta);
let [text, nextUpdate] = global.format_time_relative_pretty(timeDelta);
this._timeoutTime = currentSecs + nextUpdate;
this._setDescriptionText(text);
}
@ -100,8 +120,6 @@ DocDisplay.prototype = {
_init : function() {
GenericDisplay.GenericDisplay.prototype._init.call(this);
let me = this;
// We keep a single timeout callback for updating last visited times
// for all the items in the display. This avoids creating individual
// callbacks for each item in the display. So proper time updates
@ -110,16 +128,16 @@ DocDisplay.prototype = {
this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
this._docManager = DocInfo.getDocManager(GenericDisplay.ITEM_DISPLAY_ICON_SIZE);
this._docManager = DocInfo.getDocManager();
this._docsStale = true;
this._docManager.connect('changed', function(mgr, 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)
@ -148,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
@ -236,3 +254,183 @@ DocDisplay.prototype = {
};
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();
}

View File

@ -7,10 +7,10 @@ const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const Tidy = imports.gi.Tidy;
const Button = imports.ui.button;
const DND = imports.ui.dnd;
@ -88,7 +88,6 @@ GenericDisplayItem.prototype = {
spacing: DEFAULT_PADDING });
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
let global = Shell.Global.get();
let infoIconUri = "file://" + global.imagedir + "info.svg";
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
infoIconUri,
@ -126,8 +125,6 @@ GenericDisplayItem.prototype = {
// It is used for updating the description text inside the details actor when
// the description text for the item is updated.
this._detailsDescriptions = [];
this.dragActor = null;
},
//// Draggable object interface ////
@ -135,21 +132,9 @@ GenericDisplayItem.prototype = {
// Returns a cloned texture of the item's icon to represent the item as it
// is being dragged.
getDragActor: function(stageX, stageY) {
this.dragActor = this._createIcon();
// If the user dragged from the icon itself, then position
// the dragActor over the original icon. Otherwise center it
// around the pointer
let [iconX, iconY] = this._icon.get_transformed_position();
let [iconWidth, iconHeight] = this._icon.get_transformed_size();
if (stageX > iconX && stageX <= iconX + iconWidth &&
stageY > iconY && stageY <= iconY + iconHeight)
this.dragActor.set_position(iconX, iconY);
else
this.dragActor.set_position(stageX - this.dragActor.width / 2, stageY - this.dragActor.height / 2);
return this.dragActor;
return this._createIcon();
},
// Returns the item icon, a separate copy of which is used to
// represent the item as it is being dragged. This is used to
// determine a snap-back location for the drag icon if it does
@ -183,18 +168,14 @@ GenericDisplayItem.prototype = {
/*
* Returns an actor containing item details. In the future details can have more information than what
* the preview pop-up has and be item-type specific.
*
* availableWidth - width available for displaying details
*/
createDetailsActor: function(availableWidth) {
createDetailsActor: function() {
let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PREVIEW_BOX_SPACING,
width: availableWidth });
spacing: PREVIEW_BOX_SPACING });
let mainDetails = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: PREVIEW_BOX_SPACING,
width: availableWidth });
spacing: PREVIEW_BOX_SPACING });
// Inner box with name and description
let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
@ -216,7 +197,7 @@ GenericDisplayItem.prototype = {
mainDetails.append(textDetails, Big.BoxPackFlags.EXPAND);
let previewIcon = this._createPreviewIcon();
let largePreviewIcon = this._createLargePreviewIcon(availableWidth, -1);
let largePreviewIcon = this._createLargePreviewIcon();
if (previewIcon != null && largePreviewIcon == null) {
mainDetails.prepend(previewIcon, Big.BoxPackFlags.NONE);
@ -303,7 +284,7 @@ GenericDisplayItem.prototype = {
//// Virtual protected methods ////
// Creates and returns a large preview icon, but only if we have a detailed image.
_createLargePreviewIcon : function(availableWidth, availableHeight) {
_createLargePreviewIcon : function() {
return null;
},
@ -380,13 +361,13 @@ GenericDisplay.prototype = {
this._redisplay(true);
},
// Launches the item that is currently selected, closing the overlay
// Launches the item that is currently selected, closing the Overview
activateSelected: function() {
if (this._selectedIndex != -1) {
let selected = this._findDisplayedByIndex(this._selectedIndex);
selected.launch();
this.unsetSelected();
Main.overlay.hide();
Main.overview.hide();
}
},
@ -445,7 +426,15 @@ GenericDisplay.prototype = {
// Returns true if the display has any displayed items.
hasItems: function() {
return this._list.displayedCount > 0;
// TODO: figure out why this._list.displayedCount is returning a
// positive number when this._mathedItems.length is 0
// This can be triggered if a search string is entered for which there are no matches.
// log("this._mathedItems.length: " + this._matchedItems.length + " this._list.displayedCount " + this._list.displayedCount);
return this._matchedItems.length > 0;
},
getMatchedItemsCount: function() {
return this._matchedItems.length;
},
// Load the initial state
@ -465,9 +454,18 @@ GenericDisplay.prototype = {
return null;
},
createDetailsForIndex: function(index, width, height) {
createDetailsForIndex: function(index) {
let item = this._findDisplayedByIndex(index);
return item.createDetailsActor(width, height);
return item.createDetailsActor();
},
// Displays the page specified by the pageNumber argument.
displayPage: function(pageNumber) {
// Cleanup from the previous selection, but don't unset this._selectedIndex
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}
this._list.page = pageNumber;
},
//// Protected methods ////
@ -497,24 +495,23 @@ GenericDisplay.prototype = {
this.selectFirstItem();
}
// We currently redisplay matching items and raise the sideshow as part of two different callbacks.
// Checking what is under the pointer after a timeout allows us to not merge these callbacks into one, at least for now.
Mainloop.timeout_add(5,
Lang.bind(this,
function() {
// Check if the pointer is over one of the items and display the information button if it is.
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let global = Shell.Global.get();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor);
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}));
// Check if the pointer is over one of the items and display the information button if it is.
// We want to do this between finishing our changes to the display and the point where
// the display is redrawn.
Mainloop.idle_add(Lang.bind(this,
function() {
let [child, x, y, mask] = Gdk.Screen.get_default().get_root_window().get_pointer();
let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE,
x, y);
if (actor != null) {
let item = this._findDisplayedByActor(actor);
if (item != null) {
item.onDrawnUnderPointer();
}
}
return false;
}),
Meta.PRIORITY_BEFORE_REDRAW);
},
// Creates a display item based on the information associated with itemId
@ -698,11 +695,6 @@ GenericDisplay.prototype = {
}));
},
// Displays the page specified by the pageNumber argument.
_displayPage: function(pageNumber) {
this._list.page = pageNumber;
},
/*
* Updates the display control to reflect the matched items set and the page selected.
*
@ -713,9 +705,11 @@ GenericDisplay.prototype = {
*/
_updateDisplayControl: function(resetDisplayControl) {
if (resetDisplayControl) {
this._selectedIndex = -1;
this.displayControl.remove_all();
let nPages = this._list.n_pages;
// Don't show the page indicator if there is only one page.
if (nPages == 1)
return;
let pageNumber = this._list.page;
for (let i = 0; i < nPages; i++) {
let pageControl = new Link.Link({ color: (i == pageNumber) ? DISPLAY_CONTROL_SELECTED_COLOR : ITEM_DISPLAY_DESCRIPTION_COLOR,
@ -729,7 +723,7 @@ GenericDisplay.prototype = {
pageControl.connect('clicked',
Lang.bind(this,
function(o, event) {
this._displayPage(pageNumberLocalScope);
this.displayPage(pageNumberLocalScope);
}));
}
} else {
@ -745,6 +739,9 @@ GenericDisplay.prototype = {
}
}
}
if (this.hasSelected()) {
this.selectFirstItem();
}
},
// Returns a display item based on its index in the ordering of the
@ -769,17 +766,8 @@ GenericDisplay.prototype = {
// Selects (e.g. highlights) a display item at the provided index,
// updates this.selectedItemDetails actor, and emits 'selected' signal.
_selectIndex: function(index) {
if (index >= this._list.displayedCount)
return
// If the item is already selected, all we do is toggling the details pane.
if (this._selectedIndex == index && index >= 0) {
this.emit('details', index);
return;
}
// Cleanup from the previous item
if (this._selectedIndex >= 0) {
if (this.hasSelected()) {
this._findDisplayedByIndex(this._selectedIndex).markSelected(false);
}

View File

@ -4,6 +4,7 @@ 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;
@ -12,18 +13,7 @@ const Mainloop = imports.mainloop;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const LG_BORDER_COLOR = new Clutter.Color();
LG_BORDER_COLOR.from_pixel(0x0000aca0);
const LG_BACKGROUND_COLOR = new Clutter.Color();
LG_BACKGROUND_COLOR.from_pixel(0x000000d5);
const GREY = new Clutter.Color();
GREY.from_pixel(0xAFAFAFFF);
const MATRIX_GREEN = new Clutter.Color();
MATRIX_GREEN.from_pixel(0x88ff66ff);
// FIXME pull from GConf
const MATRIX_FONT = 'Monospace 10';
/* Imports...feel free to add here as needed */
/* Imports...feel free to add here as needed */
var commandHeader = "const Clutter = imports.gi.Clutter; " +
"const GLib = imports.gi.GLib; " +
"const Gtk = imports.gi.Gtk; " +
@ -35,7 +25,6 @@ var commandHeader = "const Clutter = imports.gi.Clutter; " +
"const Tweener = imports.ui.tweener; " +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
"const global = Shell.Global.get(); " +
"const stage = global.stage; " +
"const color = function(pixel) { let c= new Clutter.Color(); c.from_pixel(pixel); return c; }; " +
/* Special lookingGlass functions */
@ -48,7 +37,7 @@ function Notebook() {
Notebook.prototype = {
_init: function() {
this.actor = new Big.Box();
this.actor = new Nbtk.BoxLayout({ vertical: true });
this.tabControls = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 4, padding: 2 });
@ -59,21 +48,24 @@ Notebook.prototype = {
appendPage: function(name, child) {
let labelOuterBox = new Big.Box({ padding: 2 });
let labelBox = new Big.Box({ padding: 2, border_color: MATRIX_GREEN,
reactive: true });
let labelBox = new Nbtk.BoxLayout({ reactive: true });
labelOuterBox.append(labelBox, Big.BoxPackFlags.NONE);
let label = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
text: name });
let label = new Nbtk.Label({ text: name });
labelBox.connect('button-press-event', Lang.bind(this, function () {
this.selectChild(child);
return true;
}));
labelBox.append(label, Big.BoxPackFlags.EXPAND);
this._tabs.push([child, labelBox]);
child.hide();
this.actor.append(child, Big.BoxPackFlags.EXPAND);
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);
},
@ -81,10 +73,10 @@ Notebook.prototype = {
_unselect: function() {
if (this._selectedIndex < 0)
return;
let [child, labelBox] = this._tabs[this._selectedIndex];
let [child, labelBox, scrollview] = this._tabs[this._selectedIndex];
labelBox.padding = 2;
labelBox.border = 0;
child.hide();
scrollview.hide();
this._selectedIndex = -1;
},
@ -96,10 +88,10 @@ Notebook.prototype = {
this.emit('selection', null);
return;
}
let [child, labelBox] = this._tabs[index];
let [child, labelBox, scrollview] = this._tabs[index];
labelBox.padding = 1;
labelBox.border = 1;
child.show();
scrollview.show();
this._selectedIndex = index;
this.emit('selection', child);
},
@ -109,7 +101,7 @@ Notebook.prototype = {
this.selectIndex(-1);
else {
for (let i = 0; i < this._tabs.length; i++) {
let [tabChild, labelBox] = this._tabs[i];
let [tabChild, labelBox, scrollview] = this._tabs[i];
if (tabChild == child) {
this.selectIndex(i);
return;
@ -131,20 +123,19 @@ Result.prototype = {
this.actor = new Big.Box();
let cmdTxt = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
ellipsize: Pango.EllipsizeMode.END,
text: command });
let cmdTxt = new Nbtk.Label({ text: command });
cmdTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(cmdTxt, Big.BoxPackFlags.NONE);
let resultTxt = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
ellipsize: Pango.EllipsizeMode.END,
text: "r(" + index + ") = " + o });
let resultTxt = new Nbtk.Label({ text: "r(" + index + ") = " + o });
resultTxt.ellipsize = Pango.EllipsizeMode.END;
this.actor.append(resultTxt, Big.BoxPackFlags.NONE);
let line = new Big.Box({ border_color: GREY,
border_bottom: 1,
height: 8 });
this.actor.append(line, Big.BoxPackFlags.NONE);
let line = new Clutter.Rectangle({ name: "Separator",
height: 1 });
let padBin = new Nbtk.Bin({ name: "Separator", x_fill: true, y_fill: true });
padBin.add_actor(line);
this.actor.append(padBin, Big.BoxPackFlags.NONE);
}
}
@ -159,17 +150,14 @@ ActorHierarchy.prototype = {
this._parentList = [];
this.actor = new Big.Box({ spacing: 4,
border: 1,
padding: 4,
border_color: GREY });
this.actor = new Nbtk.BoxLayout({ name: "ActorHierarchy", vertical: true });
},
setTarget: function(actor) {
this._previousTarget = this._target;
this.target = actor;
this.actor.remove_all();
this.actor.get_children().forEach(function (child) { child.destroy(); });
if (!(actor instanceof Clutter.Actor))
return;
@ -182,11 +170,9 @@ ActorHierarchy.prototype = {
while ((parent = parent.get_parent()) != null) {
this._parentList.push(parent);
let link = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
reactive: true,
text: "" + parent });
this.actor.append(link, Big.BoxPackFlags.IF_FITS);
let link = new 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);
@ -215,16 +201,13 @@ PropertyInspector.prototype = {
this._parentList = [];
this.actor = new Big.Box({ spacing: 4,
border: 1,
padding: 4,
border_color: GREY });
this.actor = new Nbtk.BoxLayout({ name: "PropertyInspector", vertical: true });
},
setTarget: function(actor) {
this.target = actor;
this.actor.remove_all();
this.actor.get_children().forEach(function (child) { child.destroy(); });
for (let propName in actor) {
let valueStr;
@ -234,11 +217,9 @@ PropertyInspector.prototype = {
valueStr = '<error>';
}
let propText = propName + ": " + valueStr;
let propDisplay = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
reactive: true,
text: propText });
this.actor.append(propDisplay, Big.BoxPackFlags.IF_FITS);
let propDisplay = new Nbtk.Label({ reactive: true,
text: propText });
this.actor.add_actor(propDisplay);
}
}
}
@ -249,22 +230,17 @@ function Inspector() {
Inspector.prototype = {
_init: function() {
let global = Shell.Global.get();
let width = 150;
let eventHandler = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
border: 1,
border_color: LG_BORDER_COLOR,
corner_radius: 4,
y: global.stage.height/2,
reactive: true
});
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 Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT, text: '' });
eventHandler.append(displayText, Big.BoxPackFlags.EXPAND);
let displayText = new Nbtk.Label();
eventHandler.add(displayText, { expand: true });
let borderPaintTarget = null;
let borderPaintId = null;
@ -274,7 +250,6 @@ Inspector.prototype = {
}));
eventHandler.connect('button-press-event', Lang.bind(this, function (actor, event) {
let global = Shell.Global.get();
Clutter.ungrab_pointer(eventHandler);
let [stageX, stageY] = event.get_coords();
@ -288,7 +263,6 @@ Inspector.prototype = {
}));
eventHandler.connect('motion-event', Lang.bind(this, function (actor, event) {
let global = Shell.Global.get();
let [stageX, stageY] = event.get_coords();
let target = global.stage.get_actor_at_pos(Clutter.PickMode.ALL,
stageX,
@ -312,8 +286,6 @@ function LookingGlass() {
LookingGlass.prototype = {
_init : function() {
let global = Shell.Global.get();
this._idleHistorySaveId = 0;
let historyPath = global.configdir + "/lookingglass-history.txt";
this._historyFile = Gio.file_new_for_path(historyPath);
@ -327,29 +299,26 @@ LookingGlass.prototype = {
this._offset = 0;
this._results = [];
// TODO replace with scrolling or something better
this._maxItems = 10;
// Sort of magic, but...eh.
this._maxItems = 150;
this.actor = new 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();
this.actor = new Big.Box({ background_color: LG_BACKGROUND_COLOR,
border: 1,
border_color: LG_BORDER_COLOR,
corner_radius: 4,
padding_top: 8,
padding_left: 4,
padding_right: 4,
padding_bottom: 4,
spacing: 4,
visible: false
});
global.stage.add_actor(this.actor);
let toolbar = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
border: 1, border_color: GREY,
corner_radius: 4 });
this.actor.append(toolbar, Big.BoxPackFlags.NONE);
let toolbar = new 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.append(inspectIcon, Big.BoxPackFlags.NONE);
toolbar.add_actor(inspectIcon);
inspectIcon.reactive = true;
inspectIcon.connect('button-press-event', Lang.bind(this, function () {
let inspector = new Inspector();
@ -367,32 +336,27 @@ LookingGlass.prototype = {
}));
let notebook = new Notebook();
this.actor.append(notebook.actor, Big.BoxPackFlags.EXPAND);
toolbar.append(notebook.tabControls, Big.BoxPackFlags.END);
this.actor.add(notebook.actor, { expand: true });
this._evalBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: 4 });
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.append(this._resultsArea, Big.BoxPackFlags.EXPAND);
this._evalBox.add(this._resultsArea, { expand: true });
let entryArea = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
this._evalBox.append(entryArea, Big.BoxPackFlags.NONE);
this._evalBox.add_actor(entryArea);
let label = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
text: 'js>>> ' });
let label = new Nbtk.Label({ text: 'js>>> ' });
entryArea.append(label, Big.BoxPackFlags.NONE);
this._entry = new Clutter.Text({ color: MATRIX_GREEN,
font_name: MATRIX_FONT,
editable: true,
activatable: true,
singleLineMode: true,
text: ''});
/* kind of a hack */
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);
@ -409,7 +373,7 @@ LookingGlass.prototype = {
notebook.selectIndex(0);
}));
this._entry.connect('activate', Lang.bind(this, function (o, e) {
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.
@ -422,8 +386,8 @@ LookingGlass.prototype = {
this._historyNavIndex = -1;
return true;
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = Shell.get_event_key_symbol(e);
this._entry.clutter_text.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
@ -452,6 +416,19 @@ LookingGlass.prototype = {
}));
},
_updateFont: function() {
let gconf = Shell.GConf.get_default();
let fontName = gconf.get_string("/desktop/gnome/interface/monospace_font_name");
// This is mishandled by the scanner - should by Pango.FontDescription_from_string(fontName);
// https://bugzilla.gnome.org/show_bug.cgi?id=595889
let fontDesc = Pango.Font.description_from_string(fontName);
// We ignore everything but size and style; you'd be crazy to set your system-wide
// monospace font to be bold/oblique/etc. Could easily be added here.
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
},
_readHistory: function () {
if (!this._historyFile.query_exists(null))
return;
@ -524,8 +501,7 @@ LookingGlass.prototype = {
},
_resizeTo: function(actor) {
let stage = Shell.Global.get().stage;
let stageWidth = stage.width;
let stage = global.stage;
let myWidth = stage.width * 0.7;
let myHeight = stage.height * 0.7;
let [srcX, srcY] = actor.get_transformed_position();
@ -555,10 +531,7 @@ LookingGlass.prototype = {
Tweener.removeTweens(this.actor);
if (!Main.startModal())
return;
let global = Shell.Global.get();
Main.pushModal(this.actor);
global.stage.set_key_focus(this._entry);
Tweener.addTween(this.actor, { time: 0.5,
@ -575,7 +548,7 @@ LookingGlass.prototype = {
this._open = false;
Tweener.removeTweens(this.actor);
Main.endModal();
Main.popModal(this.actor);
Tweener.addTween(this.actor, { time: 0.5,
transition: "easeOutQuad",

View File

@ -3,19 +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();
@ -24,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();
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
@ -46,25 +62,27 @@ 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 == null) {
runDialog = new RunDialog.RunDialog();
}
runDialog.open();
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) {
recorder = new Shell.Recorder({ stage: global.stage });
@ -77,15 +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
@ -93,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++) {
@ -116,27 +141,136 @@ 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() {
@ -147,8 +281,14 @@ function createLookingGlass() {
return lookingGlass;
}
function getRunDialog() {
if (runDialog == null) {
runDialog = new RunDialog.RunDialog();
}
return runDialog;
}
function createAppLaunchContext() {
let global = Shell.Global.get();
let screen = global.screen;
let display = screen.get_display();

View File

@ -19,14 +19,14 @@ const Dash = imports.ui.dash;
const Tweener = imports.ui.tweener;
const Workspaces = imports.ui.workspaces;
const ROOT_OVERLAY_COLOR = new Clutter.Color();
ROOT_OVERLAY_COLOR.from_pixel(0x000000ff);
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
// Time for initial animation going into overlay mode
// 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 overlay components, such as the side panel
// 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,
@ -73,17 +73,14 @@ const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
let addRemoveButtonSize = null;
function Overlay() {
function Overview() {
this._init();
}
Overlay.prototype = {
Overview.prototype = {
_init : function() {
let me = this;
let global = Shell.Global.get();
this._group = new Clutter.Group();
this._group._delegate = this;
@ -95,21 +92,29 @@ Overlay.prototype = {
this._activeDisplayPane = null;
// Used to catch any clicks when we have an active pane; see the comments
// During transitions, we raise this to the top to avoid having the overview
// area be reactive; it causes too many issues such as double clicks on
// Dash elements, or mouseover handlers in the workspaces.
this._coverPane = new Clutter.Rectangle({ opacity: 0,
reactive: true });
this._group.add_actor(this._coverPane);
this._coverPane.connect('event', Lang.bind(this, function (actor, event) { return true; }));
// Similar to the cover pane but used for dialogs ("panes"); see the comments
// in addPane below.
this._transparentBackground = new Clutter.Rectangle({ opacity: 0,
reactive: true });
this._group.add_actor(this._transparentBackground);
// Background color for the overlay
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERLAY_COLOR });
// 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(displayGridColumnWidth);
this._dash = new Dash.Dash();
this._group.add_actor(this._dash.actor);
// Container to hold popup pane chrome.
@ -127,14 +132,12 @@ Overlay.prototype = {
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._repositionChildren();
this._coverPane.lower_bottom();
this._workspaces = null;
},
_recalculateGridSizes: function () {
let global = Shell.Global.get();
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO);
// We divide the screen into an imaginary grid which helps us determine the layout of
@ -148,29 +151,56 @@ Overlay.prototype = {
}
},
_repositionChildren: function () {
let global = Shell.Global.get();
relayout: function () {
let screenHeight = global.screen_height;
let screenWidth = global.screen_width;
let contentHeight = global.screen_height - Panel.PANEL_HEIGHT;
let contentY = Panel.PANEL_HEIGHT;
let contentHeight = screenHeight - contentY;
this._dash.actor.set_position(0, Panel.PANEL_HEIGHT);
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;
this._backOver.set_position(0, Panel.PANEL_HEIGHT);
// 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,
Panel.PANEL_HEIGHT);
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) {
pane.actor.width = displayGridColumnWidth * 2;
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.
@ -179,6 +209,7 @@ Overlay.prototype = {
let backgroundEventId = null;
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (isOpen) {
pane.actor.width = displayGridColumnWidth * 2;
this._activeDisplayPane = pane;
this._transparentBackground.raise_top();
this._paneContainer.raise_top();
@ -203,11 +234,11 @@ Overlay.prototype = {
//// Draggable target interface ////
// Closes any active panes if a GenericDisplayItem is being
// dragged over the overlay, i.e. as soon as it starts being dragged.
// 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.WellDisplayItem) {
|| source instanceof AppDisplay.BaseWellItem) {
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
return true;
@ -218,108 +249,130 @@ Overlay.prototype = {
//// 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;
if (!Main.startModal())
return;
Main.pushModal(this._dash.actor);
this.visible = true;
this.animationInProgress = true;
let global = Shell.Global.get();
let screenWidth = global.screen_width;
let screenHeight = global.screen_height;
this._dash.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);
/* 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 overlay is displayed greatly
// increases performance of the overlay especially when there are many
// 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 overlay rather than
// 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();
// 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 Dash just before the top workspace fully
// slides in on the top. Which means that we have more time to wait before
// drawing the dash 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 dash. The clipping is removed in this._showDone().
this._dash.actor.set_clip(0, 0,
this._workspaces.getFullSizeX(),
this._dash.actor.height);
Tweener.addTween(this._dash.actor,
{ clipWidthRight: this._dash._width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
// 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,
transition: "easeOutQuad",
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() {
hide: function() {
if (!this.visible || this._hideInProgress)
return;
let global = Shell.Global.get();
this.animationInProgress = true;
this._hideInProgress = true;
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
// lower the panes, so that workspaces display is on top while sliding out
this._dash.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 Dash 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._dash.actor.set_clip(0, 0,
this._dash.actor.width + WORKSPACE_GRID_PADDING + this._workspaces.getWidthToTopActiveWorkspace(),
this._dash.actor.height);
Tweener.addTween(this._dash.actor,
{ clipWidthRight: this._workspaces.getFullSizeX() + this._workspaces.getWidthToTopActiveWorkspace() - global.screen_width,
// 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,
transition: "easeOutQuad",
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');
},
@ -330,6 +383,18 @@ Overlay.prototype = {
this.show();
},
/**
* getWorkspacesForWindow:
* @metaWindow: A #MetaWindow
*
* Returns the Workspaces object associated with the given window.
* This method is not be accessible if the overview is not open
* and will return %null.
*/
getWorkspacesForWindow: function(metaWindow) {
return this._workspaces;
},
/**
* activateWindow:
* @metaWindow: A #MetaWindow
@ -337,45 +402,31 @@ Overlay.prototype = {
*
* 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 overlay is currently active;
* 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.activateWindowFromOverlay(metaWindow, time);
this.hide();
this._workspaces.activateWindowFromOverview(metaWindow, time);
},
//// Private methods ////
// Raises the Dash 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 Dash.
_showDone: function() {
if (this._hideInProgress)
return;
this._dash.actor.raise_top();
this._dash.actor.remove_clip();
this.animationInProgress = false;
this._coverPane.lower_bottom();
this.emit('shown');
},
_hideDone: function() {
let global = Shell.Global.get();
global.window_group.show();
this._workspaces.destroy();
this._workspaces = null;
this._dash.actor.remove_clip();
this._dash.hide();
this._group.hide();
@ -383,41 +434,47 @@ Overlay.prototype = {
this.animationInProgress = false;
this._hideInProgress = false;
Main.endModal();
this._coverPane.lower_bottom();
Main.popModal(this._dash.actor);
this.emit('hidden');
},
_addNewWorkspace: function() {
global.screen.append_new_workspace(false, global.screen.get_display().get_current_time());
},
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
this._addNewWorkspace();
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
}
};
Signals.addSignalMethods(Overlay.prototype);
Signals.addSignalMethods(Overview.prototype);
Tweener.registerSpecialProperty("clipHeightBottom", _clipHeightBottomGet, _clipHeightBottomSet);
function _clipHeightBottomGet(actor) {
let [xOffset, yOffset, clipWidth, clipHeight] = actor.get_clip();
return clipHeight;
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
}
function _clipHeightBottomSet(actor, clipHeight) {
actor.set_clip(0, 0, actor.width, clipHeight);
}
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;
Tweener.registerSpecialProperty("clipHeightTop", _clipHeightTopGet, _clipHeightTopSet);
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);
},
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);
}
// Draggable target interface
acceptDrop: function(source, actor, x, y, time) {
return this._acceptDropCallback(source, actor, x, y, time);
}
};

View File

@ -8,6 +8,9 @@ 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;
@ -15,10 +18,19 @@ const Main = imports.ui.main;
const PANEL_HEIGHT = 26;
const TRAY_HEIGHT = PANEL_HEIGHT - 1;
const PANEL_BACKGROUND_COLOR = new Clutter.Color();
PANEL_BACKGROUND_COLOR.from_pixel(0x000000ff);
const DEFAULT_PADDING = 4;
const PANEL_ICON_SIZE = 24;
const BACKGROUND_TOP = new Clutter.Color();
BACKGROUND_TOP.from_pixel(0x161616ff);
const BACKGROUND_BOTTOM = new Clutter.Color();
BACKGROUND_BOTTOM.from_pixel(0x000000ff);
const PANEL_FOREGROUND_COLOR = new Clutter.Color();
PANEL_FOREGROUND_COLOR.from_pixel(0xffffffff);
const SN_BACKGROUND_COLOR = new Clutter.Color();
SN_BACKGROUND_COLOR.from_pixel(0xffff00a0);
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
@ -47,85 +59,272 @@ 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);
// backBox contains the panel background and the clock.
let backBox = new Big.Box({ width: global.screen_width,
height: PANEL_HEIGHT,
backgroundColor: PANEL_BACKGROUND_COLOR,
x_align: Big.BoxAlignment.CENTER });
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, PANEL_FOREGROUND_COLOR, true, null, PANEL_HEIGHT, DEFAULT_FONT);
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 hotCorner = new Clutter.Rectangle({ width: 1,
height: 1,
opacity: 0,
reactive: true });
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);
}));
/* 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.
hotCorner.connect('enter-event',
Lang.bind(this, this._onHotCornerTriggered));
hotCorner.connect('button-release-event',
Lang.bind(this, this._onHotCornerTriggered));
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));
box.add_actor(hotCorner);
this._leftBox.append(this._hotCornerEnvirons, Big.BoxPackFlags.FIXED);
this._leftBox.append(this._hotCorner, Big.BoxPackFlags.FIXED);
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,
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();
});
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 clockbox = new Big.Box({ y_align: Big.BoxAlignment.CENTER,
padding_left: 4,
padding_right: 4 });
clockbox.append(this._clock, Big.BoxPackFlags.NONE);
backBox.append(clockbox, Big.BoxPackFlags.EXPAND);
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,
@ -164,22 +363,58 @@ Panel.prototype = {
}));
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();
@ -213,15 +448,40 @@ Panel.prototype = {
displayDate.setMinutes(displayDate.getMinutes() + 1);
msecRemaining += 60000;
}
this._clock.set_text(displayDate.toLocaleFormat("%a %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;
},
_onHotCornerTriggered : function() {
if (!Main.overlay.animationInProgress) {
Main.overlay.toggle();
_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;
}
};

View File

@ -10,30 +10,61 @@ 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;
function PlaceDisplay(name, icon, onActivate) {
this._init(name, icon, onActivate);
/**
* 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, iconTexture, onActivate) {
_init : function(name, iconFactory, onActivate) {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
reactive: true,
spacing: 4 });
this.actor.connect('button-press-event', Lang.bind(this, function (b, e) {
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 });
this.actor.append(iconTexture, Big.BoxPackFlags.NONE);
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);
@ -49,6 +80,9 @@ Places.prototype = {
this._menuBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._menuBox, Big.BoxPackFlags.EXPAND);
this._devBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this._dirsBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PLACES_VSPACING });
this.actor.append(this._dirsBox, Big.BoxPackFlags.EXPAND);
@ -57,14 +91,33 @@ Places.prototype = {
let homeUri = homeFile.get_uri();
let homeLabel = Shell.util_get_label_for_uri (homeUri);
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
let homeTexture = Shell.TextureCache.get_default().load_gicon(homeIcon, PLACES_ICON_SIZE);
let home = new PlaceDisplay(homeLabel, homeTexture, Lang.bind(this, function() {
Main.overlay.hide();
Gio.app_info_launch_default_for_uri(homeUri, Main.createAppLaunchContext());
}));
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');
@ -77,31 +130,35 @@ Places.prototype = {
}
if (networkApp != null) {
let networkIcon = networkApp.create_icon_texture(PLACES_ICON_SIZE);
let network = new PlaceDisplay(networkApp.get_name(), networkIcon, Lang.bind(this, function () {
Main.overlay.hide();
networkApp.launch();
}));
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 connectIcon = Shell.TextureCache.get_default().load_icon_name("applications-internet", PLACES_ICON_SIZE);
let connect = new PlaceDisplay('Connect to...', connectIcon, Lang.bind(this, function () {
Main.overlay.hide();
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
}));
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);
let timeoutId = 0;
this._bookmarkTimeoutId = 0;
monitor.connect('changed', Lang.bind(this, function () {
if (timeoutId > 0)
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
timeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._timeoutId = 0;
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
}));
@ -114,6 +171,9 @@ Places.prototype = {
this._dirsBox.remove_all();
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
return;
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
if (!success)
@ -147,13 +207,72 @@ Places.prototype = {
if (label == null)
continue;
let icon = Shell.util_get_icon_for_uri(bookmark);
let iconTexture = Shell.TextureCache.get_default().load_gicon(icon, PLACES_ICON_SIZE);
let item = new PlaceDisplay(label, iconTexture, Lang.bind(this, function() {
Main.overlay.hide();
Gio.app_info_launch_default_for_uri(bookmark, Main.createAppLaunchContext());
}));
let item = new PlaceDisplay(label,
function() {
return Shell.TextureCache.get_default().load_gicon(icon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(bookmark, Main.createAppLaunchContext());
});
this._dirsBox.append(item.actor, Big.BoxPackFlags.NONE);
}
},
_updateDevices: function() {
this._devBox.remove_all();
/* first go through all connected drives */
let drives = this._volumeMonitor.get_connected_drives();
for (let i = 0; i < drives.length; i++) {
let volumes = drives[i].get_volumes();
for(let j = 0; j < volumes.length; j++) {
let mount = volumes[j].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
}
/* add all volumes that is not associated with a drive */
let volumes = this._volumeMonitor.get_volumes();
for(let i = 0; i < volumes.length; i++) {
if(volumes[i].get_drive() != null)
continue;
let mount = volumes[i].get_mount();
if(mount != null) {
this._addMount(mount);
}
}
/* add mounts that have no volume (/etc/mtab mounts, ftp, sftp,...) */
let mounts = this._volumeMonitor.get_mounts();
for(let i = 0; i < mounts.length; i++) {
if(mounts[i].is_shadowed())
continue;
if(mounts[i].get_volume())
continue;
this._addMount(mounts[i]);
}
},
_addMount: function(mount) {
let mountLabel = mount.get_name();
let mountIcon = mount.get_icon();
let root = mount.get_root();
let mountUri = root.get_uri();
let devItem = new PlaceDisplay(mountLabel,
function() {
return Shell.TextureCache.get_default().load_gicon(mountIcon, PLACES_ICON_SIZE);
},
function() {
Gio.app_info_launch_default_for_uri(mountUri, Main.createAppLaunchContext());
});
this._devBox.append(devItem.actor, Big.BoxPackFlags.NONE);
}
};
Signals.addSignalMethods(Places.prototype);

View File

@ -2,10 +2,14 @@
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;
@ -18,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();
@ -27,18 +33,31 @@ function RunDialog() {
RunDialog.prototype = {
_init : function() {
let global = Shell.Global.get();
this._isOpen = false;
let gconf = Shell.GConf.get_default();
gconf.connect('changed', Lang.bind(this, function (gconf, key) {
if (key == 'development_tools')
this._enableInternalCommands = gconf.get_bool('development_tools');
}));
this._enableInternalCommands = gconf.get_boolean('development_tools');
this._internalCommands = { 'lg':
Lang.bind(this, function() {
Mainloop.idle_add(function() { Main.createLookingGlass().open(); });
Main.createLookingGlass().open();
}),
'restart': Lang.bind(this, function() {
let global = Shell.Global.get();
'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);
})
};
@ -54,45 +73,77 @@ RunDialog.prototype = {
reactive: true });
this._group.add_actor(this._overlay);
let boxGroup = new Clutter.Group();
boxGroup.set_position((global.screen_width - BOX_WIDTH) / 2,
(global.screen_height - BOX_HEIGHT) / 2);
this._group.add_actor(boxGroup);
let boxH = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
width: global.screen_width,
height: global.screen_height });
let box = new Big.Box({ background_color: BOX_BACKGROUND_COLOR,
corner_radius: 4,
reactive: false,
width: BOX_WIDTH,
height: BOX_HEIGHT
});
boxGroup.add_actor(box);
this._group.add_actor(boxH);
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
boxH.append(boxV, Big.BoxPackFlags.NONE);
let dialogBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
background_color: BOX_BACKGROUND_COLOR,
corner_radius: 4,
reactive: false,
padding: DIALOG_PADDING,
width: DIALOG_WIDTH });
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans',
text: 'Please enter a command:' });
label.set_position(6, 6);
boxGroup.add_actor(label);
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 });
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
this._errorBox = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: DIALOG_PADDING });
dialogBox.append(this._errorBox, Big.BoxPackFlags.EXPAND);
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER,
x_align: Big.BoxAlignment.CENTER,
width: ICON_BOX_SIZE,
height: ICON_BOX_SIZE });
this._errorBox.append(iconBox, Big.BoxPackFlags.NONE);
this._commandError = false;
let errorIcon = Shell.TextureCache.get_default().load_icon_name("gtk-dialog-error", ICON_SIZE);
iconBox.append(errorIcon, Big.BoxPackFlags.EXPAND);
this._errorMessage = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans Bold',
line_wrap: true });
this._errorBox.append(this._errorMessage, Big.BoxPackFlags.EXPAND);
this._errorBox.hide();
this._entry.connect('activate', Lang.bind(this, function (o, e) {
this._run(o.get_text());
this.close();
return false;
if (!this._commandError)
this.close();
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = Shell.get_event_key_symbol(e);
let symbol = e.get_key_symbol();
if (symbol == Clutter.Escape) {
this.close();
return true;
@ -102,16 +153,31 @@ RunDialog.prototype = {
},
_run : function(command) {
let f = this._internalCommands[command];
let f;
if (this._enableInternalCommands)
f = this._internalCommands[command];
else
f = null;
if (f) {
f();
} else if (command) {
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();
}
}
},
@ -120,13 +186,10 @@ RunDialog.prototype = {
if (this._isOpen) // Already shown
return;
if (!Main.startModal())
return;
this._isOpen = true;
this._group.show();
let global = Shell.Global.get();
Main.pushModal(this._group);
global.stage.set_key_focus(this._entry);
},
@ -136,10 +199,13 @@ RunDialog.prototype = {
this._isOpen = false;
this._errorBox.hide();
this._commandError = false;
this._group.hide();
this._entry.text = '';
Main.endModal();
Main.popModal(this._group);
}
};
Signals.addSignalMethods(RunDialog.prototype);

View File

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

View File

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

View File

@ -9,6 +9,8 @@ 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 DocInfo = imports.misc.docInfo;
@ -156,11 +158,11 @@ 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();
Shell.draw_clock(this.collapsedActor,
time.getHours() % 12,
time.getMinutes());
@ -311,7 +313,7 @@ AppsWidget.prototype = {
_init : function() {
Widget.prototype._init.apply(this, arguments);
this.title = "Applications";
this.title = _("Applications");
this.actor = new Big.Box({ spacing: 2 });
this.collapsedActor = new Big.Box({ spacing: 2});
@ -336,7 +338,7 @@ RecentDocsWidget.prototype = {
_init : function() {
Widget.prototype._init.apply(this, arguments);
this.title = "Recent Documents";
this.title = _("Recent Documents");
this.actor = new Big.Box({ spacing: 2 });
this._recentManager = Gtk.RecentManager.get_default();

View File

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

View File

@ -1,9 +1,9 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const AltTab = imports.ui.altTab;
const Main = imports.ui.main;
@ -17,10 +17,8 @@ function WindowManager() {
WindowManager.prototype = {
_init : function() {
let me = this;
let shellwm = global.window_manager;
this._global = Shell.Global.get();
this._shellwm = this._global.window_manager;
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
@ -28,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

@ -36,18 +36,18 @@ stamp-big-enum-types.h: $(big_source_h) big/big-enum-types.h.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/big/big-enum-types.h.in \
$(big_source_h) ) >> xgen-teth && \
(cmp -s 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
$(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,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
$(AM_V_GEN) $(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
$(AM_V_GEN) (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
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/tidy/tidy-enum-types.h.in \
$(tidy_source_h) ) >> xgen-teth && \
(cmp -s 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
$(AM_V_GEN) ( 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

@ -1,9 +1,12 @@
NULL =
BUILT_SOURCES =
CLEANFILES =
EXTRA_DIST =
EXTRA_DIST =
libexec_PROGRAMS =
noinst_LTLIBRARIES =
noinst_LTLIBRARIES =
noinst_PROGRAMS =
.AUTOPARALLEL:
bin_SCRIPTS = gnome-shell
@ -14,21 +17,24 @@ gnome-shell: gnome-shell.in
-e "s|@libexecdir[@]|$(libexecdir)|" \
-e "s|@libdir[@]|$(libdir)|" \
-e "s|@pkgdatadir[@]|$(pkgdatadir)|" \
-e "s|@PYTHON[@]|$(PYTHON)|" \
-e "s|@sysconfdir[@]|$(sysconfdir)|" \
$< > $@ && chmod a+x $@
CLEANFILES += gnome-shell
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
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,6 +63,8 @@ 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 \
@ -70,6 +78,8 @@ libgnome_shell_la_SOURCES = \
shell-generic-container.h \
shell-gtk-embed.c \
shell-gtk-embed.h \
shell-menu.c \
shell-menu.h \
shell-overflow-list.c \
shell-overflow-list.h \
shell-process.c \
@ -89,7 +99,7 @@ libgnome_shell_la_SOURCES = \
shell-wm.c \
shell-wm.h
non_gir_sources = \
non_gir_sources = \
shell-embedded-window-private.h
shell_recorder_sources = \
@ -107,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)
@ -118,7 +128,7 @@ 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
@ -126,9 +136,9 @@ stamp-shell-marshal.h: Makefile shell-marshal.list
$(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
@ -136,32 +146,35 @@ shell-marshal.c: Makefile shell-marshal.list
$(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
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-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)) \
@ -172,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
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Tidy \
--nsversion=1.0 \
--include=Clutter-1.0 \
--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
$(AM_V_GEN) $(G_IR_SCANNER) \
--namespace=Big \
--nsversion=1.0 \
--include=Clutter-1.0 \
--include=GdkPixbuf-2.0 \
--libtool="$(LIBTOOL)" \
--program=mutter \
--program-arg=--mutter-plugins=$$(pwd)/libgnome-shell.la \
$(addprefix $(srcdir)/,$(big_source_h)) \
@ -209,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

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

@ -26,7 +26,8 @@
#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>
@ -239,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)));

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

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!@PYTHON@
import atexit
import optparse
@ -13,44 +13,6 @@ import tempfile
import termios
import time
import errno
import dbus
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.")
@ -190,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
@ -207,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");
@ -227,27 +227,6 @@ elif options.debug:
if options.wide:
options.geometry = "1280x800"
metacity_pid = pidof("metacity")
compiz_pid = pidof("compiz.real") or pidof("compiz")
# In Gnome 2.26 the panel grabs a dbus name and allows replacement; use that.
bus = dbus.Interface(dbus.SessionBus().get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'),
'org.freedesktop.DBus')
names = bus.ListNames()
gnome_panel_dbus = 'org.gnome.Panel' in names
if gnome_panel_dbus:
gnome_panel_pid = None
else:
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.
@ -258,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"
@ -268,23 +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()
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'
start_shell()
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:
@ -292,29 +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
# 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("~"))
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_dbus or 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,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 ();
}

94
src/nbtk/nbtk-clipboard.h Normal file
View File

@ -0,0 +1,94 @@
/*
* nbtk-clipboard.h: 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>
*
*/
#ifndef _NBTK_CLIPBOARD_H
#define _NBTK_CLIPBOARD_H
#include <glib-object.h>
G_BEGIN_DECLS
#define NBTK_TYPE_CLIPBOARD nbtk_clipboard_get_type()
#define NBTK_CLIPBOARD(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
NBTK_TYPE_CLIPBOARD, NbtkClipboard))
#define NBTK_CLIPBOARD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
NBTK_TYPE_CLIPBOARD, NbtkClipboardClass))
#define NBTK_IS_CLIPBOARD(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
NBTK_TYPE_CLIPBOARD))
#define NBTK_IS_CLIPBOARD_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
NBTK_TYPE_CLIPBOARD))
#define NBTK_CLIPBOARD_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
NBTK_TYPE_CLIPBOARD, NbtkClipboardClass))
typedef struct _NbtkClipboard NbtkClipboard;
typedef struct _NbtkClipboardClass NbtkClipboardClass;
typedef struct _NbtkClipboardPrivate NbtkClipboardPrivate;
/**
* NbtkClipboard:
*
* The contents of this structure is private and should only be accessed using
* the provided API.
*/
struct _NbtkClipboard
{
/*< private >*/
GObject parent;
NbtkClipboardPrivate *priv;
};
struct _NbtkClipboardClass
{
GObjectClass parent_class;
};
/**
* NbtkClipboardCallbackFunc:
* @clipboard: A #NbtkClipboard
* @text: text from the clipboard
* @user_data: user data
*
* Callback function called when text is retrieved from the clipboard.
*/
typedef void (*NbtkClipboardCallbackFunc) (NbtkClipboard *clipboard,
const gchar *text,
gpointer user_data);
GType nbtk_clipboard_get_type (void);
NbtkClipboard* nbtk_clipboard_get_default (void);
void nbtk_clipboard_get_text (NbtkClipboard *clipboard, NbtkClipboardCallbackFunc callback, gpointer user_data);
void nbtk_clipboard_set_text (NbtkClipboard *clipboard, const gchar *text);
G_END_DECLS
#endif /* _NBTK_CLIPBOARD_H */

897
src/nbtk/nbtk-entry.c Normal file
View File

@ -0,0 +1,897 @@
/*
* nbtk-entry.c: Plain entry actor
*
* 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.
*
* Written by: Thomas Wood <thomas.wood@intel.com>
*
*/
/**
* SECTION:nbtk-entry
* @short_description: Widget for displaying text
*
* #NbtkEntry is a simple widget for displaying text. It derives from
* #NbtkWidget to add extra style and placement functionality over
* #ClutterText. The internal #ClutterText is publicly accessibly to allow
* applications to set further properties.
*
* #NbtkEntry supports the following pseudo style states:
* <itemizedlist>
* <listitem>
* <para>focus: the widget has focus</para>
* </listitem>
* <listitem>
* <para>indeterminate: the widget is showing the hint text</para>
* </listitem>
* </itemizedlist>
*/
#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 <clutter-imcontext/clutter-imtext.h>
#include "nbtk-entry.h"
#include "nbtk-widget.h"
#include "nbtk-texture-cache.h"
#include "nbtk-marshal.h"
#include "nbtk-clipboard.h"
#define HAS_FOCUS(actor) (clutter_actor_get_stage (actor) && clutter_stage_get_key_focus ((ClutterStage *) clutter_actor_get_stage (actor)) == actor)
/* properties */
enum
{
PROP_0,
PROP_CLUTTER_TEXT,
PROP_HINT_TEXT,
PROP_TEXT,
};
/* signals */
enum
{
PRIMARY_ICON_CLICKED,
SECONDARY_ICON_CLICKED,
LAST_SIGNAL
};
#define NBTK_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_ENTRY, NbtkEntryPrivate))
#define NBTK_ENTRY_PRIV(x) ((NbtkEntry *) x)->priv
struct _NbtkEntryPrivate
{
ClutterActor *entry;
gchar *hint;
ClutterActor *primary_icon;
ClutterActor *secondary_icon;
gfloat spacing;
};
static guint entry_signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (NbtkEntry, nbtk_entry, NBTK_TYPE_WIDGET);
static void
nbtk_entry_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NbtkEntry *entry = NBTK_ENTRY (gobject);
switch (prop_id)
{
case PROP_HINT_TEXT:
nbtk_entry_set_hint_text (entry, g_value_get_string (value));
break;
case PROP_TEXT:
nbtk_entry_set_text (entry, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_entry_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (gobject);
switch (prop_id)
{
case PROP_CLUTTER_TEXT:
g_value_set_object (value, priv->entry);
break;
case PROP_HINT_TEXT:
g_value_set_string (value, priv->hint);
break;
case PROP_TEXT:
g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->entry)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_entry_dispose (GObject *object)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object);
if (priv->entry)
{
clutter_actor_unparent (priv->entry);
priv->entry = NULL;
}
}
static void
nbtk_entry_finalize (GObject *object)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (object);
g_free (priv->hint);
priv->hint = NULL;
}
static void
nbtk_entry_style_changed (NbtkWidget *self)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (self);
ShellThemeNode *theme_node;
ClutterColor color;
const PangoFontDescription *font;
gchar *font_string;
theme_node = nbtk_widget_get_theme_node (self);
shell_theme_node_get_foreground_color (theme_node, &color);
clutter_text_set_color (CLUTTER_TEXT (priv->entry), &color);
if (shell_theme_node_get_color (theme_node, "caret-color", FALSE, &color))
clutter_text_set_cursor_color (CLUTTER_TEXT (priv->entry), &color);
if (shell_theme_node_get_color (theme_node, "selection-background-color", FALSE, &color))
clutter_text_set_selection_color (CLUTTER_TEXT (priv->entry), &color);
font = shell_theme_node_get_font (theme_node);
font_string = pango_font_description_to_string (font);
clutter_text_set_font_name (CLUTTER_TEXT (priv->entry), font_string);
g_free (font_string);
NBTK_WIDGET_CLASS (nbtk_entry_parent_class)->style_changed (self);
}
static void
nbtk_entry_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
gfloat icon_w;
shell_theme_node_adjust_for_height (theme_node, &for_height);
clutter_actor_get_preferred_width (priv->entry, for_height,
min_width_p,
natural_width_p);
if (priv->primary_icon)
{
clutter_actor_get_preferred_width (priv->primary_icon, -1, NULL, &icon_w);
if (min_width_p)
*min_width_p += icon_w + priv->spacing;
if (natural_width_p)
*natural_width_p += icon_w + priv->spacing;
}
if (priv->secondary_icon)
{
clutter_actor_get_preferred_width (priv->secondary_icon,
-1, NULL, &icon_w);
if (min_width_p)
*min_width_p += icon_w + priv->spacing;
if (natural_width_p)
*natural_width_p += icon_w + priv->spacing;
}
shell_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
}
static void
nbtk_entry_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
gfloat icon_h;
shell_theme_node_adjust_for_width (theme_node, &for_width);
clutter_actor_get_preferred_height (priv->entry, for_width,
min_height_p,
natural_height_p);
if (priv->primary_icon)
{
clutter_actor_get_preferred_height (priv->primary_icon,
-1, NULL, &icon_h);
if (min_height_p && icon_h > *min_height_p)
*min_height_p = icon_h;
if (natural_height_p && icon_h > *natural_height_p)
*natural_height_p = icon_h;
}
if (priv->secondary_icon)
{
clutter_actor_get_preferred_height (priv->secondary_icon,
-1, NULL, &icon_h);
if (min_height_p && icon_h > *min_height_p)
*min_height_p = icon_h;
if (natural_height_p && icon_h > *natural_height_p)
*natural_height_p = icon_h;
}
shell_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
}
static void
nbtk_entry_allocate (ClutterActor *actor,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
ClutterActorClass *parent_class;
ClutterActorBox content_box, child_box, icon_box;
gfloat icon_w, icon_h;
gfloat entry_h, min_h, pref_h, avail_h;
parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class);
parent_class->allocate (actor, box, flags);
shell_theme_node_get_content_box (theme_node, box, &content_box);
avail_h = content_box.y2 - content_box.y1;
child_box.x1 = content_box.x1;
child_box.x2 = content_box.x2;
if (priv->primary_icon)
{
clutter_actor_get_preferred_width (priv->primary_icon,
-1, NULL, &icon_w);
clutter_actor_get_preferred_height (priv->primary_icon,
-1, NULL, &icon_h);
icon_box.x1 = content_box.x1;
icon_box.x2 = icon_box.x1 + icon_w;
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
icon_box.y2 = icon_box.y1 + icon_h;
clutter_actor_allocate (priv->primary_icon,
&icon_box,
flags);
/* reduce the size for the entry */
child_box.x1 += icon_w + priv->spacing;
}
if (priv->secondary_icon)
{
clutter_actor_get_preferred_width (priv->secondary_icon,
-1, NULL, &icon_w);
clutter_actor_get_preferred_height (priv->secondary_icon,
-1, NULL, &icon_h);
icon_box.x2 = content_box.x2;
icon_box.x1 = icon_box.x2 - icon_w;
icon_box.y1 = (int) (content_box.y1 + avail_h / 2 - icon_h / 2);
icon_box.y2 = icon_box.y1 + icon_h;
clutter_actor_allocate (priv->secondary_icon,
&icon_box,
flags);
/* reduce the size for the entry */
child_box.x2 -= icon_w - priv->spacing;
}
clutter_actor_get_preferred_height (priv->entry, child_box.x2 - child_box.x1,
&min_h, &pref_h);
entry_h = CLAMP (pref_h, min_h, avail_h);
child_box.y1 = (int) (content_box.y1 + avail_h / 2 - entry_h / 2);
child_box.y2 = child_box.y1 + entry_h;
clutter_actor_allocate (priv->entry, &child_box, flags);
}
static void
clutter_text_focus_in_cb (ClutterText *text,
ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
/* remove the hint if visible */
if (priv->hint
&& !strcmp (clutter_text_get_text (text), priv->hint))
{
clutter_text_set_text (text, "");
}
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "focus");
clutter_text_set_cursor_visible (text, TRUE);
}
static void
clutter_text_focus_out_cb (ClutterText *text,
ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
/* add a hint if the entry is empty */
if (priv->hint && !strcmp (clutter_text_get_text (text), ""))
{
clutter_text_set_text (text, priv->hint);
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), "indeterminate");
}
else
{
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (actor), NULL);
}
clutter_text_set_cursor_visible (text, FALSE);
}
static void
nbtk_entry_paint (ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
ClutterActorClass *parent_class;
parent_class = CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class);
parent_class->paint (actor);
clutter_actor_paint (priv->entry);
if (priv->primary_icon)
clutter_actor_paint (priv->primary_icon);
if (priv->secondary_icon)
clutter_actor_paint (priv->secondary_icon);
}
static void
nbtk_entry_pick (ClutterActor *actor,
const ClutterColor *c)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->pick (actor, c);
clutter_actor_paint (priv->entry);
if (priv->primary_icon)
clutter_actor_paint (priv->primary_icon);
if (priv->secondary_icon)
clutter_actor_paint (priv->secondary_icon);
}
static void
nbtk_entry_map (ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv;
CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->map (actor);
clutter_actor_map (priv->entry);
if (priv->primary_icon)
clutter_actor_map (priv->primary_icon);
if (priv->secondary_icon)
clutter_actor_map (priv->secondary_icon);
}
static void
nbtk_entry_unmap (ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY (actor)->priv;
CLUTTER_ACTOR_CLASS (nbtk_entry_parent_class)->unmap (actor);
clutter_actor_unmap (priv->entry);
if (priv->primary_icon)
clutter_actor_unmap (priv->primary_icon);
if (priv->secondary_icon)
clutter_actor_unmap (priv->secondary_icon);
}
static void
nbtk_entry_clipboard_callback (NbtkClipboard *clipboard,
const gchar *text,
gpointer data)
{
ClutterText *ctext = (ClutterText*) ((NbtkEntry *) data)->priv->entry;
gint cursor_pos;
if (!text)
return;
/* delete the current selection before pasting */
clutter_text_delete_selection (ctext);
/* "paste" the clipboard text into the entry */
cursor_pos = clutter_text_get_cursor_position (ctext);
clutter_text_insert_text (ctext, text, cursor_pos);
}
static gboolean
nbtk_entry_key_press_event (ClutterActor *actor,
ClutterKeyEvent *event)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
/* This is expected to handle events that were emitted for the inner
ClutterText. They only reach this function if the ClutterText
didn't handle them */
/* paste */
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
&& event->keyval == CLUTTER_v)
{
NbtkClipboard *clipboard;
clipboard = nbtk_clipboard_get_default ();
nbtk_clipboard_get_text (clipboard, nbtk_entry_clipboard_callback, actor);
return TRUE;
}
/* copy */
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
&& event->keyval == CLUTTER_c)
{
NbtkClipboard *clipboard;
gchar *text;
clipboard = nbtk_clipboard_get_default ();
text = clutter_text_get_selection ((ClutterText*) priv->entry);
if (text && strlen (text))
nbtk_clipboard_set_text (clipboard, text);
return TRUE;
}
/* cut */
if ((event->modifier_state & CLUTTER_CONTROL_MASK)
&& event->keyval == CLUTTER_x)
{
NbtkClipboard *clipboard;
gchar *text;
clipboard = nbtk_clipboard_get_default ();
text = clutter_text_get_selection ((ClutterText*) priv->entry);
if (text && strlen (text))
{
nbtk_clipboard_set_text (clipboard, text);
/* now delete the text */
clutter_text_delete_selection ((ClutterText *) priv->entry);
}
return TRUE;
}
return FALSE;
}
static void
nbtk_entry_key_focus_in (ClutterActor *actor)
{
NbtkEntryPrivate *priv = NBTK_ENTRY_PRIV (actor);
/* We never want key focus. The ClutterText should be given first
pass for all key events */
clutter_actor_grab_key_focus (priv->entry);
}
static void
nbtk_entry_class_init (NbtkEntryClass *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 (NbtkEntryPrivate));
gobject_class->set_property = nbtk_entry_set_property;
gobject_class->get_property = nbtk_entry_get_property;
gobject_class->finalize = nbtk_entry_finalize;
gobject_class->dispose = nbtk_entry_dispose;
actor_class->get_preferred_width = nbtk_entry_get_preferred_width;
actor_class->get_preferred_height = nbtk_entry_get_preferred_height;
actor_class->allocate = nbtk_entry_allocate;
actor_class->paint = nbtk_entry_paint;
actor_class->pick = nbtk_entry_pick;
actor_class->map = nbtk_entry_map;
actor_class->unmap = nbtk_entry_unmap;
actor_class->key_press_event = nbtk_entry_key_press_event;
actor_class->key_focus_in = nbtk_entry_key_focus_in;
widget_class->style_changed = nbtk_entry_style_changed;
pspec = g_param_spec_object ("clutter-text",
"Clutter Text",
"Internal ClutterText actor",
CLUTTER_TYPE_TEXT,
G_PARAM_READABLE);
g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec);
pspec = g_param_spec_string ("hint-text",
"Hint Text",
"Text to display when the entry is not focused "
"and the text property is empty",
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_HINT_TEXT, pspec);
pspec = g_param_spec_string ("text",
"Text",
"Text of the entry",
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
/* signals */
/**
* NbtkEntry::primary-icon-clicked:
*
* Emitted when the primary icon is clicked
*/
entry_signals[PRIMARY_ICON_CLICKED] =
g_signal_new ("primary-icon-clicked",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NbtkEntryClass, primary_icon_clicked),
NULL, NULL,
_nbtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
/**
* NbtkEntry::secondary-icon-clicked:
*
* Emitted when the secondary icon is clicked
*/
entry_signals[SECONDARY_ICON_CLICKED] =
g_signal_new ("secondary-icon-clicked",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NbtkEntryClass, secondary_icon_clicked),
NULL, NULL,
_nbtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
nbtk_entry_init (NbtkEntry *entry)
{
NbtkEntryPrivate *priv;
priv = entry->priv = NBTK_ENTRY_GET_PRIVATE (entry);
priv->entry = g_object_new (CLUTTER_TYPE_IMTEXT,
"line-alignment", PANGO_ALIGN_LEFT,
"editable", TRUE,
"reactive", TRUE,
"single-line-mode", TRUE,
NULL);
g_signal_connect (priv->entry, "key-focus-in",
G_CALLBACK (clutter_text_focus_in_cb), entry);
g_signal_connect (priv->entry, "key-focus-out",
G_CALLBACK (clutter_text_focus_out_cb), entry);
priv->spacing = 6.0f;
clutter_actor_set_parent (priv->entry, CLUTTER_ACTOR (entry));
clutter_actor_set_reactive ((ClutterActor *) entry, TRUE);
/* set cursor hidden until we receive focus */
clutter_text_set_cursor_visible ((ClutterText *) priv->entry, FALSE);
}
/**
* nbtk_entry_new:
* @text: text to set the entry to
*
* Create a new #NbtkEntry with the specified entry
*
* Returns: a new #NbtkEntry
*/
NbtkWidget *
nbtk_entry_new (const gchar *text)
{
NbtkWidget *entry;
/* add the entry to the stage, but don't allow it to be visible */
entry = g_object_new (NBTK_TYPE_ENTRY,
"text", text,
NULL);
return entry;
}
/**
* nbtk_entry_get_text:
* @entry: a #NbtkEntry
*
* Get the text displayed on the entry
*
* Returns: the text for the entry. This must not be freed by the application
*/
G_CONST_RETURN gchar *
nbtk_entry_get_text (NbtkEntry *entry)
{
g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL);
return clutter_text_get_text (CLUTTER_TEXT (entry->priv->entry));
}
/**
* nbtk_entry_set_text:
* @entry: a #NbtkEntry
* @text: text to set the entry to
*
* Sets the text displayed on the entry
*/
void
nbtk_entry_set_text (NbtkEntry *entry,
const gchar *text)
{
NbtkEntryPrivate *priv;
g_return_if_fail (NBTK_IS_ENTRY (entry));
priv = entry->priv;
/* set a hint if we are blanking the entry */
if (priv->hint
&& text && !strcmp ("", text)
&& !HAS_FOCUS (priv->entry))
{
text = priv->hint;
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate");
}
else
{
if (HAS_FOCUS (priv->entry))
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "focus");
else
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), NULL);
}
clutter_text_set_text (CLUTTER_TEXT (priv->entry), text);
g_object_notify (G_OBJECT (entry), "text");
}
/**
* nbtk_entry_get_clutter_text:
* @entry: a #NbtkEntry
*
* Retrieve the internal #ClutterText so that extra parameters can be set
*
* Returns: (transfer none): the #ClutterText used by #NbtkEntry. The entry is
* owned by the #NbtkEntry and should not be unref'ed by the application.
*/
ClutterActor*
nbtk_entry_get_clutter_text (NbtkEntry *entry)
{
g_return_val_if_fail (NBTK_ENTRY (entry), NULL);
return entry->priv->entry;
}
/**
* nbtk_entry_set_hint_text:
* @entry: a #NbtkEntry
* @text: text to set as the entry hint
*
* Sets the text to display when the entry is empty and unfocused. When the
* entry is displaying the hint, it has a pseudo class of "indeterminate".
* A value of NULL unsets the hint.
*/
void
nbtk_entry_set_hint_text (NbtkEntry *entry,
const gchar *text)
{
NbtkEntryPrivate *priv;
g_return_if_fail (NBTK_IS_ENTRY (entry));
priv = entry->priv;
g_free (priv->hint);
priv->hint = g_strdup (text);
if (!strcmp (clutter_text_get_text (CLUTTER_TEXT (priv->entry)), ""))
{
clutter_text_set_text (CLUTTER_TEXT (priv->entry), priv->hint);
nbtk_widget_set_style_pseudo_class (NBTK_WIDGET (entry), "indeterminate");
}
}
/**
* nbtk_entry_get_hint_text:
* @entry: a #NbtkEntry
*
* Gets the text that is displayed when the entry is empty and unfocused
*
* Returns: the current value of the hint property. This string is owned by the
* #NbtkEntry and should not be freed or modified.
*/
G_CONST_RETURN
gchar *
nbtk_entry_get_hint_text (NbtkEntry *entry)
{
g_return_val_if_fail (NBTK_IS_ENTRY (entry), NULL);
return entry->priv->hint;
}
static gboolean
_nbtk_entry_icon_press_cb (ClutterActor *actor,
ClutterButtonEvent *event,
NbtkEntry *entry)
{
NbtkEntryPrivate *priv = entry->priv;
if (actor == priv->primary_icon)
g_signal_emit (entry, entry_signals[PRIMARY_ICON_CLICKED], 0);
else
g_signal_emit (entry, entry_signals[SECONDARY_ICON_CLICKED], 0);
return FALSE;
}
static void
_nbtk_entry_set_icon_from_file (NbtkEntry *entry,
ClutterActor **icon,
const gchar *filename)
{
if (*icon)
{
g_signal_handlers_disconnect_by_func (*icon,
_nbtk_entry_icon_press_cb,
entry);
clutter_actor_unparent (*icon);
*icon = NULL;
}
if (filename)
{
NbtkTextureCache *cache;
cache = nbtk_texture_cache_get_default ();
*icon = (ClutterActor*) nbtk_texture_cache_get_texture (cache, filename, FALSE);
clutter_actor_set_reactive (*icon, TRUE);
clutter_actor_set_parent (*icon, CLUTTER_ACTOR (entry));
g_signal_connect (*icon, "button-release-event",
G_CALLBACK (_nbtk_entry_icon_press_cb), entry);
}
clutter_actor_queue_relayout (CLUTTER_ACTOR (entry));
}
/**
* nbtk_entry_set_primary_icon_from_file:
* @entry: a #NbtkEntry
* @filename: filename of an icon
*
* Set the primary icon of the entry to the given filename
*/
void
nbtk_entry_set_primary_icon_from_file (NbtkEntry *entry,
const gchar *filename)
{
NbtkEntryPrivate *priv;
g_return_if_fail (NBTK_IS_ENTRY (entry));
priv = entry->priv;
_nbtk_entry_set_icon_from_file (entry, &priv->primary_icon, filename);
}
/**
* nbtk_entry_set_secondary_icon_from_file:
* @entry: a #NbtkEntry
* @filename: filename of an icon
*
* Set the primary icon of the entry to the given filename
*/
void
nbtk_entry_set_secondary_icon_from_file (NbtkEntry *entry,
const gchar *filename)
{
NbtkEntryPrivate *priv;
g_return_if_fail (NBTK_IS_ENTRY (entry));
priv = entry->priv;
_nbtk_entry_set_icon_from_file (entry, &priv->secondary_icon, filename);
}

88
src/nbtk/nbtk-entry.h Normal file
View File

@ -0,0 +1,88 @@
/*
* nbtk-entry.h: Plain entry actor
*
* 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: 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_ENTRY_H__
#define __NBTK_ENTRY_H__
G_BEGIN_DECLS
#include <nbtk/nbtk-widget.h>
#define NBTK_TYPE_ENTRY (nbtk_entry_get_type ())
#define NBTK_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_ENTRY, NbtkEntry))
#define NBTK_IS_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_ENTRY))
#define NBTK_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_ENTRY, NbtkEntryClass))
#define NBTK_IS_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_ENTRY))
#define NBTK_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_ENTRY, NbtkEntryClass))
typedef struct _NbtkEntry NbtkEntry;
typedef struct _NbtkEntryPrivate NbtkEntryPrivate;
typedef struct _NbtkEntryClass NbtkEntryClass;
/**
* NbtkEntry:
*
* The contents of this structure is private and should only be accessed using
* the provided API.
*/
struct _NbtkEntry
{
/*< private >*/
NbtkWidget parent_instance;
NbtkEntryPrivate *priv;
};
struct _NbtkEntryClass
{
NbtkWidgetClass parent_class;
/* signals */
void (*primary_icon_clicked) (NbtkEntry *entry);
void (*secondary_icon_clicked) (NbtkEntry *entry);
};
GType nbtk_entry_get_type (void) G_GNUC_CONST;
NbtkWidget * nbtk_entry_new (const gchar *text);
G_CONST_RETURN gchar *nbtk_entry_get_text (NbtkEntry *entry);
void nbtk_entry_set_text (NbtkEntry *entry,
const gchar *text);
ClutterActor* nbtk_entry_get_clutter_text (NbtkEntry *entry);
void nbtk_entry_set_hint_text (NbtkEntry *entry,
const gchar *text);
G_CONST_RETURN gchar *nbtk_entry_get_hint_text (NbtkEntry *entry);
void nbtk_entry_set_primary_icon_from_file (NbtkEntry *entry,
const gchar *filename);
void nbtk_entry_set_secondary_icon_from_file (NbtkEntry *entry,
const gchar *filename);
G_END_DECLS
#endif /* __NBTK_ENTRY_H__ */

View File

@ -1,5 +1,5 @@
/*** BEGIN file-header ***/
#include "tidy-enum-types.h"
#include "nbtk-enum-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
@ -23,7 +23,7 @@ GType
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
enum_type_id = g_@type@_register_static("@EnumName@", values);
enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
}
return enum_type_id;
}

View File

@ -1,6 +1,10 @@
/*** BEGIN file-header ***/
#ifndef __TIDY_ENUM_TYPES_H__
#define __TIDY_ENUM_TYPES_H__
#if !defined(NBTK_H_INSIDE) && !defined(NBTK_COMPILATION)
#error "Only <nbtk/nbtk.h> can be included directly.h"
#endif
#ifndef __NBTK_ENUM_TYPES_H__
#define __NBTK_ENUM_TYPES_H__
#include <glib-object.h>
@ -15,11 +19,11 @@ G_BEGIN_DECLS
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* !__TIDY_ENUM_TYPES_H__ */
#endif /* !__NBTK_ENUM_TYPES_H__ */
/*** END file-tail ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define TIDY_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
#define NBTK_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
/*** END value-header ***/

341
src/nbtk/nbtk-label.c Normal file
View File

@ -0,0 +1,341 @@
/*
* nbtk-label.c: Plain label actor
*
* 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.
*
* Written by: Thomas Wood <thomas@linux.intel.com>
*
*/
/**
* SECTION:nbtk-label
* @short_description: Widget for displaying text
*
* #NbtkLabel is a simple widget for displaying text. It derives from
* #NbtkWidget to add extra style and placement functionality over
* #ClutterText. The internal #ClutterText is publicly accessibly to allow
* applications to set further properties.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <clutter/clutter.h>
#include "nbtk-label.h"
#include "nbtk-widget.h"
enum
{
PROP_0,
PROP_CLUTTER_TEXT,
PROP_TEXT
};
#define NBTK_LABEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), NBTK_TYPE_LABEL, NbtkLabelPrivate))
struct _NbtkLabelPrivate
{
ClutterActor *label;
};
G_DEFINE_TYPE (NbtkLabel, nbtk_label, NBTK_TYPE_WIDGET);
static void
nbtk_label_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
NbtkLabel *label = NBTK_LABEL (gobject);
switch (prop_id)
{
case PROP_TEXT:
nbtk_label_set_text (label, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_label_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
NbtkLabelPrivate *priv = NBTK_LABEL (gobject)->priv;
switch (prop_id)
{
case PROP_CLUTTER_TEXT:
g_value_set_object (value, priv->label);
break;
case PROP_TEXT:
g_value_set_string (value, clutter_text_get_text (CLUTTER_TEXT (priv->label)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
nbtk_label_style_changed (NbtkWidget *self)
{
NbtkLabelPrivate *priv;
ShellThemeNode *theme_node;
ClutterColor color;
const PangoFontDescription *font;
gchar *font_string;
priv = NBTK_LABEL (self)->priv;
theme_node = nbtk_widget_get_theme_node (self);
shell_theme_node_get_foreground_color (theme_node, &color);
clutter_text_set_color (CLUTTER_TEXT (priv->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 (priv->label), font_string);
g_free (font_string);
NBTK_WIDGET_CLASS (nbtk_label_parent_class)->style_changed (self);
}
static void
nbtk_label_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
shell_theme_node_adjust_for_height (theme_node, &for_height);
clutter_actor_get_preferred_width (priv->label, 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_label_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
shell_theme_node_adjust_for_width (theme_node, &for_width);
clutter_actor_get_preferred_height (priv->label, 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_label_allocate (ClutterActor *actor,
const ClutterActorBox *box,
ClutterAllocationFlags flags)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
ShellThemeNode *theme_node = nbtk_widget_get_theme_node (NBTK_WIDGET (actor));
ClutterActorClass *parent_class;
ClutterActorBox content_box;
shell_theme_node_get_content_box (theme_node, box, &content_box);
parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class);
parent_class->allocate (actor, box, flags);
clutter_actor_allocate (priv->label, &content_box, flags);
}
static void
nbtk_label_paint (ClutterActor *actor)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
ClutterActorClass *parent_class;
parent_class = CLUTTER_ACTOR_CLASS (nbtk_label_parent_class);
parent_class->paint (actor);
clutter_actor_paint (priv->label);
}
static void
nbtk_label_map (ClutterActor *actor)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->map (actor);
clutter_actor_map (priv->label);
}
static void
nbtk_label_unmap (ClutterActor *actor)
{
NbtkLabelPrivate *priv = NBTK_LABEL (actor)->priv;
CLUTTER_ACTOR_CLASS (nbtk_label_parent_class)->unmap (actor);
clutter_actor_unmap (priv->label);
}
static void
nbtk_label_class_init (NbtkLabelClass *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 (NbtkLabelPrivate));
gobject_class->set_property = nbtk_label_set_property;
gobject_class->get_property = nbtk_label_get_property;
actor_class->paint = nbtk_label_paint;
actor_class->allocate = nbtk_label_allocate;
actor_class->get_preferred_width = nbtk_label_get_preferred_width;
actor_class->get_preferred_height = nbtk_label_get_preferred_height;
actor_class->map = nbtk_label_map;
actor_class->unmap = nbtk_label_unmap;
widget_class->style_changed = nbtk_label_style_changed;
pspec = g_param_spec_object ("clutter-text",
"Clutter Text",
"Internal ClutterText actor",
CLUTTER_TYPE_TEXT,
G_PARAM_READABLE);
g_object_class_install_property (gobject_class, PROP_CLUTTER_TEXT, pspec);
pspec = g_param_spec_string ("text",
"Text",
"Text of the label",
NULL, G_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
}
static void
nbtk_label_init (NbtkLabel *label)
{
NbtkLabelPrivate *priv;
label->priv = priv = NBTK_LABEL_GET_PRIVATE (label);
label->priv->label = g_object_new (CLUTTER_TYPE_TEXT,
"ellipsize", PANGO_ELLIPSIZE_END,
NULL);
clutter_actor_set_parent (priv->label, CLUTTER_ACTOR (label));
}
/**
* nbtk_label_new:
* @text: text to set the label to
*
* Create a new #NbtkLabel with the specified label
*
* Returns: a new #NbtkLabel
*/
NbtkWidget *
nbtk_label_new (const gchar *text)
{
if (text == NULL || *text == '\0')
return g_object_new (NBTK_TYPE_LABEL, NULL);
else
return g_object_new (NBTK_TYPE_LABEL,
"text", text,
NULL);
}
/**
* nbtk_label_get_text:
* @label: a #NbtkLabel
*
* Get the text displayed on the label
*
* Returns: the text for the label. This must not be freed by the application
*/
G_CONST_RETURN gchar *
nbtk_label_get_text (NbtkLabel *label)
{
g_return_val_if_fail (NBTK_IS_LABEL (label), NULL);
return clutter_text_get_text (CLUTTER_TEXT (label->priv->label));
}
/**
* nbtk_label_set_text:
* @label: a #NbtkLabel
* @text: text to set the label to
*
* Sets the text displayed on the label
*/
void
nbtk_label_set_text (NbtkLabel *label,
const gchar *text)
{
NbtkLabelPrivate *priv;
g_return_if_fail (NBTK_IS_LABEL (label));
g_return_if_fail (text != NULL);
priv = label->priv;
clutter_text_set_text (CLUTTER_TEXT (priv->label), text);
g_object_notify (G_OBJECT (label), "text");
}
/**
* nbtk_label_get_clutter_text:
* @label: a #NbtkLabel
*
* Retrieve the internal #ClutterText so that extra parameters can be set
*
* Returns: (transfer none): ethe #ClutterText used by #NbtkLabel. The label
* is owned by the #NbtkLabel and should not be unref'ed by the application.
*/
ClutterActor*
nbtk_label_get_clutter_text (NbtkLabel *label)
{
g_return_val_if_fail (NBTK_LABEL (label), NULL);
return label->priv->label;
}

75
src/nbtk/nbtk-label.h Normal file
View File

@ -0,0 +1,75 @@
/*
* nbtk-label.h: Plain label actor
*
* 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: 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_LABEL_H__
#define __NBTK_LABEL_H__
G_BEGIN_DECLS
#include <nbtk/nbtk-widget.h>
#define NBTK_TYPE_LABEL (nbtk_label_get_type ())
#define NBTK_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_LABEL, NbtkLabel))
#define NBTK_IS_LABEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_LABEL))
#define NBTK_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_LABEL, NbtkLabelClass))
#define NBTK_IS_LABEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_LABEL))
#define NBTK_LABEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_LABEL, NbtkLabelClass))
typedef struct _NbtkLabel NbtkLabel;
typedef struct _NbtkLabelPrivate NbtkLabelPrivate;
typedef struct _NbtkLabelClass NbtkLabelClass;
/**
* NbtkLabel:
*
* The contents of this structure is private and should only be accessed using
* the provided API.
*/
struct _NbtkLabel
{
/*< private >*/
NbtkWidget parent_instance;
NbtkLabelPrivate *priv;
};
struct _NbtkLabelClass
{
NbtkWidgetClass parent_class;
};
GType nbtk_label_get_type (void) G_GNUC_CONST;
NbtkWidget * nbtk_label_new (const gchar *text);
G_CONST_RETURN gchar *nbtk_label_get_text (NbtkLabel *label);
void nbtk_label_set_text (NbtkLabel *label,
const gchar *text);
ClutterActor * nbtk_label_get_clutter_text (NbtkLabel *label);
G_END_DECLS
#endif /* __NBTK_LABEL_H__ */

View File

@ -6,3 +6,7 @@ VOID:UINT
VOID:UINT,UINT
VOID:OBJECT,OBJECT
VOID:STRING,OBJECT
VOID:OBJECT,OBJECT,INT,INT
VOID:OBJECT,FLOAT,FLOAT,INT,ENUM
VOID:FLOAT,FLOAT,INT,ENUM
VOID:FLOAT,FLOAT

111
src/nbtk/nbtk-private.c Normal file
View File

@ -0,0 +1,111 @@
#include "nbtk-private.h"
/* Utility function to modify a child allocation box with respect to the
* x/y-fill child properties. Expects childbox to contain the available
* allocation space.
*/
void
_nbtk_allocate_fill (ClutterActor *child,
ClutterActorBox *childbox,
NbtkAlign x_alignment,
NbtkAlign y_alignment,
gboolean x_fill,
gboolean y_fill)
{
gfloat natural_width, natural_height;
gfloat min_width, min_height;
gfloat child_width, child_height;
gfloat available_width, available_height;
ClutterRequestMode request;
ClutterActorBox allocation = { 0, };
gdouble x_align, y_align;
if (x_alignment == NBTK_ALIGN_START)
x_align = 0.0;
else if (x_alignment == NBTK_ALIGN_MIDDLE)
x_align = 0.5;
else
x_align = 1.0;
if (y_alignment == NBTK_ALIGN_START)
y_align = 0.0;
else if (y_alignment == NBTK_ALIGN_MIDDLE)
y_align = 0.5;
else
y_align = 1.0;
available_width = childbox->x2 - childbox->x1;
available_height = childbox->y2 - childbox->y1;
if (available_width < 0)
available_width = 0;
if (available_height < 0)
available_height = 0;
if (x_fill)
{
allocation.x1 = childbox->x1;
allocation.x2 = (int) (allocation.x1 + available_width);
}
if (y_fill)
{
allocation.y1 = childbox->y1;
allocation.y2 = (int) (allocation.y1 + available_height);
}
/* if we are filling horizontally and vertically then we're done */
if (x_fill && y_fill)
{
*childbox = allocation;
return;
}
request = CLUTTER_REQUEST_HEIGHT_FOR_WIDTH;
g_object_get (G_OBJECT (child), "request-mode", &request, NULL);
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
{
clutter_actor_get_preferred_width (child, available_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
clutter_actor_get_preferred_height (child, child_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
}
else
{
clutter_actor_get_preferred_height (child, available_width,
&min_height,
&natural_height);
child_height = CLAMP (natural_height, min_height, available_height);
clutter_actor_get_preferred_width (child, child_height,
&min_width,
&natural_width);
child_width = CLAMP (natural_width, min_width, available_width);
}
if (!x_fill)
{
allocation.x1 = childbox->x1 + (int) ((available_width - child_width) * x_align);
allocation.x2 = allocation.x1 + (int) child_width;
}
if (!y_fill)
{
allocation.y1 = childbox->y1 + (int) ((available_height - child_height) * y_align);
allocation.y2 = allocation.y1 + (int) child_height;
}
*childbox = allocation;
}

49
src/nbtk/nbtk-private.h Normal file
View File

@ -0,0 +1,49 @@
/*
* nbtk-private.h: Private declarations
*
* 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.
* Boston, MA 02111-1307, USA.
*
*/
#ifndef __NBTK_PRIVATE_H__
#define __NBTK_PRIVATE_H__
#include <glib.h>
#include "nbtk-widget.h"
#include "nbtk-bin.h"
G_BEGIN_DECLS
#define I_(str) (g_intern_static_string ((str)))
#define NBTK_PARAM_READABLE \
(G_PARAM_READABLE | \
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
#define NBTK_PARAM_READWRITE \
(G_PARAM_READABLE | G_PARAM_WRITABLE | \
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
G_END_DECLS
ClutterActor *_nbtk_widget_get_dnd_clone (NbtkWidget *widget);
void _nbtk_bin_get_align_factors (NbtkBin *bin, gdouble *x_align, gdouble *y_align);
void _nbtk_allocate_fill (ClutterActor *child, ClutterActorBox *childbox, NbtkAlign x_align, NbtkAlign y_align, gboolean x_fill, gboolean y_fill);
#endif /* __NBTK_PRIVATE_H__ */

1065
src/nbtk/nbtk-scroll-bar.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/*
* nbtk-scroll-bar.h: Scroll bar actor
*
* 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.
* Boston, MA 02111-1307, USA.
*
* Written by: Chris Lord <chris@openedhand.com>
* 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_SCROLL_BAR_H__
#define __NBTK_SCROLL_BAR_H__
#include <nbtk/nbtk-adjustment.h>
#include <nbtk/nbtk-bin.h>
G_BEGIN_DECLS
#define NBTK_TYPE_SCROLL_BAR (nbtk_scroll_bar_get_type())
#define NBTK_SCROLL_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NBTK_TYPE_SCROLL_BAR, NbtkScrollBar))
#define NBTK_IS_SCROLL_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NBTK_TYPE_SCROLL_BAR))
#define NBTK_SCROLL_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NBTK_TYPE_SCROLL_BAR, NbtkScrollBarClass))
#define NBTK_IS_SCROLL_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NBTK_TYPE_SCROLL_BAR))
#define NBTK_SCROLL_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NBTK_TYPE_SCROLL_BAR, NbtkScrollBarClass))
typedef struct _NbtkScrollBar NbtkScrollBar;
typedef struct _NbtkScrollBarPrivate NbtkScrollBarPrivate;
typedef struct _NbtkScrollBarClass NbtkScrollBarClass;
/**
* NbtkScrollBar:
*
* The contents of this structure are private and should only be accessed
* through the public API.
*/
struct _NbtkScrollBar
{
/*< private >*/
NbtkBin parent_instance;
NbtkScrollBarPrivate *priv;
};
struct _NbtkScrollBarClass
{
NbtkBinClass parent_class;
/* signals */
void (*scroll_start) (NbtkScrollBar *bar);
void (*scroll_stop) (NbtkScrollBar *bar);
};
GType nbtk_scroll_bar_get_type (void) G_GNUC_CONST;
NbtkWidget * nbtk_scroll_bar_new (NbtkAdjustment *adjustment);
void nbtk_scroll_bar_set_adjustment (NbtkScrollBar *bar,
NbtkAdjustment *adjustment);
NbtkAdjustment *nbtk_scroll_bar_get_adjustment (NbtkScrollBar *bar);
G_END_DECLS
#endif /* __NBTK_SCROLL_BAR_H__ */

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