Compare commits

...

1177 Commits

Author SHA1 Message Date
5b3c086ec3 Bump version to 2.91.0 2010-10-04 15:51:18 -04:00
8273de6bfa Add org.gnome.accessibility.magnifier.gschema.xml.in to POTFILES.in 2010-10-04 15:43:28 -04:00
e15e202e11 Support and require Mutter 2.91.0 2010-10-04 15:07:53 -04:00
c4edba042a [i18n] Updated German translation 2010-10-04 20:32:25 +02:00
8e25a1eb3b Updated Slovenian translation 2010-10-04 15:01:17 +02:00
1babf10e58 updating translation for Punjabi 2010-10-04 07:22:02 +05:30
8f9ef3f8f8 Add icon-naming-utils to build packages
icon-naming-utils is needed to build gnome-icon-theme(-symbolic).
Fedora already has it (commit 4b781a), add it to other
distributions.
2010-10-03 15:02:59 +02:00
446e97bf12 CSS: Remove overwritten style left over from a previous design 2010-10-03 14:13:30 +02:00
4a316fbc66 Use System Settings instead of Preferences in the user menu
This matches the terminology used in the result of the action.
2010-10-02 16:42:06 -04:00
8a7c1eebc0 Updated French translation 2010-10-01 23:19:46 +02:00
f336564e19 PopupMenu: add horizontal sliders
Introduce Cairo-drawn sliders to be used in PopupMenus (for example for
volume). They are stylable to some extent (colors, border width, slider
height) and have the standard behaviour of a slider, except they are
completely modal (once you start dragging, all events are intercepted by
the slider, which thus is kept active and highlighted at all times).
They show numeric values between 0 and 1 (scaling must be performed outside)
and emit value-changed on button release, but no activate, keeping the
menu open.

https://bugzilla.gnome.org/show_bug.cgi?id=625029
2010-10-01 15:18:36 -04:00
aebdf79430 Connect PopupMenuManager to destroy signal
PopupMenuManager now connects to the destroy signal of PopupMenu, so
that destroying a PopupMenu is now enough for removing it from the
relevant manager. Useful if menu come and go on-the-fly (like in
app views or sidebars).

https://bugzilla.gnome.org/show_bug.cgi?id=630914
2010-10-01 12:37:06 -04:00
25fe730d16 Add Clutter dependency on gdk-pixbuf in moduleset
Clutter also depends on gdk-pixbuf so build gdk-pixbuf
before Clutter.

https://bugzilla.gnome.org/show_bug.cgi?id=631086
2010-10-01 16:12:52 +02:00
61b029207d [windowDimmer] handle changing of window_type
dim/undim parent window when window_type changed to/from MODAL_DIALOG
https://bugzilla.gnome.org/show_bug.cgi?id=630363
2010-10-01 01:09:15 +04:00
4c068c135b [misc] add fileUtils.listDirAsync
Request information for a files from the directory asynchronously.
https://bugzilla.gnome.org/show_bug.cgi?id=623708
2010-10-01 01:08:22 +04:00
734d93087a Remove use of octal constants
New spidermonkey warns on octal constants, so we can't
even use them for file permissions. Switch to hex plus a comment.
2010-09-30 12:43:12 -04:00
e22fbda689 telepathy: Use string.replace in a way compatible with newer Spidermonkey
The semantics of the first argument changed from literal -> regexp
if the 'g' option was specified.  To remove ambiguity, stop using
the spidermonkey extension and create a standard RegExp object.

https://bugzilla.gnome.org/show_bug.cgi?id=630539
2010-09-30 12:43:12 -04:00
11db188fe9 Support xulrunner 1.9.3+
Add small wrappers around JS_AddValueRoot.
Add JS_BeginRequest in our custom code.

https://bugzilla.gnome.org/show_bug.cgi?id=630539
2010-09-30 12:43:12 -04:00
61c906807b Don't use mutter_window_get_window_type / MetaCompWindowType
They have been removed so we have to use meta_window_get_window_type()
and MetaWindowType instead.

https://bugzilla.gnome.org/show_bug.cgi?id=630363
2010-09-30 18:36:28 +02:00
c6eb2761c7 gnome-shell.in: Never add empty elements to LD_LIBRARY_PATH
An empty element means the current directory, and is insecure.

https://bugzilla.gnome.org/show_bug.cgi?id=631004
2010-09-30 15:25:21 +02:00
109de6a356 messageTray: Do not show the summary when removing a source
Having the summary pop up automatically after a source icon has been
removed is pretty useless ("Hey, there was something interesting going
on, but you missed it and it's gone now, kthxbye").

https://bugzilla.gnome.org/show_bug.cgi?id=630939
2010-09-29 23:11:24 +02:00
fe5a289460 Fix compilation against latest GTK+-3 changes
Adjust to GDK/GTK+ API changes:
 - removal of GdkColormap
 - expose-event -> draw transition

https://bugzilla.gnome.org/show_bug.cgi?id=630641
2010-09-28 22:56:45 +02:00
1b2a1a3a3d [i18n] Updated German translation 2010-09-28 20:57:42 +02:00
e967807acf shell-gtk-embed: Use GtkWidget instead of GtkObject
GtkObject has been deprecated and removed from GTK+.
2010-09-27 17:05:40 +02:00
4aee584850 Updated Hebrew translation. 2010-09-27 00:01:54 +02:00
ab8984e1ce Updated Spanish translation 2010-09-25 10:43:42 +02:00
b96cf2042a [StatusIconDispatcher] Add keyboard and display icons to tray icon list 2010-09-24 14:53:50 -05:00
1413fa6e03 Revert "StThemeNodeTransition: work around Cogl bug"
This reverts commit 8f0f159960.

Cogl has been fixed, so it is no longer needed.

https://bugzilla.gnome.org/show_bug.cgi?id=629616
2010-09-24 17:31:41 +02:00
a6e4bab990 Add symbolic icons to TextureCache's load_icon_name()
Icons can be loaded as St.Icon.SYMBOLIC, FULLCOLOR, APPLICATION or
DOCUMENT. The first will look for a symbolic equivalent, the second
looks for a full-color version (and does fallback, eg, from
"drive-harddisk-usb" to "drive-harddisk"). APPLICATION and DOCUMENT do
full-color icons without fallback (as specified by the icon spec).

And update various callers to use the right flags.

Based on a patch from Matt Novenstern.

https://bugzilla.gnome.org/show_bug.cgi?id=621311
2010-09-24 10:57:27 -04:00
4b781ae7e6 gnome-shell.modules: add gnome-icon-theme, gnome-icon-theme-symbolic
https://bugzilla.gnome.org/show_bug.cgi?id=621311
2010-09-24 09:48:15 -04:00
702b8e78e4 accessibility-status: Remove left-over debug message 2010-09-24 10:49:12 +02:00
4571a0ea0d Add basic error handling to search system.
If a search provider misbehaves, the search system fails to return any
results from any providers. Work around this.

https://bugzilla.gnome.org/show_bug.cgi?id=627950
2010-09-24 10:01:33 +02:00
437538644e introspection: Fix annotation
The scanner now warns about unknown annotations, which catched this
invalid 'type' annotation.
2010-09-24 02:08:32 +02:00
dc5ceffe40 Remove Alt+W/A/S/D hack
This was just for use within Xephyr, and gnome-shell doesn't work in
Xephyr any more anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=624858
2010-09-23 15:17:06 -04:00
1c7592b4b1 Updated Polish translation 2010-09-23 20:44:12 +02:00
fc8c93b2ed build: Add missing file statusIconDispatcher.js 2010-09-23 19:17:43 +02:00
9708b68540 [baseIcon] Tie the icon's width to its height
Both current design and new mockups use square icons. Currently this
is implemented by setting a fixed width and height in the CSS, which
does not work for the growing/shrinking items in the new sidebar.
By moving the assumption of square items into the code, the size will
adjust according to icon size, spacing, padding and font size if not
explicitly overwritten in the CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=625887
2010-09-23 19:08:43 +02:00
01f4dc68b8 [baseIcon] Allow setting the icon size from code
The current design features a sidebar where the icon size shrinks
automatically to fit more items. Add a setSizeManually parameter
to BaseIcon, which disables sizes read from CSS and allows to use
BaseIcon.setIconSize() to support this.

https://bugzilla.gnome.org/show_bug.cgi?id=625887
2010-09-23 19:08:43 +02:00
8c1bf346a9 [appDisplay] Factor out WellGrid/AppIcon
All mockups now use a representation for documents/places similar to
the one used for applications. Rename AppIcon to BaseIcon and move its
code together with WellGrid out of appDisplay to stress their general
usefulness.

https://bugzilla.gnome.org/show_bug.cgi?id=625887
2010-09-23 19:08:43 +02:00
8f0f159960 StThemeNodeTransition: work around Cogl bug
Switch to using the layer combine constant rather than the material
primary color for representing the opacity of the material; this
avoids triggering a Cogl bug where changing the primary color corrupts
the layer state.

https://bugzilla.gnome.org/show_bug.cgi?id=629616
2010-09-23 12:44:07 -04:00
cbf2cbac61 [StatusIconDispatcher] Move non-system-tray icons to message tray
New StatusIconDispatcher dispatches icons to the system or message tray.

Based on a patch from Matt Novenstern
https://bugzilla.gnome.org/show_bug.cgi?id=608869
2010-09-23 09:49:47 -04:00
82e6f9c8d6 [MessageTray] show newly-added sources even if they don't post notifications
eg, when a trayicon is added, show the summary briefly

https://bugzilla.gnome.org/show_bug.cgi?id=608869
2010-09-23 09:49:47 -04:00
ae9360659d [ShellTrayIcon] add ShellTrayIcon, make ShellTrayManager use it
The actor emitted by ShellTrayManager is now ShellTrayIcon, a subclass
of ShellGtkEmbed which has several properties on it which are (or will
soon be) useful to the shell.

Part of the rearranging to use ShellTrayIcon means that we now show
the ShellEmbeddedWindow before creating its ShellGtkEmbed, which
requires a few modifications to ShellEmbeddedWindow (notably, telling
it at construct time what stage it will be drawn on, since it needs to
know that before it has a ShellGtkEmbed now).

https://bugzilla.gnome.org/show_bug.cgi?id=608869
2010-09-23 09:49:47 -04:00
63f2066135 [ShellGtkEmbed] do a better job of tracking the actor's position
Previously the code to keep the X window aligned with its actor made
various assumptions that were true in the panel status tray area but
that are not true in the message tray. Fix it up by repositioning the
X window at clutter_actor_paint() time, which will definitely be
called every time the actor moves, whether it's because of its own or
its parent/ancestor's changes.

https://bugzilla.gnome.org/show_bug.cgi?id=608869
2010-09-23 09:49:47 -04:00
745e8f608f [ShellGtkEmbed] base this on ClutterX11TexturePixmap, not ClutterGLX
As of 1.4, ClutterGLXTexturePixmap is identical to
ClutterX11TexturePixmap (with the differences having been moved into
the cogl layer). So make ShellGtkEmbed use the (introspected) X11
version, which then allows us to make the instance and class structs
public as well.

https://bugzilla.gnome.org/show_bug.cgi?id=608869
2010-09-23 09:49:47 -04:00
c9a7c9d491 [NotificationDaemon] always resolve a notification's ShellApp first
Resolve a notification's ShellApp before posting the notification, so
that notification sources now always have an app associated (assuming
they came from an app as opposed to the command line). Index sources
by PID rather than by appName (so that, eg, multiple calls to
notify-send now show up as separate sources).

For Sources that have an associated app, use the app's icon for the
source, rather than tracking the notification icon.

This change also lets us get rid of appNameMap, since we can just use
shell_app_get_name() now.

https://bugzilla.gnome.org/show_bug.cgi?id=629090
2010-09-23 09:49:47 -04:00
ad8a97dfe0 Updated Slovenian translation 2010-09-23 15:10:25 +02:00
8591a2fc09 gnome-shell.in: Make xephr available within the scope of run_shell
https://bugzilla.gnome.org/show_bug.cgi?id=629304
2010-09-22 20:42:01 +02:00
d188a7b32a PopupSwitchMenuItem: use SVG switches
https://bugzilla.gnome.org/show_bug.cgi?id=629954
2010-09-22 11:12:31 -04:00
52d9cebcef Added Norwegian Nynorsk translation. 2010-09-22 15:10:30 +02:00
f18e57dc38 data/Makefile.am: fix indentation 2010-09-21 09:02:08 -04:00
828ad348ce [MessageTray] fix allocation in the title-too-long case
Previously we were hiding the banner label if the title was too long,
but this causes queue_relayout() warnings. Instead, just set its
opacity to 0.

https://bugzilla.gnome.org/show_bug.cgi?id=629308
2010-09-21 08:12:34 -04:00
516fe49bb0 Style fixes for the popup menu
https://bugzilla.gnome.org/show_bug.cgi?id=629954
2010-09-20 17:20:58 -04:00
555409aba2 Add spacing between label and switch for menu items
Currently there is no spacing between items packed into the switch
menu item layout box.  Add some.

https://bugzilla.gnome.org/show_bug.cgi?id=629954
2010-09-20 17:20:00 -04:00
7298831f54 Fix the universal access menu text to match mockups
This makes the menu label text more closely match the mockups
http://live.gnome.org/GnomeShell/Design/Guidelines/SystemStatus/UniversalAccess

https://bugzilla.gnome.org/show_bug.cgi?id=629954
2010-09-20 13:00:04 -04:00
fd5f30ab0d Use gdk_error_trap_pop_ignore() where appropriate
gdk_error_trap_pop() has been marked with G_GNUC_WARN_UNUSED_RESULT,
so use gdk_error_trap_pop_ignore() whenever the return value is ignored.
2010-09-20 14:54:26 +02:00
a2553f48e2 Enable side-by-side tiling
Override the metacity schema for side-by-side tiling to change the
default behavior when running mutter in GNOME Shell.

https://bugzilla.gnome.org/show_bug.cgi?id=606260
2010-09-17 16:02:37 +02:00
6f75c8c172 Add ORBit2-devel to required packages
GConf requires it to build, it's been forgotten when we introduced
it into the moduleset. Debian uses 'liborbit2-dev', Fedora
and Mandriva 'ORBit2-devel', and SuSE 'orbit2-devel'.

https://bugzilla.gnome.org/show_bug.cgi?id=629882
2010-09-17 15:52:54 +02:00
0cb8953232 accessibility.js: Fix use of non-existent gconf_client_get_value()
gconf_client_get_value() doesn't exist; apparently
gconf_client_get_float() was meant instead.
2010-09-16 15:35:13 -04:00
6ea18136ac Add Universal Access status indicator
Introduce the Universal Access status indicator as designed, modeled
after the similar UI provided by g-s-d. This indicator allows the user
to change rapidly the keyboard and mouse behaviour (sticky keys, slow
keys, bounce keys, mouse keys), as well as the enabled ATs (magnifier,
screen reader, screen keyboard) and the HighContrast Gtk theme.

https://bugzilla.gnome.org/show_bug.cgi?id=624916
2010-09-16 15:03:26 -04:00
e43f10c8ed Bump the required clutter version to 1.3.14 2010-09-16 19:28:15 +02:00
bbbce5f12f build: cairo-1.10.0 is stable, not a devel snapshot 2010-09-16 18:46:57 +02:00
6cdc2c26df build: bump cairo and pixman to latest stable releases 2010-09-16 18:36:47 +02:00
4e1de26a02 PopupMenu: Add support for submenus
Adds class PopupSubMenuMenuItem, which is an item holding a submenu,
that is opened when the corresponding item is active, and is keyboard
and mouse navigable like its Gtk counterpart.

https://bugzilla.gnome.org/show_bug.cgi?id=623498
2010-09-15 14:02:22 -04:00
b5ee89459a Support setting the image after construction
This patch allows the icon in PopupImageMenuItems to be changed at
any time, while preserving the item and all other properties (style,
signals) attached and without rebuilding the whole menu. This is useful
for images reflecting a dynamic status (e.g. cellular strength
indicator or battery level)

https://bugzilla.gnome.org/show_bug.cgi?id=623652
2010-09-15 13:34:28 -04:00
2adfca0582 Use non recursive automake for JS
Use only one Makefile for all JS module, to make faster builds and
to increase maintenability.

https://bugzilla.gnome.org/show_bug.cgi?id=629775
2010-09-15 18:38:46 +02:00
5ccc763385 Cancel Destroy effect of modal windows when the parent has gone away
Modal dialogs slide back into the titlebar of the parent window when destroyed.
This looks weird if the parent window itself has been destroyed, so cancel the
effect in this case.
https://bugzilla.gnome.org/show_bug.cgi?id=629560
2010-09-15 15:55:33 +04:00
652ce3ce8c introspection: Fix annotations
The scanner got more strict, now some annotations need fixing.
2010-09-15 03:02:26 +02:00
1bd0ad11d8 Use WellGrid for application results
Extend WellGrid with an optional rowLimit parameter and an accessor
function for the grid's items, then use it to replace the custom
container used to display the application search results.
Also adjust the spacing of the search results slightly to make it
consistent with the app well.

https://bugzilla.gnome.org/show_bug.cgi?id=622446
2010-09-15 00:18:22 +02:00
27e71d9a6c Fix shell_global_format_time_relative_pretty() parameter name
An out parameter annotation was missed due to a difference
in the parameter name between the declaration and the implementation.

https://bugzilla.gnome.org/show_bug.cgi?id=629595
2010-09-14 16:16:02 -04:00
7f2fce2684 .gitignore: add magnifier schema stuff 2010-09-14 11:32:34 -04:00
25f907ffb1 St: Use a local material template
To be consistent with what we do with the shadow
material, use the same pattern in setup_framebuffer().
2010-09-14 00:00:34 +02:00
1034798969 st-shadows: Use a template material when creating shadows
To avoid recompiling shadows each time a new shadow is created,
use a copy of a static template material.

See http://bugzilla.clutter-project.org/show_bug.cgi?id=2280#c5.

https://bugzilla.gnome.org/show_bug.cgi?id=629383
2010-09-13 18:11:03 +02:00
862f1ea18c st: Use template material for transitions
To avoid compiling a new shader each time a transition is started,
use a copy of a static template material.

See http://bugzilla.clutter-project.org/show_bug.cgi?id=2280#c5.

https://bugzilla.gnome.org/show_bug.cgi?id=629384
2010-09-13 17:50:05 +02:00
7c65643eed Added Estonian ('et') to LINGUAS 2010-09-12 17:47:20 +03:00
e9da061558 [l10n] Updated Estonian translation 2010-09-12 17:46:45 +03:00
45dcfa9a70 [Overview] Don't dim window previews
Undim windows when going to the overview and
restore their state when leaving.
https://bugzilla.gnome.org/show_bug.cgi?id=629371
2010-09-12 13:39:52 +04:00
907dd4381b [appSwitcher] Check the modifier state rather than assuming Meta
It isn't guaranteed that Alt+Shift equals to Meta, so we have to check
the modifier instead.

https://bugzilla.gnome.org/show_bug.cgi?id=629368
2010-09-11 22:41:59 +02:00
687bfbb081 [windowDimmer] Bump GLSL version to 1.10
The shader currently forces GLSL 1.0 to avoid being incompatible with older hardware but is still using features not available in 1.0.

Strict compilers fail to compile the shader:

error C7506: OpenGL/ES does not define the global variable gl_TexCoord

As every hardware/driver that supports 1.0 also supports 1.10 bumping the version to fix it is safe.

https://bugzilla.gnome.org/show_bug.cgi?id=629343
2010-09-11 21:41:47 +02:00
246d9f1357 [appSwitcher] Close the switcher on Meta_L/R release
The keyReleaseEvent handler does not take into account that a
user might release Alt while still holding shift
(the keycode becomes Meta_L/R in that case).

The result is that the switcher stays open which is unexpected.

https://bugzilla.gnome.org/show_bug.cgi?id=629368
2010-09-11 19:01:42 +02:00
e37f17be2b [build]Add shader_DATA to EXTRA_DIST 2010-09-11 15:56:53 +02:00
3c2ec3c770 Fix wrong filename in data/Makefile.am 2010-09-11 15:44:33 +02:00
a969e82954 Attach dialogs to windows with visual effects
Override the new mutter preference /apps/mutter/general/attach_modal_dialogs
to attach modal dialogs to their parent window. Animate the modal dialogs
expanding from the top of the parent window. Slowly dim the parent window
after the dialog comes up.
https://bugzilla.gnome.org/show_bug.cgi?id=612726
2010-09-11 05:39:57 +04:00
509ad5ed9a Updated Portuguese translation 2010-09-10 21:45:58 +01:00
afd3b76970 Fix various details of how notifications are shown
This patch ensures the following notifications behavior:
- Urgent notifications that have long title or banner text are auto-expanded
  correctly.
- Single-line notifications that have _expandNotification() called (e.g.
  because the user mouses over to them), are treated as expanded, which means
  they get fully expanded if they are updated with more content and the user
  can escape them.
- The position of expanded notifications is updated when they are updated.
- Notification banner is shown again on the first line if it can fully fit
  there after a notification is updated, even if it was previously hidden
  because the notification was expanded and the old banner did not fully fit.
- New notifications are immediately hidden if the user mouses away from them.
- If a new notification is updated while it is shown, we extend the time it
  will be shown.
- If a new notification is updated while it is hiding, we stop hiding it and
  show it again.
- If a summary notification is updated while it is hiding, we let it finish
  hiding and show a new notification with the updated information.

Implementation details:
- Single-line notifications now have 4px bottom padding instead of 8px, which
  means that their height matches the tray height, they are fully shown in the
  banner mode, and don't pop out by 4px when the notification is expanded.
- Notification keeps a flag that indicates whether it is expanded, updates
  its expanded look when it is updated, and emits an 'expanded' signal
  indicating that its layout has possibly changed. The message tray connects
  to this 'expanded' signal when it is showing a notification in the expanded
  state and updates the position of the notification accordingly when this
  signal is received so that the notification is fully shown. This is better
  than connecting to 'notify::height' signal on the notification bin, since
  it results in fewer callbacks.

https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-10 15:47:12 -04:00
399ebcc049 Some Magnifier DBus methods incorrectly interpret rectangles.
Modified methods to use [left, top, right, bottom] instead of
[left, top, width, height].

https://bugzilla.gnome.org/show_bug.cgi?id=626123
2010-09-10 12:03:40 -04:00
e88f08072c Bug 622414 - Port magnifier to GSettings
The Shell is the only user of the magnifier, so there's no
reason to keep using GConf for its settings. Since it's a
session-wide tool, use a distinct schema,
org.gnome.accessibility.magnifier, stored in
/desktop/gnome/accessibility/magnifier just like before.
Put these settings in a separate schema file for clarity.

Old enums in GConf were stored as integers, we now use the
facilities provided by GSettings to save them as strings,
and convert them to integers automatically thanks to the
mapping stored in the schemas. Remove hard-coded default values,
which we can get from the schemas.

https://bugzilla.gnome.org/show_bug.cgi?id=622414
2010-09-10 16:38:09 +02:00
38c3422331 [DND] change cursor when dragging
Return a DND.DragMotionResult constant from delegate _handleDragMotion
methods as well as the existing return value from the drag monitor method dragMotion.
https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-09-10 06:00:28 +04:00
0e2ed0fb0b add shell_global_[un]set_cursor
This functions set/unset the cursor on the stage window.
https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-09-10 05:58:19 +04:00
4f61f9a43d remove scrollbar-[width/height]
1. They are useless
2. We can get its value from get_preferred_[width/height] in StScrollBar
https://bugzilla.gnome.org/show_bug.cgi?id=624893
2010-09-10 05:57:36 +04:00
d6995194dd add get_preferred_[width/height] to StScrollBar
https://bugzilla.gnome.org/show_bug.cgi?id=624893
2010-09-10 05:57:15 +04:00
0a9ebf62b3 property for StScrollBar.trough should be set directly
We were previously putting the decorations for the trough on the StScrollBar itself,
which won't work if the scroll bar has padding.
https://bugzilla.gnome.org/show_bug.cgi?id=624893
2010-09-10 05:56:37 +04:00
ab25b8ab69 change parent class of StScrollBar from StBin to StWidget
1. It doesn't have child
2. It work like StWidget without child
https://bugzilla.gnome.org/show_bug.cgi?id=624893
2010-09-10 05:56:07 +04:00
d2290cc3e2 build: clutter deps on atk 2010-09-09 18:31:40 -04:00
e5e8590024 Updated Polish translation 2010-09-09 19:52:30 +02:00
178c8c50a0 Fix build with recent gtk3
use new keysyms names
https://bugzilla.gnome.org/show_bug.cgi?id=629128
2010-09-09 18:34:09 +04:00
b7212a4e8f Updated French translation
Contributed by Pablo Martin-Gomez, Claude Paroz and Bruno Brouard
2010-09-08 16:16:59 +02:00
177a136adc introspection: Fix use of pango_font_description_from_string() 2010-09-08 15:37:33 +02:00
dddd97f6df introspection: Build with --warn-all --warn-error
* Use --warn-all, --warn-error
* Fix various broken gtk-doc
* Drop unused shell_get_event_related
* For header defines, we currently require them to end in _H to be skipped
* Drop the no-longer-necessary fix-meta-rectangle.py hack
* Move to the convention of using -private.h for headers that are,
  well, private.
* Add shell-wm-private.h
2010-09-07 13:07:52 -04:00
86feb674ee Updated Swedish translation 2010-09-06 22:56:12 +02:00
0f8da7d24f [build] Remove libgee from moduleset
It is no longer a dependency of dconf.
2010-09-06 16:51:39 +02:00
8efaa798a9 [l10n] Updated German translation 2010-09-04 16:15:48 +02:00
a243ba6693 [StLabel] Implement text-shadow property
Use the existing shadow code to add a drop shadow to the underlying
ClutterText actor if the text-shadow property is specified.

https://bugzilla.gnome.org/show_bug.cgi?id=624384
2010-09-02 21:49:59 +02:00
ba1da9deb9 [StThemeNode] Make shadow helper functions semi-public
Move shadow helper functions from st-theme-node-drawing to st-private
to make them available to widgets which want to add shadows to internal
actors.
Also add a new helper function for creating the shadow material from a
ClutterActor.

https://bugzilla.gnome.org/show_bug.cgi?id=624384
2010-09-02 21:49:59 +02:00
29781b2e5c [StThemeNode] Add text-shadow property
Reorganize the existing code which parses the -st-shadow property
to allow parsing different shadow properties and add support for
the text-shadow property.

https://bugzilla.gnome.org/show_bug.cgi?id=624384
2010-09-02 21:49:59 +02:00
e942444630 [StShadow] Add reference counting
If a shadow property is inherited from a parent, multiple StThemeNodes
share a common StShadow. It would be possible to use st_shadow_copy()
for this purpose, but proper reference counting is nicer.

https://bugzilla.gnome.org/show_bug.cgi?id=624384
2010-09-02 21:49:59 +02:00
c3b88d4113 [l10n] Updated Italian translation 2010-09-02 21:30:52 +02:00
6d2d4fcc77 Don't expand notifications that pop up over the pointer
Expanding notifications automatically just because they popped up where
the pointer is positioned distracts the user. It can also lead to a behavior
that is surprising to the user by, for example, making the user's input
switch to the notification's text entry box.

It is possible to expand a notification that popped up over the pointer
by mousing away from it and then mousing back in immediately.

https://bugzilla.gnome.org/show_bug.cgi?id=617209
2010-09-02 14:48:36 -04:00
9f9067e29b [StThemeNode] Add basic background-position support
Add basic support for background-position, which only supports absolute
values.

Also don't require an unit to be specified for 0 (because the unit does not
really matter here 0 is 0 regardless of the unit).

https://bugzilla.gnome.org/show_bug.cgi?id=624375
2010-09-01 18:13:43 +02:00
c779dcb608 l10n: Updated Greek translation for gnome-shell 2010-08-31 23:35:35 +03:00
1c4d53eec3 l10n: Updated Greek translation for gnome-shell 2010-08-31 22:06:00 +03:00
a25f7df626 Fully show long titles when a notification is expanded
We used to keep long titles ellipsized when a notification was expanded,
which was a bug. We now show them fully by line wrapping them.

Based on the original patch from Steven Van Bael.

https://bugzilla.gnome.org/show_bug.cgi?id=623970
2010-08-31 13:47:17 -04:00
f8dc3b88f8 Use 'customContent' flag instead of 'bannerBody'
We used 'bannerBody' flag to differentiate the case when we move the banner to
the body when the notification is expanded from the one when we don't do that
and only use the custom content set for the notification, as is the case for
Telepathy notifications. We also always cleared the content of the notification
on update when bannerBody was set to true.

Flag named 'customContent' reflects the use case for it more clearly. The
comments that accompany it were also updated and improved.

We now always add the banner text as the first element in the expanded
notification unless 'customContent' flag is set to true.

If the 'body' parameter is specified, we use it in addition to the banner
text. The earlier version of the code had a bug that resulted in the 'body'
parameter not being set only in the case when the 'bannerBody' was set to
true and the banner text had newlines in it.

https://bugzilla.gnome.org/show_bug.cgi?id=623970
2010-08-31 13:47:10 -04:00
539b8ae9f6 Don't show the banner when hiding the notification or showing it in the summary mode
The banner should not be appearing briefly when we are hiding the notification.
For that, we should only restore the opacity of the banner in popInCompleted()
when we are done hiding the notification. We do need to restore the opacity
in case the notification is updated and is shown in the banner mode again.

The banner should not be appearing briefly when we are showing the notification
in the summary mode. For that, we should not use the animation time to fade out
the banner in popOut() for summary notifications.

These two problems were particularly visible when the ANIMATION_TIME was increased.

https://bugzilla.gnome.org/show_bug.cgi?id=623970
2010-08-31 13:47:01 -04:00
cc06916811 Update British English translation 2010-08-31 09:33:26 +01:00
5e7c25e136 Notice style transitions that don't change how StThemeNode paints
Add st_theme_node_paint_equal() and use that to do two things:

 1) Avoid animating transitions where nothing changes.
 2) Copy cached painting state from the old theme node to the new
    theme node.

https://bugzilla.gnome.org/show_bug.cgi?id=627083
2010-08-30 13:40:12 -04:00
b9f9dd948a [AltTab] fix Alt-Shift-Tab again
In Clutter 1.2, clutter_event_get_keysym() ignored the state of the
Shift key. In 1.4, it does not, so we have to adjust our comparisons
accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=627782
2010-08-30 12:28:00 -04:00
d1f0a1e33a Updated Hungarian translation 2010-08-29 19:43:27 +02:00
93d3270566 Calculate whether we need an expansion row for the banner correctly
The old calculation did not take into account the icon and the spacing
between columns. This resulted in the notifications that had a slightly
longer title/banner combination than could actually fit not being expandable.

The new calculation is done in _bannerBoxAllocate() so
that we don't need to hardcode which other elements are present.

https://bugzilla.gnome.org/show_bug.cgi?id=627985
2010-08-26 16:07:51 -04:00
6f57f07214 [MessageTray] Clean up source-vs-notification icon handling
A Source needs exactly one summary icon (which in the case of a
trayicon-based source won't even be just an image), but possibly many
notification icons, which may vary for successive notifications
(particularly in the case of NotificationDaemon notifications). So
differentiate these cases in the API.

https://bugzilla.gnome.org/show_bug.cgi?id=627303
2010-08-26 11:00:54 -04:00
1951812a47 [MessageTray] use Params.parse in Notification
https://bugzilla.gnome.org/show_bug.cgi?id=627303
2010-08-26 10:52:01 -04:00
8f6a7f393d [MessageTray] remove Notification IDs
Notification daemon notifications have IDs, but other kinds don't
necessarily, and the generic code doesn't need to bother with it.

https://bugzilla.gnome.org/show_bug.cgi?id=627303
2010-08-26 10:52:01 -04:00
d3031b406a [MessageTray] remove Source IDs
The tray itself does not actually need them, and to make status icon
sources work correctly the NotificationDaemon will need to be tracking
its sources by two separate IDs, so the existing system won't work.

Also remove MessageTray.removeSourceByApp(), which is
NotificationDaemon-specific, and implement the functionality in
notificationDaemon.js instead.

https://bugzilla.gnome.org/show_bug.cgi?id=627303
2010-08-26 10:52:01 -04:00
2915319602 gnome-shell.modules: Disable librsvg theme engine
The librsvg theme engine uses now-gone GTK+ drawing functions so doesn't
compile with GTK+ 3. Since we don't need the theme engine anyways,
skip bulding it.
2010-08-24 15:04:29 -04:00
0751d122d7 Updated Serbian translation 2010-08-24 05:40:53 +02:00
957b3b69dc [lg] fix queue_relayout warnings
https://bugzilla.gnome.org/show_bug.cgi?id=624940
2010-08-23 13:03:58 -04:00
083b1c9d8b [lg] Close inspector on Esc
https://bugzilla.gnome.org/show_bug.cgi?id=624940
2010-08-23 13:03:58 -04:00
09edf4ba59 [lg] Use scroll wheel in inspector to select parent actors
scroll-up selects the parent actor, then grandparent, etc. scroll-down
moves the selection back towards the frontmost actor.

https://bugzilla.gnome.org/show_bug.cgi?id=624940
2010-08-23 13:03:15 -04:00
1a50b94b19 [lg] split inspector event handlers out into separate functions
https://bugzilla.gnome.org/show_bug.cgi?id=624940
2010-08-23 13:00:39 -04:00
5bd977dd3c [transitions] Do not recreate FBOs on opacity changes
Creating an FBO may be expensive, so we should avoid the operation
if possible. When transitioning between theme nodes, the widget's
opacity is used to paint to the offscreen textures which are blended
together - this means that the textures have to be recreated each time
the widget's opacity changes. It is much more effective to paint the
textures at full opacity and respect the widget's paint opacity when
blending the textures together.

https://bugzilla.gnome.org/show_bug.cgi?id=627085
2010-08-23 18:41:34 +02:00
c3cb0be011 Fix copy / paste error in previous commit 2010-08-23 18:37:25 +02:00
63ee20dc17 Bump vala version to 0.9.7
https://bugzilla.gnome.org/show_bug.cgi?id=627740
2010-08-23 18:32:38 +02:00
9284e96a48 Added Japanese translation. 2010-08-23 01:25:27 +09:00
bdd4e68422 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2010-08-21 20:43:24 +08:00
5c60d8982e [Overview] Fix zoom when dragging items from the dash
Commit 4632db177 removed a required include statement, re-add it to
fix DND from the dash.
2010-08-21 11:25:20 +02:00
50ed2f45af [build] add gnome-menus-devel to openSUSE packages list
https://bugzilla.gnome.org/show_bug.cgi?id=627390
2010-08-20 16:29:19 +02:00
9debefd7ca [build] Requires xulrunner 1.9.1.x on openSUSE, required by gjs
gjs needs xulrunner 1.9.1 (see bug 627383), install the right package
on openSUSE distributions.

https://bugzilla.gnome.org/show_bug.cgi?id=627384
2010-08-20 16:29:18 +02:00
c18ff91030 [panel] Add a style class while the overview is active
Designers have asked for the possibility to style the panel
differently in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=624381
2010-08-20 12:06:48 +02:00
039229f340 Make it possible to register new search providers for the dash after it has been created.
Factors out meta creation from SearchResults._init to SearchResults.createProviderMeta(provider).

Adds Dash.addSearchProvider(provider).

https://bugzilla.gnome.org/show_bug.cgi?id=625954
2010-08-19 18:04:30 -04:00
d9169d27f5 [ShellTrayManager] a few updates
Use the new na_tray_child_get_wm_class() method.
Add the trayicon title to the signal.

https://bugzilla.gnome.org/show_bug.cgi?id=627306
2010-08-19 10:14:18 -04:00
7ff7ec0e7a [tray] sync NaTray code from gnome-panel
Our copies and gnome-panel's had been ported for GSEAL independently.
Sync them back up again.

https://bugzilla.gnome.org/show_bug.cgi?id=627306
2010-08-19 10:14:10 -04:00
a9c0dcbd6b [search] Use 'AND' instead of 'OR' on search terms
The current search system uses the OR operator to concatenate search
terms. While results which are matched multiple times sort before
other matches, it is almost guaranteed that adding an additional term
to the search increments the number of results, which is rather
surprising.

https://bugzilla.gnome.org/show_bug.cgi?id=610955
2010-08-18 23:59:27 +02:00
8258c01d5c [build] add missing packages for openSUSE
Add missing packages for build on openSUSE

https://bugzilla.gnome.org/show_bug.cgi?id=627175
2010-08-17 17:58:27 +02:00
6c6527b66d [gnome-shell-build-setup.sh] Fix for lsb_release system value containing space
On SLED11, lsb_release system is "SUSE LINUX", breaking the script.
Adding quotes fixes this issue.

https://bugzilla.gnome.org/show_bug.cgi?id=627172
2010-08-17 17:54:59 +02:00
cac0848316 Remove usage of gdk_screen_get_rgb_colormap()
gdk_screen_get_rgb_colormap() has been removed from GTK+; there's
no longer a special visual that is used for drawing true-color
images distinct from the system visual. So, we don't need to
check for it; if the visual isn't the system visual, we just
fall through to the case where we create a new GdkColormap.
2010-08-12 20:12:00 -04:00
26c9453b3a [gnome-shell.modules] Upgrade moduleset to cairo-1.9.14
The 1.9.14 snapshot, along with many other things, fixes a major bug in
painting images that was causing the cairo-converted Metacity theme cod
not to work properly.
2010-08-12 20:02:24 -04:00
4e283cf419 Reuse same labels and containers on notification updates
When calling Notification.update, reuse the previous _bannerBox and
related labels (only changing the label content and relayouting), so
that the opacity set on popOut is preserved. As a consequence, updating
an opened notification no longer shows (or flicker) the banner at the
top.

https://bugzilla.gnome.org/show_bug.cgi?id=625502
2010-08-11 16:55:06 -04:00
e96a76edf4 Revert "[gnome-shell.modules] Work around problem of git with 'gtk+'"
This reverts commit b76fe12209.

We now have a workaround symlink server side for the git 1.7.2 handling
of '+', and also there's a patch in git upstream and in some distros, so
we don't need the workaround around in our moduleset anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=626302
2010-08-11 14:29:30 -04:00
766b5b801c [St] Remove _st_actor_contains()
The function has been upstreamed as clutter_actor_contains() - with
the switch to clutter-1.4 it is now available to the Shell, so it
is no longer necessary to keep a copy in-tree.

https://bugzilla.gnome.org/show_bug.cgi?id=626512
2010-08-10 15:03:13 +02:00
3fb7cce80f Drop custom ClutterActor.contains
Clutter 1.4 does provides a native implementation

https://bugzilla.gnome.org/show_bug.cgi?id=624571
2010-08-10 08:41:50 +02:00
a0d9c9b65a [gnome-shell.modules] Switch Clutter to master (Clutter 1.4 branch)
Build the Clutter 1.4 development branch instead of against Clutter 1.2;
this seems to work fine with GNOME Shell at this point, with various
fixes having been applied Mutter, GNOME Shell, and Clutter.
2010-08-09 17:18:06 -04:00
597cd9c7ab [messageTray] fix padding/spacing around summary items
The space between the rightmost item and the edge of the screen should
be considered part of the rightmost item, and the space between items
should be considered part of the adjacent items, to prevent excess
jitter when moving between them.

https://bugzilla.gnome.org/show_bug.cgi?id=626112
2010-08-09 12:30:18 -04:00
1f7f3715cc Updated Swedish translation 2010-08-06 01:24:34 +02:00
0905940ef8 [StContainer] Add :first-child, :last-child pseudo classes
Add support for the CSS :first-child and :last-child properties to
StContainer, and thus to all containers in St and ShellGenericContainer.

The internal ordering of the container's children is used to determine
the child to which to attach the pseudo class, not the children's
positions. This means that containers where positions can differ from
the ordering (ShellGenericContainer / StGroup) may behave unexpectedly,
so some caution is required.

https://bugzilla.gnome.org/show_bug.cgi?id=625316
2010-08-05 19:05:18 +02:00
0573cbfbac Added ta translation 2010-08-05 21:48:21 +05:30
65e37b1d6b [gnome-shell.modules] Update vala to 0.9.4.
dconf now requires vala 0.9.4, update the moduleset.

https://bugzilla.gnome.org/show_bug.cgi?id=626000
2010-08-04 15:39:56 -04:00
e7fb2c50a3 [Calendar] Fix wrong start date in corner case
The start date is shifted by a week if the day number of the month's
first day is smaller than the week start's day number. Probably the
only real world examples are months starting on a Sunday with locales
using Monday as start of week.

https://bugzilla.gnome.org/show_bug.cgi?id=625756
2010-08-02 16:48:10 +02:00
09374b08a3 Updated Norwegian bokmål translation 2010-08-01 14:09:35 +02:00
7fa9e88294 [St] Remove unused width/height from st_theme_node_transition_paint
We query the texture size here but never actually use it.

https://bugzilla.gnome.org/show_bug.cgi?id=625713
2010-08-01 12:10:53 +02:00
b76fe12209 [gnome-shell.modules] Work around problem of git with 'gtk+'
Use gtk%2b in the checkout URL, since recent versions of GIT have
trouble with the '+' in gtk+.

https://bugzilla.gnome.org/show_bug.cgi?id=625135
2010-07-28 17:09:18 -04:00
911e71542b Set LD_LIBRARY_PATH before running dconf
When we are manually starting dconf in the case where it can't
be activated via D-Bus, we need to set LD_LIBRARY_PATH in its
environment, since dconf is no longer linked with a rpath.
(Unlike the rest of GNOME, it doesn't use libtool.)
2010-07-28 15:31:16 -04:00
43de15c3fc Updated Spanish translation 2010-07-28 19:49:05 +02:00
5cb2ea04f7 MoreLink: Ignore calls to activate() if the actor isn't visible
This fixes (another time) the bug about the "Recent Items" label
being clickable when there are no items.

https://bugzilla.gnome.org/show_bug.cgi?id=582037
2010-07-27 16:54:58 +02:00
e287aa10e3 [notifications] Make the whole notification clickable
It is not obvious that only the icon is clickable to activate the
default action - in fact, with the area being that tiny, many don't
even know that notifications can be clicked.
Just extend the clickable area to the whole notification.

https://bugzilla.gnome.org/show_bug.cgi?id=613932
2010-07-27 00:11:09 +02:00
b237cf9a63 Use CoglHandle rather than CoglHandle*
This breaks building on 1.4, and has always been wrong anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=624571
2010-07-26 21:55:25 +02:00
c0d4f11510 Updated Spanish translation 2010-07-26 21:16:19 +02:00
1850c93785 Updated Slovenian translation 2010-07-25 21:41:56 +02:00
cd0e31cd30 Updated Bulgarian translation 2010-07-25 18:40:43 +03:00
02ebd44851 [shadows] Fix shadows with small blur radius
There's an assertion in calculate_gaussian_kernel() to avoid a division
by zero - due to an unnecessary cast from float to int this assertion
is triggered incorrectly for small (but non-zero) values, e.g. a blur
radius of 1px.
2010-07-25 00:37:12 +02:00
29c4742383 [gdmuser] Annotate gdm_list_users()
Recently, g-ir-scanner got a little stricter with regard to
GSList, marking functions not introspectable if the element
type is not annotated. This fixes a visible JS Error by g-ir
and gdmuser/gdm-user-manager.c
2010-07-24 13:25:51 +02:00
d059d1fedc Update Simplified Chinese translation. 2010-07-24 18:00:28 +08:00
7cac4ee1ae [i18n] Updated German translation 2010-07-22 19:08:41 +02:00
0c38f49dde Fix typo inside Switch class
Corrects setToogleState into setToggleState, slipped from 4dfc869e

https://bugzilla.gnome.org/show_bug.cgi?id=621880
2010-07-22 12:49:48 -04:00
2e77724341 Updated Galician translations 2010-07-22 16:39:13 +02:00
13c10b1e27 Updated Hebrew translation. 2010-07-22 16:30:25 +03:00
229604690b [gnome-shell.in] set $XDG_DATA_DIRS too
This is needed to find gsettings schemas that are installed in
the jhbuild prefix.
2010-07-22 09:23:34 -04:00
4dfc869e9d Add support for toggle switches in menus
Adds class PopupSwitchMenuItem, which is a two-state switch similar
to those in system status indicators mockups. Also adds class Switch,
which represents the switch itself, in case it is useful somewhere
else.

https://bugzilla.gnome.org/show_bug.cgi?id=621880
2010-07-22 09:06:01 -04:00
7bde88a6e2 Complete Simplified Chinese translation. 2010-07-22 20:38:02 +08:00
73ecdbd6da Add API for system status indicators
Add a container in the panel for holding them, a fast method for
loading and a simple base class to be subclassed by specific
implementations.

https://bugzilla.gnome.org/show_bug.cgi?id=621705
2010-07-21 12:31:06 -04:00
6eb90434f0 Update the look of various message tray components
The following changes make message tray look more polished:
 - all notifications are now same width (no min and max width)
 - there is an equal padding all around the notification (which resulted in
   the increased tray height)
 - action buttons are now nicely styled
 - chat text box glows when focused (nevermind the unfocused look because
   we'll soon always have it focused when it is showing)
 - chat text has padding on the left and rounded background
 - summary source buttons no longer have a border

https://bugzilla.gnome.org/show_bug.cgi?id=624584
2010-07-21 02:42:17 -04:00
65991cc057 Make Esc hide the tray when a notification has focus
It's convenient to have Esc working for expanded new notifications that
have focus and for summary notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=617224
2010-07-21 01:27:21 -04:00
95d438b86d Grab focus in expanded notifications on hover
In addition to already grabbing focus in the summary notifications,
we also want to grab focus in the new notifications when the user
hovers over them and expands them.

The notifications that expand automatically will only get focus once
the user hovers over them. The notifications that don't expand will
never grab focus because they don't need it.

Make sure that we toggle the way we grab focus when switching between
the overview and the main mode. This is necessary because, unlike
summary notifications that pop down when the user moves between the two
modes, new notifications keep being shown as long as the user hovers
over them or until they time out.

https://bugzilla.gnome.org/show_bug.cgi?id=617224
2010-07-21 01:20:37 -04:00
46906eef43 Grab focus in the summary notification
Because clicking on the summary item to have it display its notification
is a more deliberate action than hovering, we can now grab focus in that
notification. This makes chat notifications in the summary more convenient
to use because you don't need to click on the text entry there.

We pop down the notification when the user clicks anywhere outside of it,
triggers the overview, or the run dialog.

https://bugzilla.gnome.org/show_bug.cgi?id=617224
2010-07-21 00:44:04 -04:00
b2185eb2b1 Always show the summary if it is summoned
This ensures that the summary appears when we are showing a new
notification and switch to the overview at the same time.

Another effect of this patch is that the summary is shown if the
user moves the mouse to the bottom right corner while a notification
is being shown, which is ok.
2010-07-21 00:18:54 -04:00
539ad8196e [panel] don't empty out the app menu when the panel itself gets focus
https://bugzilla.gnome.org/show_bug.cgi?id=623429
2010-07-20 15:03:17 -04:00
adbf3b1c37 [ShellGlobal] add SHELL_STAGE_INPUT_MODE_FOCUSED
Add SHELL_STAGE_INPUT_MODE_FOCUSED, to move the keyboard focus to the
shell without grabbing the keyboard or mouse, and make
stage_input_mode into a GObject property so that (among other things),
callers can tell when MODE_FOCUSED reverts back to MODE_NORMAL.

https://bugzilla.gnome.org/show_bug.cgi?id=623429
2010-07-20 15:03:17 -04:00
6259513b0f [build] Use dpkg-checkbuilddeps to check for installed packages
This is required to handle Provides header, as used by lib*-dev packages
(for example libtiff5-dev provides libtiff-dev), this allows the build
setup script to specify the "generic" package names.

https://bugzilla.gnome.org/show_bug.cgi?id=624009
2010-07-20 16:29:01 +02:00
d8df46d4a1 Enable insertion and removal of menus
This patch adds the method "removeMenu" to PopupMenuManager, to allow
for removal of menus after they're inserted. In order to do this, it
needs to store along with the menu all the relevant signal connections,
that are disconnected when the menu is removed.
Also adds a parameter "position" to "addMenu", so that menus can added
in arbitrary order (in particular to reintroduce those which were removed).
This patch is intended towards dynamic menu users, like extensions for
application lists, docks, sidebars showing recent documents or favourites,
as well as advanced system tray implementations.

https://bugzilla.gnome.org/show_bug.cgi?id=622730
2010-07-20 09:35:12 -04:00
4aa80105ca Fix possible property access on undefined object
PopupMenuManager allows the insertion of menu without a sourceActor
(or with a null one), but never checks before calling contains() on
it.

https://bugzilla.gnome.org/show_bug.cgi?id=622730
2010-07-20 09:35:12 -04:00
13a1175792 fix "undo remove from favorites"
In GSettings, a change notification is generated immediately from context of the _set() call.
In GConf, The "value_changed" signal is emitted whenever the server
notifies your client program that a value has changed in the database (100% NOT from context of the _set() call).
https://bugzilla.gnome.org/show_bug.cgi?id=624296
2010-07-20 16:24:24 +04:00
ed065fc4ea Updated Galician translations 2010-07-20 13:03:31 +02:00
4632db177a Clean up unused includes
Some late spring cleaning ...
2010-07-19 01:46:01 +02:00
cc0de39725 [panel] Fix translatable string
Fix a string which is not extracted correctly by marking it
correctly with double quotes.
2010-07-19 01:46:01 +02:00
f8a5728615 Update vala to 0.9.3
Fixes incompatbility between the .gir files generated by Vala and the
current g-ir-compiler.

https://bugzilla.gnome.org/show_bug.cgi?id=624301
2010-07-15 10:22:36 -04:00
5695c8b0aa Fix invoking actions on notifications
We need to only connect to 'action-invoked' on notification once
when the notification is created. We were accumulating callbacks
otherwise, which resulted, for example, in the Rhythmbox skipping
through multiple tracks when the 'Next' button was hit.

Always be sure to destroy the notification when its source is
destroyed, which is the case when an action is invoked.

Note that in the future, we might not want to destroy the source
for some notifications when an action is invoked. For example,
it makes sense to keep Rhythmbox in the tray while the music is
playing and allow the user to use the controls from the summary
notification too.
2010-07-14 17:16:35 -04:00
11c73fcbc3 [i18n] Updated German translation 2010-07-14 22:21:30 +02:00
5a7201ef4d Resolve cyclic dependency on StatusMenu
Solved by splitting the base class (PanelMenuButton) in a separate
module, ui.panelMenu, which is meant to hold also other reusable
button classes.

https://bugzilla.gnome.org/show_bug.cgi?id=621705
2010-07-13 11:58:13 -04:00
d2902cb70f Updated Norwegian bokmål translation 2010-07-13 15:28:59 +02:00
1b03d5cb45 [St] fix a bug noticed by gcc -O3
https://bugzilla.gnome.org/show_bug.cgi?id=623295
2010-07-12 14:24:16 -04:00
51caecc1b3 Bump version to 2.31.5 2010-07-12 12:58:00 -04:00
ef1d3c56d8 [gnome-shell-build-setup.sh] Pull in autopoint for gdk-pixbuf
The gdk-pixbuf autogen.sh uses autopoint. This is part of
gettext on most systems, but Fedora 14 splits autopoint
into a separate subpackage, so we need to add a version
check.

For completeness, system version extraction is added generally,
though we are only using it on Fedora currently.

https://bugzilla.gnome.org/show_bug.cgi?id=624175
2010-07-12 12:45:22 -04:00
aa8f386b7d Added Traditional Chinese translation (Hong Kong and Taiwan) 2010-07-12 19:26:41 +08:00
43b751e27a Update Czech translation 2010-07-11 21:54:47 +02:00
69fde6822c [StartupNotification] Do not bounce the animation
The spinner animation moving from left-to-right to indicate a starting
application changes its direction on reaching the end of the movement.
Instead, keep the spinner at the right of the app name until startup
has finished.

https://bugzilla.gnome.org/show_bug.cgi?id=623687
2010-07-10 02:25:58 +02:00
b28c4dcd81 [docInfo] Fix recent items
GJS no longer translates time_t values into Date objects, update
the code where we relied on the previous behavior.
2010-07-10 00:23:23 +02:00
5014d16647 [configure] Use pkg-config --libs instead of --print-requires
The latter was added in version 0.23 (0.25 is current), but
distributions using version 0.22 are still out there ...
2010-07-09 22:18:44 +02:00
a5f9039e12 [configure] Do not use grep -q
Although mandated by POSIX, not all implementions[0] support this
option. Use redirection to /dev/null instead.

[0] http://docs.sun.com/app/docs/doc/816-5165/grep-1?a=view
2010-07-09 20:11:58 +02:00
d9eb4702b2 [configure] Check that mutter was compiled with GTK+-3.0
If mutter was compiled with GTK+-2.0, the build will fail with a
rather cryptic message - better fail early during configure with
a proper error message.

https://bugzilla.gnome.org/show_bug.cgi?id=623889
2010-07-09 18:27:16 +02:00
a19047fa3a [build] Fix typo in dependency list 2010-07-08 00:11:24 +02:00
edba3e843f Updated Galician translations 2010-07-08 00:09:46 +02:00
e48d119801 Build the full GTK+ 3.0 stack
Now that we are targetting GTK+ 3.0, always build the full GTK+ stack,
along with librsvg and gtk-engines (so we have an SVG loader, and maybe
the user's GTK+ theme engine.)

New modules:

 gtk+-3, gtk-engines-3, gnome-desktop-3, gdk-pixbuf, pixman, cairo, librsvg

Removed modules:

 gir-repository

Add new requirements to gnome-shell-build-setup.sh and remove some
older requirements we no longer need.

Based on a patch from Colin Walters

https://bugzilla.gnome.org/show_bug.cgi?id=621845
2010-07-07 13:05:09 -04:00
643c7fdb3a Switch build to Gtk+-3.0
Update the build dependencies to gtk+-3.0 and adjust the javascript
to run on gtk+-3. Obviously depends on mutter compiled with gtk+-3
as well.

https://bugzilla.gnome.org/show_bug.cgi?id=621845
2010-07-07 12:57:59 -04:00
174caf0016 Work around g-ir-scanner problem with Gdk.Rectangle
g-ir-scanner is currently buggy and confuses the Gdk.Rectangle alias
with MetaRectangle. Since this is moderately hard to fix in
gobject-introspection and the fix would conflict with in-progress
changes, work around by doing a 'sed job' on the generated Meta.gir.

https://bugzilla.gnome.org/show_bug.cgi?id=623640
2010-07-07 12:57:59 -04:00
ab0d57d6ca Use MetaRectangle for allocated returns
The conversion of GdkRectangle to a typedef for cairo_rectangle_int_t
in GTK+-3 makes it no longer a proper boxed type (it's still registered
boxed, but gobject-introspection doesn't know that.) So, switch to using
MetaRectangle, which is now registered as a boxed type by Mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=621845
2010-07-07 12:56:47 -04:00
a45021bd60 Replace deprecated GDK symbols
The fix depends on API introduced in this cycle, so the required
GTK+ version is bumped to 2.21.1.

https://bugzilla.gnome.org/show_bug.cgi?id=621845
2010-07-05 20:25:50 -04:00
7b79e2e35c [TelepathyClient] Fix notification of presence change
When renaming Source.name to Source.title in commit 83689e4 some
references were missed, which broke presence change notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=623494
2010-07-04 02:06:06 +02:00
fdbda8e731 Updated Spanish translation 2010-07-03 12:51:32 +02:00
4c6c6d8658 update for Punjabi by A S Alam 2010-07-03 06:43:53 +05:30
c405cce700 Updated Spanish translation 2010-07-02 08:59:22 +02:00
8ade2fc116 Make pango be built before clutter in moduleset
If pango is built, do it before clutter since it will
use it instead of the system version.
2010-06-29 19:52:59 +02:00
40c7d3763b Remove the cursor from the search entry when it doesn't have focus
We should not be showing the cursor in the search entry in the overview
if the user's input will be appearing elsewhere, such as in the run dialog,
in the Looking Glass console, or in the notification's response field.
2010-06-28 18:13:45 -04:00
71bbd4ed5c Updated Spanish translation 2010-06-28 20:57:40 +02:00
a2617fe06a Update Simplified Chinese translations. 2010-06-27 11:06:42 +08:00
d1e1afdaab Add icon buttons to notifications
Now if an id is passed to Notification.addButton that matches a theme icon,
it will be displayed as an icon.  This is another in the implement the
music player mockups series.
http://live.gnome.org/GnomeShell/Design/Guidelines/MessageTray/MusicPlayer

https://bugzilla.gnome.org/show_bug.cgi?id=621014
2010-06-26 20:25:23 +02:00
a94978db36 Bump version to 2.31.4 2010-06-25 18:28:55 -04:00
97f883b10e Implement "text-align"
"text-align" allows setting the alignment of text, with respect to
other lines and allocated space, without requiring a reference to
the ClutterText (which is private for most widgets).
If not specified, all text is left-aligned.

https://bugzilla.gnome.org/show_bug.cgi?id=622447
2010-06-25 22:43:14 +02:00
3af4ca3fe9 Missed some 'Shell.GConf' references in switch to GSettings.
Replaced all calls to Shell.GConf with GConf.Client in magnifier.js.

https://bugzilla.gnome.org/show_bug.cgi?id=622524
2010-06-25 16:42:08 -04:00
c19c236dbf Magnifier DBus setCrosswireColor() doesn't convert correctly to hex string.
Modified setCrosswireColor() in magnifierDBus.js to correctly pad hex string
with leading zeroes when converting from integer.

https://bugzilla.gnome.org/show_bug.cgi?id=622508
2010-06-25 16:40:20 -04:00
6873539846 Update Mutter minimum version for plugin changes
Require mutter-2.31.4, which has the revised effects plugin API.
2010-06-25 16:27:28 -04:00
d9275d3dda Added Lithuanian translation 2010-06-25 20:28:34 +03:00
e8b72a2a59 Switch to using dconf
* Add dconf and dependencies to the moduleset and add
  libxml2 dependency to gnome-shell-build-setup.sh

* if we can't ping the dconf D-Bus service, try to
  activate it manually.

* Stop forcing GConf via GSETTINGS_BACKEND

https://bugzilla.gnome.org/show_bug.cgi?id=622308
2010-06-25 12:48:14 -04:00
a160e31c2a Fix missing semicolon in source title commit
Just add the missing semicolon

https://bugzilla.gnome.org/show_bug.cgi?id=622592
2010-06-24 13:16:03 -04:00
a84e2e3307 [format] Add 'x' format specifier and field width
Sometimes it is useful to print numbers in hex format - add the
appropriate specifier. Also support a minimum field width to
pad the formatted string with spaces (or zeros if the width is
prefixed with '0').

https://bugzilla.gnome.org/show_bug.cgi?id=622597
2010-06-24 15:54:54 +02:00
83689e494c Show source title on hover, notification on click in the message tray
This is part of the design update for the message tray.

Source now takes an extra argument called 'title'.

All expanded message tray items are same width, which is determined by
the width of the item with the longest title, up to MAX_SOURCE_TITLE_WIDTH.
This is done so that items don't move around too much when one is expanded
and another one is collapsed.

https://bugzilla.gnome.org/show_bug.cgi?id=617224
2010-06-23 15:23:01 -04:00
7c4d4b8695 Do not exclude Documentation from applications
There is currently no way of launching the desktop-wide help other
then running yelp explicitly from the run dialog or a terminal. It
should instead be included with the rest of applications.

https://bugzilla.gnome.org/show_bug.cgi?id=622458
2010-06-23 01:17:17 +02:00
771648893f Updated Spanish translation 2010-06-22 23:08:40 +02:00
81aed78a1f [panel] Flip left and right group in RTL locales
While the contents of the left and right group in the panel are
flipped correctly, the groups themselves have to be swapped as
well. The location of the hot corner has to be corrected as well.

https://bugzilla.gnome.org/show_bug.cgi?id=622243
2010-06-21 18:40:29 +02:00
9af979097d Remove unintended GConf dependency GTK+ in moduleset
Commit 2799327 introduced a dependency on gtk+ for gconf,
instead of glib, pulling the whole stack.
2010-06-21 18:34:02 +02:00
35764fa09e Move Tweener.slowDownFactor into St
It has probably crossed the line to evil by a mile or so, but here
it is: a Tweener.slowDownFactor replacement used by all animations
without exception.
While at it, update Tweener to use the new setTimeScale() upstream
function instead of adjusting the timeline directly.

https://bugzilla.gnome.org/show_bug.cgi?id=622249
2010-06-21 16:19:25 +02:00
4b1fea2fa4 [windowTracker] Only remove "interesting" windows
Windows are only added to an application if they are considered
"interesting". If we keep it that way, we cannot unconditionally
call _shell_app_remove_window() - applications without interesting
windows are not considered running, so the call crashes the shell.

https://bugzilla.gnome.org/show_bug.cgi?id=622236
2010-06-21 15:35:36 +02:00
04ecde9f8e [StButton] Cleanup left-over animation code
StButton used to animate hover changes - the animation itself was
removed in commit a4481b38d, but some related member variables were
left in place.
2010-06-21 00:01:05 +02:00
ee79579b2e Change the algorithm used to calculate week numbers
The currently used algorithm returns incorrect results in some corner
cases, so replace it with a better one.

https://bugzilla.gnome.org/show_bug.cgi?id=620125
2010-06-20 23:53:43 +02:00
0f52c924e2 Updated Slovenian translation 2010-06-20 20:55:31 +02:00
9ef2a46e33 Replace non-toplevel Gtk include 2010-06-19 21:35:24 +02:00
1f550dbc72 [ShellApp] Move assertion below precondition check
Need to track down why we're calling _remove_window with a window not
in the app, but this is the quick fix for a crasher.
2010-06-19 11:32:00 -04:00
e63a0f3a13 Updated Hebrew translation. 2010-06-19 18:01:55 +03:00
62b07a5260 Added Norwegian bokmål translation 2010-06-19 16:43:22 +02:00
91bcca71c6 Update Simplified Chinese translation. 2010-06-19 21:49:48 +08:00
e8fc731fc1 Revert "[gsettings] Restore the recorder's default pipeline"
This reverts commit 91e2117708.

The recorder already defaults to the default value when no pipeline is
set.
2010-06-19 13:07:13 +02:00
91e2117708 [gsettings] Restore the recorder's default pipeline
It got lost in the gsettings transition.
2010-06-19 12:34:58 +02:00
4ccff179a5 [recorder] Don't pass recorderSettings as a paramter to the signal handler
We want to use the settings object created in start(), not the argument
passed to the signal handler.
2010-06-19 12:08:52 +02:00
bd4aa54e48 Rescue innocent schema files from the greedy make god
Removing the prerequisites from the gschemas.compiled rule broke
the build, as this is what triggers the generation of the actual
schema files expected by the rule's command.
Instead of just restoring the former dependencies, make sure that
the schema is validated before compilation, not after.

https://bugzilla.gnome.org/show_bug.cgi?id=622050
2010-06-19 05:11:52 +02:00
f8b142064b Sacrifice spaces, replace with a tab to keep the make god happy 2010-06-18 17:48:13 -04:00
38f5e30162 Updated Galician translations 2010-06-18 21:44:36 +02:00
2799327c84 Migrate to GSettings
Use GSettings for all Shell configuration. GConf is kept to read
configuration from external programs (Metacity, Nautilus and Magnifier),
but ShellGConf is removed because it's mostly useless for the few calls
we still have. Also get rid of unused GConf code in ShellAppSystem.

A basic GConf schema is still used to override Metacity defaults and
configure Magnifier in a system-wide fashion. GConf is also used as
GSettings backend via the GSETTINGS_BACKEND environment variable.
All of this will be removed when these programs have been ported
to GSettings and able to use dconf.

GLib 2.25.9 is required. Schemas are converted to the new XML format,
and compiled at build time in data/ so that the Shell can be run from
the source tree. This also requires setting the GSETTINGS_SCHEMA_DIR
environment variable both when running installed or from source tree,
in src/gnome-shell.in and src/gnome-shell-clock-preferences.in.

https://bugzilla.gnome.org/show_bug.cgi?id=617917
2010-06-18 20:27:41 +02:00
da4e24555b Split off running state handling into separate structure
This is a small memory usage optimization, and cleans up the code.
In particular, this will help for later patches which perform
more substantial operations on running apps.

https://bugzilla.gnome.org/show_bug.cgi?id=621203
2010-06-18 13:03:41 -04:00
7f8f0f2358 Add animated display of startup notification
The shell design says that upon launching an application,
no X window should have focus, and we should display an
animated launching indicator.

Implement this by in panel.js, keep track of the last started
application.  If there isn't currently an X focus, show an animation
for the last starting application.

https://bugzilla.gnome.org/show_bug.cgi?id=598349
2010-06-17 23:18:28 +04:00
cae61e62fd [StThemeNode] implement CSS "outline" property
Could potentially be used for focus indication

https://bugzilla.gnome.org/show_bug.cgi?id=621669
2010-06-17 14:06:47 -04:00
ab61017041 [environment] use St.describe_actor for Clutter.Actor.prototype.toString
https://bugzilla.gnome.org/show_bug.cgi?id=621668
2010-06-17 13:19:50 -04:00
792dc489ee [St] add st_describe_actor, for debugging
This can be used when adding debug printfs, to get clear descriptions of
actors.

Also update the Looking Glass inspector to use it

https://bugzilla.gnome.org/show_bug.cgi?id=621668
2010-06-17 12:48:13 -04:00
9baf8e19ea Kill Ubuntu indicators on start-up
Canonical replaced status icons with libindicator based solutions,
which don't work in the shell environment. Force the distro-patched
versions to fall-back to upstream.

https://bugzilla.gnome.org/show_bug.cgi?id=621382
2010-06-17 18:44:50 +02:00
362fc78dcf Revert "[appSwitcher] Remove unneeded workaround"
This reverts commit a1bfaac5a2.

https://bugzilla.gnome.org/show_bug.cgi?id=613194
2010-06-17 17:17:57 +02:00
4800a80c3a Update GnomeShellPlugin according to recent changes in MutterPlugin
https://bugzilla.gnome.org/show_bug.cgi?id=621083
2010-06-17 01:44:44 +04:00
d8f7629a4f [linearView] Update workspace opacity
While zoomed out in drag mode, the workspaces at the left and right
of the active workspace are slightly transparent - when switching
workspaces, one of the transparent workspaces becomes the new active
workspace, but its opacity is not updated.

https://bugzilla.gnome.org/show_bug.cgi?id=620940
2010-06-16 20:56:10 +02:00
7514dfaef9 [linearView] Drop _dropGroup
When in drag mode, the linear view raises a transparent actor
covering the entire stage. That way the view can handle events
like dragging items to the screen edges, but in order to not
disable any drop target not handled by itself, it duplicates
huge amounts of code from dnd.js.

Cleanup that mess by using the new drag monitoring support.

https://bugzilla.gnome.org/show_bug.cgi?id=620504
2010-06-16 20:56:10 +02:00
c50e324366 [dnd] Add monitoring hooks for motion/drop events
Sometimes it is desirable to be able to react to DND events that
happen outside a target actor's bounds, e.g. to implement reactive
screen edges. Add a simple interface which allows to hook into
drag motion and drop handling without jumping through ugly hoops.

https://bugzilla.gnome.org/show_bug.cgi?id=620504
2010-06-16 20:56:09 +02:00
6e09cc5fc8 Fade in alt-tab popup, adjust timings
The design calls for item to not appear abruptly, but not too slow
either - 100ms seems to be a good sweet spot for elements which are
supposed to appear "instantly".
Add a fade effect to the alt-tab popup and set the timings for other
fade effects to 100ms.

https://bugzilla.gnome.org/show_bug.cgi?id=621247
2010-06-16 20:55:26 +02:00
eafd3848a9 Updated Spanish translation 2010-06-15 19:28:58 +02:00
942810e88e [ShellOverflowList] remove ShellOverflowList
Nothing uses ShellOverflowList any more, so remove it. (Even if we
want that sort of functionality again later, we'd want it to be
StWidget-based, and with a name less likely to be confused with
StOverflowBox.)

https://bugzilla.gnome.org/show_bug.cgi?id=621582
2010-06-15 12:02:33 -04:00
df13408973 [dash] remove a bunch of dead code in the dash
The dash has lots of unused code left over from earlier designs. Kill
it.

https://bugzilla.gnome.org/show_bug.cgi?id=621582
2010-06-15 12:00:41 -04:00
bbfc980fe6 add st_texture_cache_load_sliced_image
This function reads a single image file which contains multiple
images internally.
The image file will be divided using @grid_width and @grid_height;
note that the dimensions of the image loaded from @path
should be a multiple of the specified grid dimensions.
https://bugzilla.gnome.org/show_bug.cgi?id=598349
2010-06-14 19:36:55 +04:00
c30b1c9bea Add Thai translation. 2010-06-14 20:28:25 +07:00
9e554097f3 Updated Norwegian bokmål translation 2010-06-14 01:03:55 +02:00
302b892dbc [gnome-shell.in] If XDG_CONFIG_DIRS empty or unset, use default value 2010-06-12 23:13:31 +04:00
c0134067d7 [Transitions] Add error checking when setting up framebuffers
The framebuffer setup code can fail, e.g. when the texture used as
color buffer has a height/width of 0. In that case, the call to
cogl_pop_framebuffer() will crash the shell trigger an assert. Add
error checking to fail gracefully.
2010-06-12 19:33:19 +02:00
a691192ffa [popupMenu] Fix wrong positioning when showing for the first time
We query the transformed position and size of the popupMenu before actually showing
it which results into wrong positioning, when displaying it for the first time.

In case of the statusMenu this can even result into it being offscreen.

https://bugzilla.gnome.org/show_bug.cgi?id=621385
2010-06-12 18:15:52 +02:00
5616a0ae2a Updated Slovenian translation 2010-06-11 22:15:18 +02:00
a4befeba53 De-duplicate "actor contains actor" code
Add _st_actor_contains() in st-private for use within St, and
monkey-patch in a Clutter.Actor.contains() for use by javascript, and
then replace all the duplicate implementations with one or the other
of those.

https://bugzilla.gnome.org/show_bug.cgi?id=621197
2010-06-11 10:05:46 -04:00
e6a70e4676 [statusMenu] Use user status icons from icon theme
Currently, we use 'gtk-yes', 'gtk-no' and 'gtk-media-pause' as
user status icons. It seems more logical to use the dedicated
icons from gnome-icon-theme instead.

https://bugzilla.gnome.org/show_bug.cgi?id=620374
2010-06-11 14:50:50 +02:00
016ab1afee [ShellMenu] remove; no longer used
https://bugzilla.gnome.org/show_bug.cgi?id=619541
2010-06-10 15:04:48 -04:00
748739ed9c [appDisplay] port from ShellMenu to PopupMenu
This fixes the style, and also makes it keyboard navigable

https://bugzilla.gnome.org/show_bug.cgi?id=619541
2010-06-10 15:04:48 -04:00
7fbf8ae4c9 [popupMenu] split this out from panel.js
We want to use this menu style in other places as well

https://bugzilla.gnome.org/show_bug.cgi?id=619541
2010-06-10 15:04:42 -04:00
9914754458 [css] Adjust transition durations
Jeremy does not like slow transitions - he's right.
2010-06-10 19:22:17 +02:00
5a94a1cf3f Updated Galician translations 2010-06-10 17:01:23 +02:00
afadeef204 Remove duplication of non_gir_sources, ensures we only need to add a file once
This also fixes shell-window-tracker-private.h not being in the dist.
2010-06-10 10:34:34 -04:00
f866707101 Updated Hebrew translation. 2010-06-10 12:21:16 +03:00
49919acb7c [StyleTransition] Improve style changes during transitions
Our behavior of reversing the animation when the widget's style
changes back to the previous one is sound. On the other hand, when
there's a change to a new style while a transition is active, we
simply cancel the ongoing transition. Updating the transition
correctly so that the new one starts from an intermediate state
is hard.
Nevertheless, if the style changes before any time of the transition
has elapsed, we should do better than the current behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=621140
2010-06-10 04:06:13 +02:00
f76dae5ec8 Add missing shell-window-tracker-private.h file 2010-06-09 16:23:37 -04:00
bf6d0dc808 Associate process identifiers with applications
Cache the set of pids for an application, in preparation for
landing an XSMP patch which requires this information.

https://bugzilla.gnome.org/show_bug.cgi?id=619542
2010-06-09 14:44:15 -04:00
e4a6bf994f Fix ShellAppSystem's use of no_focus_window, clean up state handling
First, we were passing an incorrect timestamp to
meta_display_focus_the_no_focus_window - fix that.

The invocation of set_focus_app to the started app there couldn't
really work, because (if the above call had worked) we'd get the
X reply *after* the started app.

What we need to untangle here is the distinction that's now made in
ShellApp between _STATE_STARTING and _STATE_RUNNING.  A nice way to
start doing this is to rebase ShellWindowTracker to only be concerned
with app states.  Concretely, the current "has windows implies
running" logic now lives just inside shell-app.c.

Rename the app-running-changed signal to be app-state-changed.  This
will ultimately be useful so that inside the panel, we can track
the last started app.

https://bugzilla.gnome.org/show_bug.cgi?id=620899
2010-06-09 14:44:15 -04:00
3fe7b13959 [workspaceSwitcher] Constrain to monitor size
Currently the workspaceSwitcher does not take the screen size into account
which could result into overflowing the screen.

Fix that but using Shell.GenericContainer instead of St.BoxLayout which takes
the monitor size into account when allocating.

https://bugzilla.gnome.org/show_bug.cgi?id=620404
2010-06-09 19:09:48 +02:00
79aeb44bf8 [appWell] Add padding
Add padding to prevent text from hitting the egde of the box which looks
ugly.

https://bugzilla.gnome.org/show_bug.cgi?id=620997
2010-06-09 18:45:19 +02:00
51478f16ec [runDialog] Fix adding entries to empty history
Before adding a new entry to the history, we check that it does not
match the previous entry to cut down the number of duplicate entries.
Part of that condition is a check for a history length greater zero
to avoid an illegal negative index, with the side effect that nothing
is ever added while the history is empty.

https://bugzilla.gnome.org/show_bug.cgi?id=621123
2010-06-09 18:24:04 +02:00
528930d0a9 [Lightbox] Use a fade effect to smooth the transition
Add show()/hide() methods to Lightbox, which (optionally) fade the
lightbox. Change all lightboxes to fade in smoothly.

https://bugzilla.gnome.org/show_bug.cgi?id=602466
2010-06-09 17:07:10 +02:00
88be8e87ac [Overview] Fade dash menus
As the design calls for smooth transitions whenever possible, use
a similar fade effect for the all-apps and more-docs menus as for
the panel menus.

https://bugzilla.gnome.org/show_bug.cgi?id=620775
2010-06-09 17:07:10 +02:00
b83d5975b0 [appDisplay] Fix crash when app well is empty
When the app well doesn't contain any applications, it displays a placeholder text
to indicate that it's a drop target. When porting WellGrid from St.Bin to St.BoxLayout,
the call to set_child() to set the text was overlooked.
https://bugzilla.gnome.org/show_bug.cgi?id=617281
2010-06-09 17:41:09 +04:00
6ca2fd03bd update Punjabi Translation 2010-06-09 10:45:36 +05:30
87e5457095 [dash] Right align well icons for RTL locales
When changing the alignment of well icons from centered to left,
we should swap it for RTL locales.

https://bugzilla.gnome.org/show_bug.cgi?id=619236
2010-06-08 23:51:16 +02:00
cba49959c1 [dash] Left align well items
When the app well does not contain enough items to fill a single
row, items are centered - the same applies to sections in the
all-app menu.

https://bugzilla.gnome.org/show_bug.cgi?id=619236
2010-06-08 23:10:06 +02:00
7c5343a9fb [searchEntry] Update hover style
Make the hover style of the search entry more distinct, and use
a fade effect of about one second to transition from dim to bright.

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-06-08 23:10:06 +02:00
0e91a213f5 [StThemeNodeTransition] Do not access CoglColor private members directly
We should not access CoglColor members directly since they are private starting with clutter 1.3.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
2010-06-08 21:03:34 +02:00
466f661436 [dash] Add a fade effect when hovering over items
Use a subtle hover transition in order to avoid abrupt visual
changes.

https://bugzilla.gnome.org/show_bug.cgi?id=620782
2010-06-08 20:47:39 +02:00
dad80b3d20 [appWellIcon] Set correct style in constructor
Currently, only the base style class is set in the constructor, the
style update according to the state of the represented app is deferred
until the actor is shown.

As existing icons are destroyed and recreated when the number of icons
changes, this behavior causes the icons of running apps to flicker if
CSS transitions are used.

Set the style directly in the constructor and update the code to not
delay style updates until the actor is shown - StWidget does defer
expensive calculations until the actor is mapped anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=620782
2010-06-08 20:47:39 +02:00
d96d07af10 [searchEntry] Correct some erroneous hover states
As the search entry captures the pointer when activated, the hover
state is not updated properly when the activation is cancelled
(either by clicking outside the entry or by hitting Escape).
Update the state manually in these cases.

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-06-08 20:47:39 +02:00
0e40782723 [StWidget] Cancel transitions if duration is zero
The current code only sets up / updates transitions when the new
node's transition-duration is non-zero. It should cancel an
existing transition if the duration is 0.
2010-06-08 20:37:38 +02:00
7cc1cf3b4a [panel] Use the same fade effects as menus
Currently, the buttons change their background immediately when
activated, while the menus fade in quickly - instead, make buttons
use the same effect as the menus.

https://bugzilla.gnome.org/show_bug.cgi?id=619240
2010-06-08 19:32:16 +02:00
702f596c44 [boxPointer] implement the other arrowSide values
https://bugzilla.gnome.org/show_bug.cgi?id=619541
2010-06-08 12:19:42 -04:00
db45c0920b [StWidget] Support style transitions
It is sometimes desirable to fade smoothly between two styles
instead of changing it abruptly.
Add transitions controlled by the transition-duration CSS property.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
2010-06-08 17:55:51 +02:00
d4a8c64d22 [StThemeNode] Add transition-duration CSS property
Add a CSS property to control style transitions.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
2010-06-08 17:55:50 +02:00
0deffbaaf0 [St] Add StThemeNodeTransition
Introduce a small helper class in order to add transitions between
theme nodes to StWidget.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
transition update
2010-06-08 17:55:50 +02:00
af3ca027a1 [StThemeNode] Add helper method to get the paint allocation
StThemeNodes may have properties - namely shadows - which paint
outside an actor's allocation. This is not a problem unless drawing
is redirected to an offscreen buffer, in which case the actually
painted size is needed in advance when setting up the buffer.

Add a convenience method to calculate an allocation large enough to
paint the node.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
2010-06-08 17:55:41 +02:00
24a4ca0c6d [StThemeNode] Add a comparison function
Add st_theme_node_equal() - two nodes are considered equal iff they
refer to identical elements, so e.g. .example and .example:hover are
not equal, even if no .example:hover rule exists in the CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
2010-06-08 17:55:40 +02:00
e1a109b9be [panel] Fix translatable strings
There are some strings in panel.js which are not extracted correctly.
Fix by marking them correctly with double quotes and _().
2010-06-08 17:13:26 +02:00
8aeadcdf9a Don't try to track remote windows
Previously we were trying to match up remote windows with local
.desktop files, which is definitely wrong.  This patch simply
falls back to the app-from-window case for this; better handling
would need design.

https://bugzilla.gnome.org/show_bug.cgi?id=620855
2010-06-07 16:39:39 -04:00
68bc5baf12 Check for availability of mallinfo()
Fixes the build on FreeBSD.

Signed-off-by: Colin Walters <walters@verbum.org>
2010-06-07 10:37:00 -04:00
8da5c5f50e Remove incorrect parameter
Commit 730681aabc calls ClutterActor.hide() with a parameter, which
is wrong, but managed to sneak in when rebasing.
2010-06-06 21:43:03 +02:00
084ef99d10 [allApps] Reorder sections
Reorder the menu sections using a DefaultLayout element to
enforce Apps, Games, Tools rather relying on them
being ordered alphabetically.
2010-06-06 19:26:13 +02:00
730681aabc [Overview] Lightbox workspaces on menu popup
Overlay a translucent rectangle to dim the workspaces/dash rather
than setting the workspaces' opacity.
Also slightly darken all lightboxes.

https://bugzilla.gnome.org/show_bug.cgi?id=602466
2010-06-06 19:05:19 +02:00
efd30a0eef [l10n] Updated Italian translation 2010-06-06 14:48:25 +02:00
3d60245b18 Add sections to the all apps view
Separate out the main app view into different sections based on the categories
in the desktop file. The configuration is done via gmenu and the desktop menu
specification, we set XDG_MENU_PREFIX="gs-" on startup, so that gmenu reads
gs-applications.menu, which we install.

There is no support for "submenus" - only the menus directly under
Applications will be displayed as categories.
https://bugzilla.gnome.org/show_bug.cgi?id=614131
2010-06-06 02:53:27 +04:00
ccbf247970 Relayout on monitor layout changes
Currently we only relayout when the screen size changes, this gets
 the cases where a monitor gets added/removed but not when the primary
 monitor changes.

 We need to relayout on all monitor layout changes.

 Remove ShellGlobal::screen-size-changed signal as it is no longer used, Gdk is
 used to track changes now.

 A ShellGlobal::gdk-screen property is added for this purpose.

https://bugzilla.gnome.org/show_bug.cgi?id=620377
2010-06-04 15:20:04 +02:00
84efaac52b Exit the overview when activating most items
In all the cases where we activate GNOME 2 UI, e.g. the shutdown
dialog, pop out of the overview.  Otherwise, it's fairly broken
since you won't see the result of your action.

https://bugzilla.gnome.org/show_bug.cgi?id=620525
2010-06-03 20:29:26 -04:00
8f5aae6df6 Updated Galician translations 2010-06-03 23:35:02 +02:00
35f27ae150 [lookingGlass] Fix scrolling in errorLog
When setting line_wrap, we need to unset the ellipsization, otherwise
ClutterText won't do what we want.
2010-06-03 12:51:16 -04:00
d387a2d531 Updated Hebrew translation. 2010-06-03 16:32:11 +03:00
63d84533c9 [ClockButton] Add a right-click menu to the clock
The clock preferences are hardly discoverable, so allow launching
them from a right-click menu.

https://bugzilla.gnome.org/show_bug.cgi?id=600276
2010-06-03 11:43:58 +02:00
fe91f7fe9e [overview] Fix dnd on mulit screen setups
Currently we don't get any drop events for dual screen modes with a screen
at the right, and behave weird by hardcoding the screen size and 0 as drag
edges.

Fix that by spawning the drop group over the whole stage and take the primary monitors position and size into account in _handleDragOver.

https://bugzilla.gnome.org/show_bug.cgi?id=620378
2010-06-03 11:35:51 +02:00
cc163237cc [StEntry] Consider children when setting hover state
When hovering over the entry's ClutterText, the entry itself
currently receives a leave event and updates the hover state.
Apply the same logic as StWidget itself to treat children as
part of the entry.

https://bugzilla.gnome.org/show_bug.cgi?id=620381
2010-06-02 23:21:13 +02:00
4acb082b6e Added Indonesian translation
Added id into LINGUAS
2010-05-31 19:46:11 +07:00
929bf7f989 [lookingGlass] Don't connect multiple times to the "unmanaged" signal 2010-05-30 22:54:35 +02:00
e3eaa69948 Add ISO week dates to the calendar
This patch adds ISO week dates to the calendar. Week dates are an
often used feature in business and government offices. Can be turned
on through gconf, off by default.

https://bugzilla.gnome.org/show_bug.cgi?id=603532
2010-05-28 01:31:33 +02:00
155bee388d Updated Polish translation 2010-05-27 23:18:56 +02:00
2ca70e9e76 [workspaceSwitcher] Display on primary monitor
Display it only on the primary monitor to be consistent with other
elements like the appSwitcher, messageTray and the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=619854
2010-05-27 20:10:19 +02:00
d31e905978 [appSwitcher] Display on primary monitor
Displaying it on the focused monitor seems to confuse users so revert back to
using the primary monitor as per designer's request.

https://bugzilla.gnome.org/show_bug.cgi?id=619854
2010-05-27 20:09:59 +02:00
a57a34c540 [linearView] Zoom out when dragging an item from the dash
When dragging windows in linear view, the workspace zooms out to
allow moving the window to other workspaces. Enable the same
behaviour for items dragged from the dash.

https://bugzilla.gnome.org/show_bug.cgi?id=618055
2010-05-27 12:12:10 +02:00
b3794f1c17 [linearView] Fix dnd to dash when zoomed out
While zoomed out, the workspaces view's drop target spans the entire
monitor to implement reactive screen edges. When a drop event is not
handled by the view, an attempt is made to pass it on down the stack,
but it doesn't work properly. Fix it by iterating the target's parents
as well.
Also improve the code which translates dnd coordinates to target
positions.

https://bugzilla.gnome.org/show_bug.cgi?id=619203
2010-05-27 12:12:10 +02:00
5b971a66ba [perf] Write UTC dates into performance logs
Instead of writing a local date without a timezone, write a UTC
date with a trailing Z.
2010-05-26 16:54:16 -04:00
77fcf68ea3 [chrome] Ignore fullscreen flag when in overview
Ignore the fullscreen flag when we are in the overview,
otherwise we might up not showing actors like the panel even though
they have visibleInOverview set to true.

https://bugzilla.gnome.org/show_bug.cgi?id=619693
2010-05-26 22:14:00 +02:00
15dd1164b7 [perf] replace frame count with accurately computed frame rate
Compute a frame rate for the period between:

 - User sees first frame of overview animation
 - User sees fully zoomed-out overview

And replace the current Frames count metrics with this. The
previous frame count metrics were actually over the period from
the start of the animation until the window labels finished
animating in; here we are careful to look at a more restricted
period.

https://bugzilla.gnome.org/show_bug.cgi?id=619521
2010-05-26 15:37:27 -04:00
0eeb62794d [perf] Add glx.swapComplete event
Add an event when we receive an event on buffer swap completion; we'll
only get this if Clutter is using the INTEL_swap_event GLX extension,
but it's useful to see the actual timing of video frames.

The recorded event includes the actual timestamp of the swap, since
we are given that in the GLX event - on my system it tends to be
consistently 80-100us before we log the event, but if something was
going wrong in event handling (too much synchronous work), then that
could could show up as a longer delay.

https://bugzilla.gnome.org/show_bug.cgi?id=619516
2010-05-26 15:37:27 -04:00
07cfb8d524 [perf] add tweener.framePrepareStart/Done events
Add events when we start preparing a frame and finish preparing
a frame. (In addition to measuring property-updating overhead, this allows
us to see the interval between finishing preparing a frame and starting
painting the frame, which is the relayout time.)

https://bugzilla.gnome.org/show_bug.cgi?id=619515
2010-05-26 15:37:27 -04:00
3e2a9a57a1 [dnd] Optionally restore the drag actor
Currently, the drag and drop code assumes that on a successful drop
the target will either consume the drag actor or that it is otherwise
OK to destroy the actor.
As the drag behavior for window preview was changed, dropping a preview
on the dash now results in the preview being swallowed - to fix, add an
option to restore the actor in case of a successful drop as well.

https://bugzilla.gnome.org/show_bug.cgi?id=619203
2010-05-26 14:06:53 +02:00
a0be7fa455 [panel] Hide application menu in overview
The activities overview is not a place where we expect users to
interact with a specific application, so showing the application
menu there is misleading.

https://bugzilla.gnome.org/show_bug.cgi?id=618479
2010-05-26 14:06:53 +02:00
a433a1c637 [StThemeNode] Make shadows respect paint opacity
Currently shadows disregard the overall opacity, so e.g. setting
an ancestor's opacity does not effect the shadow. Fix this by
deferring the setting of the shadow's color until it is painted.
Also move duplicated drawing code from st_theme_node_paint() into
its own function.

https://bugzilla.gnome.org/show_bug.cgi?id=619083
2010-05-25 23:03:15 +02:00
d05cf2445d [StWidget] Clean up private member variables
When moving the drawing code into StThemeNode, most private members
of StWidget became obsolete, so remove them.

https://bugzilla.gnome.org/show_bug.cgi?id=619025
2010-05-25 23:03:15 +02:00
764f5b62f0 [clockPreferences] Fix translations
The preference dialog for the panel clock does not set its gettext
domain, so it's not translated even if though translations are
already available.
Fix by setting the domain in the GtkBuilder file and binding the
domain to the locale directory.

https://bugzilla.gnome.org/show_bug.cgi?id=618873
2010-05-25 23:03:15 +02:00
03a0809e39 Use St.Group where appropriate
There are some places in the code where we use both fixed positioning
and CSS. Currently we use either a combination of ClutterGroup and StBin,
or we uses StBoxLayout with fixed positioning. Replace those with the new
StGroup container.

https://bugzilla.gnome.org/show_bug.cgi?id=613907
2010-05-25 23:03:14 +02:00
f0645d468c [StGroup] Respect CSS sizing in size requests
Currently the size of an StGroup depends exclusively on the group's
children - it should be possible to override this behaviour with
fixed values in the CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=613907
2010-05-25 23:03:14 +02:00
ea3b2a5707 Update versions for 2.31.2
Update the GNOME Shell version to 2.31.2, and make corresponding
updates to dependencies:

 clutter => 1.2.8
 mutter => 2.31.2
 gobject-introspection => 0.6.11
 gjs => 0.7
2010-05-25 15:22:42 -04:00
25eaf2a294 Updated Spanish translation 2010-05-25 18:31:50 +02:00
7bf748c579 [StTable] Align children to integral positions
Like the other St widgets, ensure we position children at integrals.

https://bugzilla.gnome.org/show_bug.cgi?id=619623
2010-05-25 11:21:34 -04:00
04f33e8dc7 [StTable] Clamp children to integral positions 2010-05-25 11:00:50 -04:00
01c493565f [panel] Ellipsize long application titles, don't push clock around
First, simply set the ellipsize flag on the application menu labels.
Next, rework how we lay out the panel components so that the center
box is always centered and constrains the left and right, rather
than pushing it around.

Previously, as part of making the shell not obviously explode if
one had a lot of tray icons, we allowed them to push the clock over.
Instead, go back to just failing in this case; we need to exile legacy
tray icons, not be slightly less ugly.

https://bugzilla.gnome.org/show_bug.cgi?id=592640
2010-05-25 10:40:15 -04:00
f1e3104128 Do not fail if json Python module is not available
Fallback to old simplejson module if present, and options that require
the json module (create extension and performance) if absent.

https://bugzilla.gnome.org/show_bug.cgi?id=619580
2010-05-25 16:32:56 +02:00
2ace472100 updating for punjabi 2010-05-25 19:32:44 +05:30
fff04d51b7 [panel] fix alignment of app menu label
we were aligning the top of the shadow with the top of the other labels,
rather than aligning the label itself

https://bugzilla.gnome.org/show_bug.cgi?id=618793
2010-05-25 09:34:01 -04:00
a1bfaac5a2 [appSwitcher] Remove unneeded workaround
SwitcherList.actor is no longer a St.BoxLayout but a
GenericContainer now, so the hack in AppSwitcher._getPreferredHeight is no
longer needed (it is called with the correct width now).

https://bugzilla.gnome.org/show_bug.cgi?id=613194
2010-05-24 16:52:38 +02:00
d80c1af1a3 Updated Norwegian bokmål translation 2010-05-24 16:29:32 +02:00
cbde065a01 [perf] Fix factor of ten in seconds => microseconds conversion
Typo: 10000000 instead of 1000000 for a million. Also, use
G_INT64_CONSTANT instead of LL for a 64-bit constant, to avoid
extraneous 128-bit arithmetic on 64-bit machines.
2010-05-24 00:09:40 -04:00
0b1c7320ab Fix "make distcheck" - add missing reference for scripting.js - properly add js/perf/*
https://bugzilla.gnome.org/show_bug.cgi?id=619276
2010-05-22 18:02:52 +02:00
ce3f003e46 Call shell_global_maybe_gc() when no work is being done
Call shell_global_maybe_gc when idle when no other work is ongoing to free
up memory and improve performance by preventing the GC to kick in at less
convenient times.

See: https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_MaybeGC

https://bugzilla.gnome.org/show_bug.cgi?id=614725
2010-05-21 23:47:41 +02:00
9fca747ef4 shell-global: Add shell_global_maybe_gc
Add a method to call JS_MaybeGC, see
https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_MaybeGC

https://bugzilla.gnome.org/show_bug.cgi?id=614725
2010-05-21 23:47:25 +02:00
9455554453 Updated Slovenian translation 2010-05-21 20:03:38 +02:00
4859eb63c4 [perf] Add --perf-upload option to gnome-shell
Add a command line option to upload the generated performance report
to a web service. The options for the upload (url, system name, secret
key) are read from ~/.config/gnome-shell/perf.ini.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 12:34:22 -04:00
e7220591ba [perf] Include monitor layout in performance reports
Add extra key, 'monitors' to performance reports which is an
array of strings:

 *<width>x<height>+<x>+<y>

Where * marks the primary monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 12:34:10 -04:00
20d579e7d8 Add units to metrics definitions
Switch from having separate METRICS and METRIC_DESCRIPTIONS objects
in a perf module to a single METRICS array. This is done so the
perf module can define the units for each metric.

In addition to improving the output in the web interface, the purpose
of having units is to give some clue about how to pick from multiple
values from different runs. In particular, with the assumption that
"noise" on the system will increase run times, for time values we want
to pick the smallest values, while for "rate" values, we want to pick
the largest value.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
52a68eb24a Add an option to dump a complete performance report
Add --perf-output=<filename> option to gnome-shell that combines
the reports written for each run by the C/Javascript code into
a complete report.

If this option is not specified, a brief human-readable summary
is printed to stdout instead.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
bc57574094 Dump a complete report from a performance run, as JSON
When SHELL_PERF_OUTPUT is set, instead of just dumping out the metrics, dump
a more complete report with:

 - Event descriptions
 - Metric descriptions and value
 - Event log

Helper functions shell_perf_log_dump_events() and shell_perf_log_dump_log()
are added to ShellPerfLog to support this. The gnome-shell wrapper is adapted
to deal with the changed report format.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
e4e92a2b38 Add shell_write_string_to_stream()
Add a helper function to write a string as UTF-8 to a GOutputStream.
The signature of GOutputStream:

 gboolean g_output_stream_write_all (GOutputStream *stream,
                                     const void *buffer,
                                     gsize count,
                                     gsize *bytes_written,
                                     GCancellable *cancellable,
                                     GError **error);

Can't currently be handled by GJS.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
023a274e41 Allow running multiple iterations of a performance test
Add gnome-shell options:

  --perf-iters=ITERS"
    Numbers of iterations of performance module to run
  --perf-warmup
    Run a dry run before performance tests

Make a successful run of a performance test return 0 not non-zero,
and handle the difference between that and a 0-exit in normal
usage (meaning replaced) in the wrapper.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
5d0536d732 Move shell-running machinery to a function
Move the code that starts gnome-shell and waits for it to exit
to a function in preparation for running it multiple times when
doing iterations of a performance test.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
08b8b39a5d Add simple malloc statistics and metrics
Add some basic statistics for allocated memory based on mallinfo(),
and use that to define two metrics:

 usedAfterOverview: bytes used after the overview is shown once
 leakedAfterOverview: additional bytes used when the overview is
   shown a second time.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:45 -04:00
c972ff3ab4 Add "statistics" functionality to ShellPerfLog
Add a facility for defining and recording numeric statistics
as performance events

 shell_perf_log_define_statistic()
   Define a statistic and the corresponding event type
 shell_perf_log_update_statistic_[ix]() -
   Update the stored statistic value
 shell_perf_log_add_statistics_callback()
   Add a function called before collecting statistics
 shell_perf_collect_statistics()
   Update statistics and record events for them

In addition to the explicit collection, statistics are
recorded at a periodic interval (currently 5s)

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-21 00:18:40 -04:00
98c2247c1b Add a facility for automated performance measurement
We want to be able to summarize the behavior of the shell's
performance in a series of "metrics", like the latency between
clicking on the Activities button and seeing a response.

This patch adds the ability to create a script under perf/
in a special format that automates a series of actions in the
shell, writing events to the performance log, then collects
statistics as the log as replayed and turns them into a set
of metrics.

The script is then executed by running as gnome-shell
--perf=<script>.

The 'core' script which is added here will be the primary
performance measurement script that we use for shell performance
regression testing; right now it has a couple of placeholder
metrics.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-20 23:41:47 -04:00
a97b8c1947 Add events before and after stage paint
Add performance events:

 clutter.stagePageStart
 clutter.stagePageDone

to track frame repaints.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-20 23:41:46 -04:00
1dd2f2c6bc Add ShellPerfLog
ShellPerfLog provides a way for different parts of the code to
record information for subsequent analysis and interactive
exploration. Events exist of a timestamp, an event ID, and
arguments to the event.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-20 23:41:40 -04:00
a9a513c621 Add "leisure function" capability
To support scheduling performance-measurement scripts that want to run
a number of actions in series, add shell_global_run_at_leisure() to run
a callback when all work is finished.

The initial implementation of this is not that accurate: we track
business in Tweener.js via new shell_global_begin_work(),
shell_global_end_work() functions, and we also handle the case
where the main loop is continually busy.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
2010-05-20 23:21:44 -04:00
2ce746e7dd [ShellAppSystem] Don't crash if the menu system is empty
This is a bit pathological, but if your menu tree is empty, we
shouldn't crash.
2010-05-20 17:06:30 -04:00
11cde53108 [main] Explicitly require the Clutter and Gtk versions we want
By default introspection will use "latest", which blows up with
Gtk3.
2010-05-20 17:03:43 -04:00
fe542f8732 Add a hack to block calls to certain introspected functions
This is useful for keeping people from using methods that only fail in
certain circumstances, by making them fail in all circumstances
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=618918
2010-05-20 15:49:16 -04:00
91319d5da2 changed 'y_fill' of '_clockButton' in panel to false
The clock appeared to high compared to the activities button
or the login name. Might be just me though.

https://bugzilla.gnome.org/show_bug.cgi?id=619144
2010-05-20 13:01:45 -04:00
5bd7b0dc31 [panel] fix button corners: they should only be rounded on the top 2010-05-20 12:05:22 -04:00
c8f4adde7f [panel] fix nested-queue_relayout warning in menus
We don't need to reposition the menu every time its button is
allocated; we can just stick it in the right place when we pop it up
(which is guaranteed to not be during a layout cycle).

(This means that now we won't reposition the menu if the button
moves/resizes while the menu is already popped up, but it's not clear
that we'd want it to anyway, since that could easily result in the
user selecting the wrong item, etc.)

Also, we don't need to override the menu's width any more, so remove
that.

https://bugzilla.gnome.org/show_bug.cgi?id=619113
2010-05-19 17:06:35 -04:00
b6a47cdf76 [telepathy] fix a bug in a last-second fix to the notification changes
https://bugzilla.gnome.org/show_bug.cgi?id=619044
2010-05-19 16:54:33 -04:00
8b242dd4bd minor js cleanups
add missing semicolons pointed out by js2-mode, add missing emacs
modelines, fix a few tabs that crept in via cut+paste
2010-05-19 13:26:41 -04:00
9b3e16595b [panel] add keyboard navigation of menus
https://bugzilla.gnome.org/show_bug.cgi?id=619008
2010-05-19 13:16:22 -04:00
2179f5836e [panel] separate "active" state from hover state in PanelBaseMenuItem
When doing keyboard navigation, the active menu item may not be the
one under the mouse.

https://bugzilla.gnome.org/show_bug.cgi?id=619008
2010-05-19 13:15:46 -04:00
320adb316d [panel] split out a PanelBaseMenuItem class
Make the existing PanelMenuItem, PanelSeparatorMenuItem,
PanelImageMenuItem inherit from it.

https://bugzilla.gnome.org/show_bug.cgi?id=619008
2010-05-19 13:15:46 -04:00
db36a90c48 Combination of updates to match design suggestions
* Align the icons inside text
* Add application name to Quit
* Fade in/out the menu
* Drop some padding around the edges
* Add padding around the separators
* Use a gradient for separators

https://bugzilla.gnome.org/show_bug.cgi?id=618460
2010-05-19 12:31:19 -04:00
5cfd72ff8b Updated German translation 2010-05-18 22:08:28 +02:00
1d721c9080 [panel] add some missing semicolons 2010-05-18 13:16:24 -04:00
5de1a15d98 magnifier: use global.get_pointer instead of gdk_window_get_pointer
(qv https://bugzilla.gnome.org/show_bug.cgi?id=597292)

https://bugzilla.gnome.org/show_bug.cgi?id=618915
2010-05-17 14:46:26 -04:00
b02089c435 Updated French translation 2010-05-17 20:24:47 +02:00
ccdc6264da Remove markup from translatable strings 2010-05-17 20:24:33 +02:00
b736f52037 Rework compare to take into account closed windows
The API docs for ShellApp claimed it sorted by the last time the
user interacted with the app, but if one closed a window, then
we would fall back to comparing against a possibly much older
timestamp from another window.  Fix this by just keeping a
user time per app.

Also clean up the comparison function to explicitly check the state
instead of deferring to the window list.

https://bugzilla.gnome.org/show_bug.cgi?id=618378
2010-05-17 13:37:13 -04:00
1af392b5f0 Allow selection of individual windows
Per design discussion, change things back so that when choosing
an individual window, we raise only that window.  However
when we select an application, raise all windows.

A behavioral change required to clearly differentiate these
is that when the window thumbnail list is popped up, it no
longer has the first window selected by default.  Therefore
the user has to explicitly press the down arrow or use the
mouse to enter individual window selection mode.

https://bugzilla.gnome.org/show_bug.cgi?id=617959
2010-05-17 13:17:56 -04:00
84716bccd4 Create ShellGlobal later to avoid connecting to X during build
The ShellGlobal initialization performs several actions like connecting
to the X server, ensuring directories exist, etc., that are problematic
because we were creating the object even when running the binary for
introspection scanning.  During compilation we may not even have X11
available in e.g. autobuilder type environments, and it's just a
bad idea to connect even if we do.

Avoid this by deferring creation of the ShellGlobal object
until the plugin is actually started.

Now that we're initializing things later, remove the connection to
screen changes, and initialize cached ShellGlobal state at the point
when the plugin is set.  The root pixmap actor is now sized initially
on creation too.  Instead of relying on screen-size-changed being
emitted on startup, explicitly invoke _relayout().

https://bugzilla.gnome.org/show_bug.cgi?id=618371
2010-05-17 13:04:38 -04:00
f438ccfc53 TelepathyClient: show notifications for presence changes
Fetch the names of the user's "subscribed" contacts, and use the
SimplePresence interface to watch for available/away/busy/etc messages
and create notifications for them.

Currently we display notifications when switching between "available"
and "offline"/"extended away", but when switching between "available"
and "away"/"busy" we just add the information to the chat window
without popping up a notification, to avoid spamming the user with
"Bob's screensaver activated" messages.

https://bugzilla.gnome.org/show_bug.cgi?id=611613
2010-05-17 09:58:36 -04:00
fdd819e9f6 TelepathyClient: track added/removed accounts
(prep work for presence tracking)

https://bugzilla.gnome.org/show_bug.cgi?id=611613
2010-05-17 09:55:31 -04:00
a3a09e6b2e TelepathyClient: rename AvatarManager to ContactManager
and belated rename info.token to info.tokens

https://bugzilla.gnome.org/show_bug.cgi?id=611613
2010-05-17 09:48:09 -04:00
7160e8a137 TelepathyClient: Simplify the channel filter specifications
https://bugzilla.gnome.org/show_bug.cgi?id=611613
2010-05-17 09:48:09 -04:00
016ad69550 [lookingGlass] Remove Properties tab, replace with popup object inspector
Make inspecting objects more dynamic by turning them into links which
pops up a dialog, rather than the more clunky tab interaction.
2010-05-17 09:30:55 -04:00
42e9b21b24 Updated German translation 2010-05-16 21:05:05 +02:00
b6e3bf198d Updated Spanish translation 2010-05-16 11:00:38 +02:00
5e3eb5e8c3 [po] Add type annotation to GtkBuilder files
Due to missing intltool support, translatable strings in the
clock preferences dialog are not added to the pot file.
2010-05-16 00:55:04 +02:00
ed1dc4649b Updated Arabic translation 2010-05-15 23:40:19 +03:00
5b586fdf3e Updated Slovenian translation 2010-05-14 21:53:53 +02:00
703b21cef0 Don't use double quotes for things that don't need to be translated
This is our convention.

The only exceptions are double quotes for words in comments that give
them a special meaning (though beware that these quotes are not truly
necessary most of the time) and double quotes that need to be a part
of the output string.
2010-05-13 16:00:38 -04:00
c7ec84eb33 Updated Spanish translation 2010-05-13 21:14:48 +02:00
4ce2620b68 Don't add a new workspace when the maximum workspaces limit is reached
It was previously possible to add a workspace above the maximum workspaces
limit by dragging an item to the "add workspace" button or using the middle
mouse button click.

Provide the user with feedback in the info bar when it is not possible to create
a new workspace or remove the current workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=591645
2010-05-13 14:30:52 -04:00
ec6bc8f216 Make the workspace added on the middle mouse button click active
This ensures that we launch the new instance of an application on the newly
added workspace in the grid view, in which we don't make the newly added
workspace active by default.

https://bugzilla.gnome.org/show_bug.cgi?id=591645
2010-05-13 14:30:52 -04:00
47a92e7fc0 Don't treat min-width and min-height as a fixed size
I have no idea why there existed code that if we saw e.g. min-width
without a width, we assigned min-width to ->width, thus effectively
treating it as a maximum.

Just delete that bit.

https://bugzilla.gnome.org/show_bug.cgi?id=618482
2010-05-13 13:15:39 -04:00
e835cd2c2d [panel] PanelImageMenuItem should follow gtk-menu-show-images
Update statusMenu to always show images for the presence items only.

https://bugzilla.gnome.org/show_bug.cgi?id=618438
2010-05-12 17:25:51 -04:00
6098dca0f8 Always hide the info bar after a short timeout
We no longer want to keep the info bar showing for as long as the user is
in the overview. We also want a shorter timeout.
2010-05-12 16:44:49 -04:00
21ff050a40 Add a new way to open an application on a new workspace
Allow using the middle mouse button to open a new instance of an
application on a new workspace. The middle mouse button function
can be achieved by clicking the left and right mouse buttons
together with a two buttons mouse or holding Ctrl while clicking
with a single button mouse.

https://bugzilla.gnome.org/show_bug.cgi?id=591645
2010-05-12 20:30:00 +02:00
508001bfde Updated Slovenian translation 2010-05-12 14:36:55 +02:00
410dfb2da3 Use gdk_screen_get_primary_monitor on gtk-2.20.1+
Starting with gtk-2.20.0 there is a gdk_screen_get_primary_monitor,
which supports querying the primary monitor from xrandr.

But due to a sorting bug and lack of heuristics in the fallback path,
it isn't really useable.

Those bugs are fixed in gtk-2.20.1, so use it when building with
gtk-2.20.1+.

https://bugzilla.gnome.org/show_bug.cgi?id=608647
2010-05-12 09:35:32 +02:00
74ccdbf3a9 St: fix allocation to not use both wfh and hfw
Passing an explicit width in the wfh case or a height in the hfw case
messes up the request caching, and confuses actors that assume they
won't be called with an explicit width/height unless they're being
allocated along the other axis.

https://bugzilla.gnome.org/show_bug.cgi?id=618295
2010-05-11 15:58:54 -04:00
80fc55b8ea Add shell-xfixes-cursor.[ch]
Also missing somehow from the magnification commit.
2010-05-11 15:03:11 -04:00
dc424280a1 Add missing magnifier files from the last commit
Also, this patch differs from the one in Bugzilla
in that we start/stop tracking the mouse depending
on whether the magnifier is active.
2010-05-11 15:00:07 -04:00
7b7c34a399 Adds magnifier functionality to gnome-shell.
Adds the ability to create one or more zoom regions that show magnified or
enhanced views of the desktop.  The magnifier provides options for:
* magnification factor,
* four mouse tracking modes common to screen magnifiers,
* positioning the magnified view in one of four screen location, or full screen,
* crosshairs to accentuate the position of the mouse,
* user preferences persistence via GConf (schemas in
  .../data/gnome-shell.schemas).
* a DBus API to allow other processes to drive the magnifier as a service.

https://bugzilla.gnome.org/show_bug.cgi?id=595507
2010-05-11 14:52:25 -04:00
865976cfe7 Updated Spanish translation 2010-05-11 20:44:28 +02:00
81a497b476 Add boxpointer.js to Makefile.am 2010-05-11 20:36:13 +02:00
dc1a6c746d [statusMenu] Update callback prototype for activate signal
When porting, we now have an 'event' arg.
2010-05-11 14:20:01 -04:00
27bcce0888 [panel] Port user status menu to panel menu
https://bugzilla.gnome.org/show_bug.cgi?id=613804
2010-05-11 14:10:36 -04:00
fdcb73d93e Make panel more menu-like, initial application menu
Change the panel into a menu-like actor, where elements can
add menu items.

Implement the initial application menu.

https://bugzilla.gnome.org/show_bug.cgi?id=613804
2010-05-11 14:10:36 -04:00
47dae0832b New widget: BoxPointer
Implement a rounded box with an arrow pointer.

https://bugzilla.gnome.org/show_bug.cgi?id=613804
2010-05-11 14:10:35 -04:00
78e3126f97 [ShellApp] Add quit method
Closes the app, will be used for the panel app menu.  Note
this is just a very primitive implementation.

https://bugzilla.gnome.org/show_bug.cgi?id=613804
2010-05-11 14:10:35 -04:00
12e45f275b Updated Norwegian bokmål translation 2010-05-11 19:51:08 +02:00
7b32888322 Updated Spanish translation 2010-05-10 23:06:16 +02:00
44c2027b40 linearView: Cancel workspace scrolling when the user stops dragging
Currently there is no way for the user to cancel a workspace drag action,
which means the user has to complete the drag action before and move back
to the other workspace manually afterwards.
So cancel the drag action when the user stops.

https://bugzilla.gnome.org/show_bug.cgi?id=618062
2010-05-10 21:28:26 +02:00
a90c81b2c7 Add missing gtk_widget_get_allocation()
In the change from widget->allocation to gtk_widget_get_allocation(),
one addition of gtk_widget_get_allocation() was missed. Add it.
2010-05-10 14:29:44 -04:00
8a25d49319 [SearchEntry] Add a glow effect when activated
(Ab)use -st-shadow to add a glow effect to the activated search entry,
matching the latest mockups.

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-05-10 20:17:28 +02:00
014ac2d388 Support -st-shadow for all background properties
Extend the existing support for -st-shadow to apply to the background,
background-gradient and border properties in addition to background-image.

https://bugzilla.gnome.org/show_bug.cgi?id=613832
2010-05-10 20:17:20 +02:00
1e3bf0ea7e Add StGroup container
Currently if we want a stylable fixed-layout container, we use either
a Clutter.Group inside an St.Bin, or we abuse St.BoxLayout.

https://bugzilla.gnome.org/show_bug.cgi?id=613907
2010-05-10 19:59:28 +02:00
54d11b65a1 Move shared container methods from st-private to a common base class
Add StContainer, which implements the ClutterContainer interface based
on the container methods in st-private and make the existing containers
subclass it.

https://bugzilla.gnome.org/show_bug.cgi?id=613907
2010-05-10 19:00:07 +02:00
6318c8e95b Add compatibility with GTK+ 2.18
To replace all calls to deprecated code, GTK+ 2.20 is required - add
some basic compatibility code, so that is still possible to build the
shell with GTK+ 2.18 when not using -DGSEAL_ENABLE.

https://bugzilla.gnome.org/show_bug.cgi?id=618258
2010-05-10 18:31:51 +02:00
8c5bb8655d Use accessor functions instead of direct access
With the transition to GTK+ 3.0, direct access to struct members
will no longer be possible.
This bumps the required minimum version of GTK+ to 2.20.

https://bugzilla.gnome.org/show_bug.cgi?id=618258
2010-05-10 18:31:51 +02:00
75b52d36f2 Do something reasonable for width-for-height sizing
The StTable code only supports height-for-width. When called in
width-for-height sizing mode, instead of treating the -1 flag
value of 'for_width' as a real width, and requesting all the
children at 1 pixel wide, use the natural width of the table
as the width for determing the height.

Since we can't rewrap in width-for-height mode, we then report
the natural width also as the minimum width of the table.

https://bugzilla.gnome.org/show_bug.cgi?id=618104
2010-05-10 11:41:23 -04:00
5111edb80b Use a St.Bin rather than a St.BoxLayout for calendar popup
Using a horizontal St.BoxLayout for calendar container forces
width-for-height layout on the St.Table child. Since St.Table
is naturally width-for-height, this can trigger bugs and is,
at best, a bit ineffecient. Use a St.Bin instead since we don't
need any BoxLayout features.

https://bugzilla.gnome.org/show_bug.cgi?id=618104
2010-05-09 16:37:08 -04:00
c4406d4ace Make getting the environment from gnome-session more robust
readlink() on /proc/<pid>/exe can have results like:

 /usr/bin/gnome-keyring-daemon.#prelink#.5DFZsF (deleted)
 /usr/bin/gnome-session (deleted)

To find gnome-session in a more robust way, read /proc/<pid>/cmdline
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=616706
2010-05-09 16:35:34 -04:00
3bd2f75866 Updated Slovenian translation 2010-05-09 21:02:33 +02:00
6360d8bba6 Updated Slovenian translation 2010-05-09 20:59:54 +02:00
f104a329b0 Fix distcheck for clock-preferences
- Add new files to POTFILES.in/POTFILES.skip
- Mark clock-preferences.ui as dist_pkgdata_DATA
2010-05-09 09:47:49 -04:00
0e9c47bd56 [overview] Fix positioning of single small windows
A single window that does not need to be scaled down, should be centered
and not placed at the bottom.

To avoid blurryness window positions should be pixel aligned.

https://bugzilla.gnome.org/show_bug.cgi?id=617827
2010-05-09 14:18:42 +02:00
2ca1fe3254 [workspacesView] Animate showing/hiding of controls
Some of the workspace view controls are hidden when the number of
workspaces is one (view toggle button, scroll bar in single view).
Use a fade effect instead of showing/hiding the control abruptly.

https://bugzilla.gnome.org/show_bug.cgi?id=613456
2010-05-09 10:46:32 +02:00
88211ed4bb [linearView] Animate scroll bar size changes
When adding/removing workspaces in linear view, both workspaces and
scrollbar movement are animated, but the size of the scrollbar handle
changes abruptly. It is more consistent to animate the size change
as well.

https://bugzilla.gnome.org/show_bug.cgi?id=613456
2010-05-09 01:48:23 +02:00
266a0fb7d6 Add a simple preference dialog for the clock
Port the 'General' preferences tab of the panel's clock applet to
javascript and add it to the build system.

https://bugzilla.gnome.org/show_bug.cgi?id=600276
2010-05-09 01:07:47 +02:00
e6b91414de [panel] Make clock configurable via gconf
Add keys for customizing the panel clock to the gconf schema and make
the clock use them. The settings are copied from gnome-panel's clock
applet, excluding all location/weather/appointment/... keys. In addition,
'internet' is no longer a supported value for the format key.

https://bugzilla.gnome.org/show_bug.cgi?id=600276
2010-05-09 01:07:40 +02:00
62afd2ffa3 Reorganize stage in terms of a UI Group actor and everything else
In preparation for adding magnification, "uiGroup.patch", organizes the stage
along the following lines:

Stage
  *Magnifier
  UI group
    Window group
    Chrome group
    Overlay group
    Alt tab
    App display
    Chrome
    ...

This allows a magnifier actor to clone and magnify the UI group.  The magnifier
is a sibling of the UI Group in this stage oraganization -- see the next patch,
"Magnifier.patch".
2010-05-06 17:18:10 -04:00
37692513cf [altTab] Update for renamed ShellApp method 2010-05-06 12:15:08 -04:00
35bf6b0d36 [altTab] Raise all windows for an app
https://bugzilla.gnome.org/show_bug.cgi?id=616051
2010-05-06 11:19:44 -04:00
0d1ac8cb5b [ShellApp] Add method to focus an app (all windows), make _activate do this
The design calls for raising all windows for a given app in
certain circumstances; implement this.  The new _focus method
raises all windows for the app if it's running.

We further change the _activate method (which a lot of the shell
UI calls now) to invoke _focus for the running case, which means
that e.g. the application well will now raise all app windows.

https://bugzilla.gnome.org/show_bug.cgi?id=616051
2010-05-06 11:19:44 -04:00
b09b30616d Fix userdata directory creation
When creating the directory to store user data, XDG_DATA_HOME is
not guaranteed to exist. Also, the standard mandates permissions
of 0700 for the directory.

https://bugzilla.gnome.org/show_bug.cgi?id=617555
2010-05-06 13:47:00 +02:00
daf133dca8 [workspaces] Split out workspace indicator into separate class
Also fix Clutter warnings.
https://bugzilla.gnome.org/show_bug.cgi?id=614905
2010-05-06 12:16:05 +04:00
ae7f30483d [linearView] Activate workspace on window drop
When a dropped window is accepted by a workspace in linear view, it
is moved to the new workspace. After that, the view zooms back in on
the original workspace, resulting in the moved window disappearing
from the user's sight.
Change this rather unexpected behavior, so that a successful drop
triggers a switch to the new workspace. This also improves consistency
with drops on the (+) area.

https://bugzilla.gnome.org/show_bug.cgi?id=617785
2010-05-06 00:19:46 +02:00
d6fc2cc36f [StEntry] Use hover support from StWidget
As StEntry handles hover differently depending on whether it is
activated or not, the generic hover support in StWidget is
insufficient. Nevertheless it makes sense to set the hover status
using StWidget methods instead of setting the pseudo class directly.
2010-05-05 21:20:32 +02:00
082a15bbc5 [linearView] Cleanup workspace scrolling and zooming
Centralize the update of actor visibilities (overlays, shadows,
off-screen workspaces). Adjust the way scrolling is handled so
that it works correctly with removed workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-05-05 21:20:29 +02:00
2bd64b6cab telepathyClient: improve Empathy interaction
Activate empathy when clicking on a chat icon by asking the
ChannelDispatcher to open the conversation in the default handler.

Also, remove the Approver and Handler for now, since until
telepathy-logger is stable, this means Empathy won't see (and log)
those conversations. This means that empathy's blinky status icon is
back; we'll have to do something else about that.

https://bugzilla.gnome.org/show_bug.cgi?id=611610
2010-05-05 14:53:35 -04:00
b1486f54c8 [ShellGlobal] Change location for user files to XDG_DATA_HOME
While the extension system already uses an XDG location (XDG_CONFIG_HOME),
other components use the deprecated $HOME/.gnome2 directory.
Replace both with XDG_DATA_HOME - the existing data (app usage stats,
looking glass history and extensions) is not migrated to the new location.

https://bugzilla.gnome.org/show_bug.cgi?id=617555
2010-05-05 20:36:52 +02:00
39a24b9a6d [dash] Make the style for places and recent items similar to apps
Change the style rules so that the style for places and recent
items matches the style for applications in a couple of aspects:

 * Use a gradient on hover
 * Use consistent padding and spacing

https://bugzilla.gnome.org/show_bug.cgi?id=610393
2010-05-05 11:43:39 -04:00
6e2ec7291e [gnome-shell.in] Move running environment inheritance earlier
We also want to use it for --eval, so that works over
ssh logins too.
2010-05-05 09:30:29 -04:00
b0ba40f812 Pick up system settings for font rendering
The appearance capplet has a tab for font settings, which we currently
ignore - pick up the settings for resolution, antialiasing and hint style.

https://bugzilla.gnome.org/show_bug.cgi?id=599713
2010-05-04 01:08:20 +02:00
50c453c54d [StShadow] Add support for spread radius
The (optional) spread radius allows to make the shadow bigger without
enlarging the blur value. Mozilla supports this parameter for the
-moz-box-shadow property.

https://bugzilla.gnome.org/show_bug.cgi?id=613832
2010-05-03 19:38:07 +02:00
b71afe55d8 [GnomeSession] split out the gnome-session presence D-Bus interface
Split this out of js/ui/statusMenu.js

https://bugzilla.gnome.org/show_bug.cgi?id=608667
2010-05-03 12:51:34 -04:00
dd0882aa8b [Chrome] add "visibleInFullscreen" property
Chrome elements with this flag set will be visible even when a
fullscreen window is present.

https://bugzilla.gnome.org/show_bug.cgi?id=608667
2010-05-03 12:51:31 -04:00
31914ab23b [Chrome] redo using ShellGenericContainer
Previously we used a ClutterGroup containing a second ClutterGroup for
the non-visibleInOverview actors. Redo it using a single
ShellGenericContainer, and use set_skip_paint() to hide the
non-overview chrome when the overview is visible.

Also fix up the default values for trackActor().

https://bugzilla.gnome.org/show_bug.cgi?id=608667
2010-05-03 12:51:22 -04:00
1816a6339d [ShellGenericContainer] add _get_skip_paint()
https://bugzilla.gnome.org/show_bug.cgi?id=608667
2010-05-03 12:51:13 -04:00
e9e2786fa3 [Params] always return a new object from Params.parse
Rather than returning a modified copy of the input params/defaults,
always return a new object, copying the appropriate values into it.

https://bugzilla.gnome.org/show_bug.cgi?id=608667
2010-05-03 12:51:09 -04:00
024ab39c6d [MessageTray] don't time out the tray if the user is mousing towards it
If a notification is about to hide, but the user has moved the mouse
towards it, let it stick around for another second (and so on, until
the mouse either reaches the tray and causes it to be pinned, or stops
moving the mouse toward it).

https://bugzilla.gnome.org/show_bug.cgi?id=610071
2010-05-03 12:09:53 -04:00
1210a78193 Updated Norwegian bokmål translation 2010-05-02 19:33:35 +02:00
c55dbd5fbd [css] remove a workaround for an old bug 2010-04-30 12:05:56 -04:00
263261cc86 [MessageTray] handle "urgent" notifications specially
Urgent notifications jump to the front of the tray's notification
queue, and come up pre-expanded.

https://bugzilla.gnome.org/show_bug.cgi?id=611612
2010-04-30 11:54:06 -04:00
077f0c56f1 [MessageTray] fix clutter warnings
Figure out if the banner is too long to fit as soon as the
notification's style is set, rather than waiting until allocation
time, since it's bad to add new table rows during allocation.

https://bugzilla.gnome.org/show_bug.cgi?id=611612
2010-04-30 11:54:03 -04:00
e83656969e telepathyClient: cache avatar images
Cache avatars to avoid having to re-download them every session.

We use a cache format that is compatible with empathy's, but we don't
actually use empathy's. This could be changed if we wanted.

https://bugzilla.gnome.org/show_bug.cgi?id=614974
2010-04-29 14:04:07 -04:00
7d7ed7ce7a [panel] y_fill the calendar button 2010-04-27 13:07:31 -04:00
929073882f [panel] Remove border bottom
This line just looks poor - it's probably a leftover from when the
panel was a gradient.  We didn't quite see it before because of
a different bug where we were over-allocating the panel to 27
pixels.
2010-04-27 13:04:48 -04:00
0513297029 [panel] Remove vertical padding for panel-button
This fixes the status menu requesting 27 pixels, which causes
the slicer for the icon to overdraw.

https://bugzilla.gnome.org/show_bug.cgi?id=616951
2010-04-27 12:53:01 -04:00
704354be2c [panel] Remove hardcoded uses of PANEL_HEIGHT
It's cleaner to just y_fill.

https://bugzilla.gnome.org/show_bug.cgi?id=616951
2010-04-27 12:52:57 -04:00
3715109ebe [panel] Fix allocation positioning for boxes
This change doesn't actually affect anything visibly, but
using the absolute coordinates of our allocation box in allocate()
is wrong; we should be positioning our children at 0,0 and using
width/height as a reference.

https://bugzilla.gnome.org/show_bug.cgi?id=616951
2010-04-27 10:37:17 -04:00
9d21b2cb25 Updated Slovenian translation 2010-04-25 10:31:55 +02:00
7f56d06546 known_vendor_prefixes should be NULL terminated
https://bugzilla.gnome.org/show_bug.cgi?id=616574
2010-04-23 18:47:23 +04:00
cf0664fcc6 [lookingGlass] Replace "Hierarchy" with the far more useful "Windows"
I debug the window list a lot more often than I debug actors.
2010-04-20 14:57:31 -04:00
26c8227df5 [ShellWindowTracker] Add a signal to notify when tracked windows change 2010-04-20 14:47:45 -04:00
df43352441 Fix Clutter warnings
https://bugzilla.gnome.org/show_bug.cgi?id=614905
2010-04-19 01:16:49 +04:00
7d705d4de3 Updated Brazilian Portuguese translation 2010-04-17 14:03:16 -03:00
4a0fbf03a8 [workspaces] Only allow mouse clicks to swich for empty workspaces
Allowing it in the case of 1 window is weird - it makes it feel
like a bug when you go from 1 to 2.
2010-04-16 17:24:54 -04:00
54168fcd31 Update visibility of controls on view change.
https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-04-16 17:40:04 +04:00
5012d64580 telepathyClient: fix summaryNotification to grow properly on updates
When adding more lines to the notification, we need to move it up as
well, or else the new lines will end up underneath the summary or
offscreen.

https://bugzilla.gnome.org/show_bug.cgi?id=615004
2010-04-15 10:12:21 -04:00
10ac42d6ad messageTray: don't show the same notification in both locations
If a notification is already being viewed from the summary area, and
it re-emits 'notify', don't show it a second time in the notification
area.

https://bugzilla.gnome.org/show_bug.cgi?id=614975
2010-04-15 10:04:33 -04:00
a277dfa9ce telepathyClient: only show single-user chats, not chat rooms
eg, for IRC, show private messages, but not channel messages

https://bugzilla.gnome.org/show_bug.cgi?id=614972
2010-04-15 10:03:59 -04:00
3d6c12121f src/Makefile.am: add stamp-shell-enum-types.h to CLEANFILES 2010-04-14 10:49:34 -04:00
98a093a279 Remove icon and menu from titlebar
To avoid visual duplication with the application menu, eliminate
the window menu button. (The window menu can still be accessed by
right-clicking on the title bar, or Alt-right-clicking anywhere on the
window.)

This is implemented using the new Mutter facility for GConf key
redirection; we add separate key for 'button_layout' with a default
that omits the menu button.

https://bugzilla.gnome.org/show_bug.cgi?id=591390
2010-04-13 13:58:42 -04:00
7467e9e3a5 Adapt to new Mutter plugin initialization method
With the changes from bug 615586, Mutter now expects a separate start()
method which is called after construction. Move our initialization from
constructed() to start() so it can access the MetaScreen.

https://bugzilla.gnome.org/show_bug.cgi?id=615592
2010-04-13 13:57:52 -04:00
a7cd294403 notificationDaemon: fix remove-source-on-app-focus code
Previously when no app was focused it would accidentally remove all
sources that had no assocated app (such as telepathy-based sources).

https://bugzilla.gnome.org/show_bug.cgi?id=614978
2010-04-13 11:50:53 -04:00
29d89467b9 Remove a stray bit of user data
We don't need to pass a user_data argument to Meta.later_add() any
more, so remove a stray 'null'.

https://bugzilla.gnome.org/show_bug.cgi?id=615590
2010-04-13 11:10:33 -04:00
dc5dcc6139 Distribute shell-enum-types.h.in and shell-enum-types.c.in
These new files need to be in EXTRA_DIST

Based on a patch by Rico Tzschichholz
https://bugzilla.gnome.org/show_bug.cgi?id=615621
2010-04-13 07:19:15 -04:00
6aaf4b87d5 Major ShellApp API cleanup, startup notification, window focus handling
This patch combines several high level changes which are conceptually
independent but in practice rather intertwined.

* Add a "state" property to ShellApp which reflects whether it's
  stopped, starting, or started.  This will allow us to later clean
  up all the callers that are using ".get_windows().length > 0" as
  a proxy for this property
* Replace shell_app_launch with shell_app_activate and shell_app_open_new_window
  A lot of code was calling .launch, but it's signficantly clearer
  if we call this ".open_new_window()", and later if we gain the ability
  to call into an application's menu, we can implement this correctly rather
  than trying to update all .launch callers.
* Because ShellApp now has a "starting" state, rebase panel.js on top of
  this so that when we get a startup-notification sequence for an app
  and transition it to starting, it becomes the focus app, and panel.js
  cleanly just tracks the focus app, rather than bouncing between SN
  sequences.  This removes display of non-app startup sequences, which
  I consider an acceptable action in light of the committed changes
  to startup-notification and GTK+.

https://bugzilla.gnome.org/show_bug.cgi?id=614755
2010-04-12 16:32:21 -04:00
4392516713 Create GTypes for Shell namespace
https://bugzilla.gnome.org/show_bug.cgi?id=614755
2010-04-12 16:01:54 -04:00
a9aa89e858 [lightbox] Fix Clutter warning by doing reallocation in a Meta.later_add
Based on an original fix by Maxim Ermilov <zaspire@rambler.ru>

https://bugzilla.gnome.org/show_bug.cgi?id=614905
2010-04-09 16:46:35 -04:00
58c0abe600 Updated Galician translations 2010-04-09 19:41:22 +02:00
d42263c1bc Change shell_global_get_modifier_keys to shell_global_get_pointer.
We can't use gdk_display_get_pointer/gdk_window_get_pointer from gjs
when XKB is active. We already had a wrapper that did the
get-modifier-state part of that, but some places also need the
get-pointer-location part of it. So update our wrapper to return both,
and update js code to use it.

https://bugzilla.gnome.org/show_bug.cgi?id=613428
2010-04-08 14:51:45 -04:00
1d2f0e0e15 workspace.js: remove some dead code
The original window dnd code needed to track whether or not the
pointer was in the clone. Some later rewrite made this unnecessary,
but we were still keeping track anyway.
2010-04-08 14:51:45 -04:00
752c25bb7d messageTray: Don't use gravity for notificationBin
When the notificaionBin has an odd width this could result into
loosing pixel aligment (and ugly looking font).

As the notification is already reactive make it non reactive and
remove the use of garvity.

https://bugzilla.gnome.org/show_bug.cgi?id=614702
2010-04-08 20:41:41 +02:00
df09e199b0 Updated Italian translation 2010-04-06 22:52:44 +02:00
ab75c8cacc [chrome] Fix fullscreen check for broken apps
Document fullscreen checks and add a third case to catch apps like
flash who position there windows sightly offscreen to hide there decorations.

https://bugzilla.gnome.org/show_bug.cgi?id=614509
2010-04-06 21:14:54 +02:00
e94d54bffb Add support for chatting directly from IM notifications
Also reorganizes the notification layout to use an StScrollView; very
tall notifications are now scrolled instead of just taking up more and
more of the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=608999
2010-04-06 09:20:50 -04:00
5bce103a40 Use Telepathy for IM notifications
And suppress libnotify-based notifications from Empathy

https://bugzilla.gnome.org/show_bug.cgi?id=608999
2010-04-06 09:16:00 -04:00
5ab852bfa3 Revert "Special-handle Empathy to have multiple sources and to queue notifications"
This reverts commit bb0a977edc.

https://bugzilla.gnome.org/show_bug.cgi?id=608999
2010-04-06 09:16:00 -04:00
439203349d Remove Big, which is no longer used
https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 09:13:51 -04:00
2320c393c9 Replace all remaining BigBoxes with StBoxLayouts or StBins
Also, remove a lot of cruft from genericDisplay.js leftover from
previous St-ifications, and remove the pre-gtk-2.16 hacks from the
status tray in panel.js (which are much less needed with the
nearly-all-black panel anyway).

https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 09:13:51 -04:00
887f0f554b [genericDisplay] Fix variable typo 2010-04-06 09:03:46 -04:00
46c210c314 [ShellMenu] port from BigBox to StBoxLayout
The actual changes to shell-menu.[ch] are pretty minimal; most of the
changes there are just style/spacing/indentation.

Also, removed shell_menu_append_separator() since it wasn't needed;
the separators would already have been behaving as intended just
because they were non-reactive.

https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 08:25:34 -04:00
b4c3ab6726 [StDrawingArea] further CSS-ify StDrawingArea users
Make shell_draw_box_pointer() use CSS colors, and set the app well
menu arrow width based on its own CSS rather than its parent's.

https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 08:22:10 -04:00
95a6353dee [StWidget] respect CSS sizing in default size request
Most subclasses override get_preferred_width/height, but if they don't
(eg, StDrawingArea), then make sure they still take CSS-specified
sizes into account.

https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 08:19:35 -04:00
cfea0649d8 remove some Big references from places that don't need them any more
https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 08:17:33 -04:00
045faf3f12 Fix appIcon menu arrows
We were looking up the wrong property for the width, and then only
setting the foreground color if a void function returned TRUE.

https://bugzilla.gnome.org/show_bug.cgi?id=614516
2010-04-06 08:17:32 -04:00
44ede8c942 Squash epic memory leak
StThemeNode holds a reference to its parent, but we never released
that reference.  This could cause us to hold onto whole chains
of theme nodes with rather dire memory usage implications.

Also move the other g_object_unref into _dispose.

https://bugzilla.gnome.org/show_bug.cgi?id=614660
2010-04-05 21:10:19 -04:00
1ddb775d59 [gnome-shell.modules] Add json-glib to jhbuild
We want to have Clutter built with the external json-glib, with
introspection support.  Clutter's build breaks if we compile
it with introspection but the system install doesn't have it,
and anyways the internal copy is buggy and unmaintained.
2010-04-05 14:08:28 -04:00
cbcbd11ba0 [ShellGlobal] Fix double-free in get_primary_monitor 2010-04-05 11:39:37 -04:00
bae07700a1 shell_global_get_primary_monitor: Use variable to store number of monitors
See https://bugzilla.gnome.org/show_bug.cgi?id=608647#c5
(forgot to add it before commiting).
2010-04-04 18:13:28 +02:00
ca13cec01c Rework shell_global_get_primary_monitor
Currently shell_global_get_primary_monitor just returns the first screen,
in the list as primary.

This is not always correct as the first screen reported by mutter isn't always,
the first one listed by RANDR.

Use gdk_screen_* to query the monitor information and add a heuristic to prefer
LVDS displays (similar like in done for gnome-panel) to prefer the laptop's
internal screen over external displays.

https://bugzilla.gnome.org/show_bug.cgi?id=608647
2010-04-04 18:06:56 +02:00
f2af295867 Updated Dutch translation 2010-04-02 22:19:09 +02:00
0dffec661a Remove the non-existing widget.js from POTFILES.in 2010-04-02 22:00:05 +02:00
bab5a006d8 windowManager: Fix up map effect
Update comment and set the opacity rather than scaling in _mapWindowDone,
 also as we don't have to move the anchor point's gravity for this effect.
2010-04-02 20:30:10 +02:00
f89b95c2aa windowManager: Fade windows on map
Fade in new windows instead of scaling them up from 0 to 1.
2010-04-02 19:51:16 +02:00
f262473a3f Fix fullscreen behaviour
The check in _windowsRestacked checks for
windows[i].x >= primary.x
and
windows[i].x <= primary.x + primary.width
(likewise for y).

This is wrong because a fullscreen window on the secondary screen is likely
to have windows[i].x == primary.x + primary.width which means that the checks
for _both_ screens would be valid, but the first one would win due to
the "break;" statement.

But here the window isn't really on the primary but on the secondary one.

Fix that by using < instead of <= for those checks.

https://bugzilla.gnome.org/show_bug.cgi?id=614509
2010-04-01 16:53:21 +02:00
b571ad0760 Added Ukrainian translation 2010-04-01 15:50:35 +03:00
750672061a placesDisplay: Prevent bookmarks from being cut off
Moving to St.Table introduced a regression that resulted in the height
of Places section to only depend on the height of the left column.

This could result into some bookmarks not being displayed at all because
there are not enough items in the left column to allocate the needed height.

Fix this by removing the St.BoxLayout actors and add the items directly to
the table.

https://bugzilla.gnome.org/show_bug.cgi?id=614144
2010-03-31 17:08:51 +02:00
2ca5cfd6f5 StTable: Update row and column count in st_table_remove_actor
Adjust the table size when removing an actor in st_table_remove_actor.

https://bugzilla.gnome.org/show_bug.cgi?id=614144
2010-03-31 16:55:14 +02:00
8dd572d1cc ShellGenericContainer: adjust requested height/width for border/padding
https://bugzilla.gnome.org/show_bug.cgi?id=614293
2010-03-31 10:10:14 -04:00
b8647cc00e Remove sidebar 2010-03-31 10:08:18 -04:00
a9bdffc9e6 runDialog: Accept Enter (keypad) key in addition to Return. 2010-03-31 15:29:11 +02:00
68723f191c notificationDaemon.js: don't call setApp() if app couldn't be determined
Notify() was calling setApp() unconditionally after attempting to
determine an application. However, determining the application can
fail (for example, when notify-send is used) and resulted in an exception
being printed.
2010-03-31 15:21:54 +02:00
5eafb29332 completed Punjabi Translation by A S Alam 2010-03-31 07:46:39 +05:30
c92ce5983d Consume startup-notification APPLICATION_ID
This patch ensures we're showing the correct data when doing
startup-notification.

https://bugzilla.gnome.org/show_bug.cgi?id=612833
2010-03-30 17:36:05 -04:00
fe52a9e1a1 Add shell_app_system_get_app_for_path
Allows looking up an app given an absolute path to its
desktop file; will be used for startup-notification.

https://bugzilla.gnome.org/show_bug.cgi?id=612833
2010-03-30 17:36:04 -04:00
1a25cd98ea Move focus change handling out of a meta_later
Ok, there admittedly wasn't a strong rationale for having it in a
later, and by performing this immediately we reduce race conditions
for our focus_app versus startup_notification handling.

https://bugzilla.gnome.org/show_bug.cgi?id=612833
2010-03-30 17:36:03 -04:00
611ca3c161 MessageTray: tweak how allocation works to fix the reactive area
Rather than having the notificationBin, summaryBin, and
summaryNotificationBin span the whole width of the screen and just
align their children to the right spot, set their anchor_gravity
appropriately, set their anchor point correctly, and let their width
vary with the width of their child.

Fixes the fact that the area to the left and right of an expanded
notification was reactive, because the notificationBin was invisibly
covering it.

https://bugzilla.gnome.org/show_bug.cgi?id=612072
2010-03-29 14:36:36 -04:00
1dd4c7140e StBoxLayout: remove an incorrect drawing optimization
Paint/pick all children, regardless of whether or not they lie within
the content_box. The previous behavior was that a child that was 99%
outside the box would be fully visible, but a child that was 100%
outside the box would be fully hidden. This is somewhat odd, and
doesn't match the behavior of the other St container classes, and at
any rate, the use of clutter_actor_get_allocation_box() for this
optimization was incorrect since it doesn't take into account
transformations (anchor point, rotation, etc) that might cause the
child to be drawn within the content_box anyway.

(For scrolled StBoxLayouts, drawing is still clipped to the
content_box, as before, but will now properly take transformations
into account as well.)

https://bugzilla.gnome.org/show_bug.cgi?id=614047
2010-03-29 14:36:36 -04:00
b9e58947cc Adjust theme of recent-items and places sections
Add a border to items which highlights on hover, just like the style
of (non-running) app-well items. For removable items in the places
section, this has the additional benefit of making clear to which
item the unmount button belongs.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-29 17:46:07 +02:00
73ab59f1d6 [placesDisplay] Add spacing between actions and devices
By moving the elements directly into the enclosing table the spacing
between them got lost.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-29 17:46:07 +02:00
df8b03398f [docDisplay] Port DashDocDisplayItem to CSS
Replace Big.Box with St.Clickable similar to the code in placesDisplay.
Adjust spacing and padding to match the places section.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-29 17:46:06 +02:00
feaaefd8ba [appDisplay,placeDisplay] Remove manual dnd mode
As the special handling for St.Clickable moved into dnd, it is no
longer necessary to use manual mode in these cases.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-29 17:46:05 +02:00
04200a4281 [dnd] Special-case St.Clickable
Currently manual dnd mode is used with St.Clickable to avoid messing
up its internal state with a pointer grab. To avoid code duplication,
move this special handling into dnd.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-29 17:45:57 +02:00
c6f84cfa59 Update Czech translation 2010-03-29 00:50:15 +02:00
103d0cba20 Updated Greek translation 2010-03-28 10:53:38 +03:00
095e15fc11 [placesDisplay] Replace remaining Big.Boxes with St.Widgets
While most of the code already is CSS stylable, the two-colum setup
is still done using Big.Box with hard coded spacings. Port those
remaining parts to St.Widget, so that all spacings can be adjusted
by the theme.

https://bugzilla.gnome.org/show_bug.cgi?id=610385
2010-03-27 19:45:10 +01:00
ca2a11c57d [workspacesView] Use add_style_class_name() to set style class
Previously Single/Mosaic view just overwrote the style class set
by the parent.
2010-03-26 23:39:43 +01:00
9423d2c9ac [build] Link against -lm
Fedora 13 uses --no-add-needed, so if we use -lm, we have
to explicitly specify it.

More information: http://fedoraproject.org/wiki/Features/ChangeInImplicitDSOLinking
2010-03-26 17:10:18 -04:00
6461db9df6 AppSwitcher: Make sure we always get the correct icon position
Call stage.get_actor_at_pos before calling icon.get_transformed_position.
2010-03-26 18:13:18 +01:00
5ff609ed49 AppSwitcher: Use CSS instead of the hardcoded POPUP_LIST_SPACING constant
The POPUP_LIST_SPACING constant was used for the AltTabPopup.actor's padding,
AltTabPopup.actor's spacing and SwitcherList._list's spacing.

Switch to CSS and remove the constant.

https://bugzilla.gnome.org/show_bug.cgi?id=613195
2010-03-26 17:49:02 +01:00
4aa2473d18 initialize a variable that gcc warns about
https://bugzilla.gnome.org/show_bug.cgi?id=613749
2010-03-26 11:20:10 -04:00
3f5bb8f98d StScrollView: fix scrollbar allocation when one scrollbar isn't shown
https://bugzilla.gnome.org/show_bug.cgi?id=613964
2010-03-26 11:05:54 -04:00
0487630e03 Updated French translation 2010-03-26 11:05:25 +01:00
d173f9e19d shell-global: Fix get_focus_monitor returning the incorrect screen
When the window's top-left corner is the same as the monitor's top-left
corner the check in shell_global_get_focus_monitor fails to detect that.

Use <= rather than < to fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=613944
2010-03-25 22:04:43 +01:00
f53bf17331 appSwitcher: Fix multiscreen positioning issues
We need to take the screens position into account when allocating.

https://bugzilla.gnome.org/show_bug.cgi?id=613944
2010-03-25 21:58:48 +01:00
ac54fed8d4 [MessageTray] pop out the last notification when mousing over the summary
https://bugzilla.gnome.org/show_bug.cgi?id=610726
2010-03-25 09:24:52 -04:00
6deee27d14 [StThemeNode] Fix gradient colors
CAIRO_FORMAT_ARGB32 matches COGL_PIXEL_FORMAT_BGRA_8888_PRE on
little Endian.
2010-03-24 23:39:43 +01:00
d9f43e27a0 [AppDisplay] Popup the menu on left-click/hold
Left-clicking an app icon and holding the button used to pop up the
app menu, but regressed when rewriting appDisplay.
Restore the previous behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=609013
2010-03-24 19:38:59 +01:00
d1a178301f [placeDisplay] Prefer eject over unmount when applicable
Clicking the eject button in the places display always triggers an
unmount action. In some cases like USB drives or DVDs, eject makes
more sense - it is also consistent with nautilus' behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=613405
2010-03-24 19:38:58 +01:00
8b3d4857aa [Overview] Postpone window repositioning while zooming
After closing a window, the remaining previews are repositioned
after a timeout; when it is called while the user zooms a preview,
the window positions get all messed up, so postpone the positioning
in this case until the zoom ends.

https://bugzilla.gnome.org/show_bug.cgi?id=613536
2010-03-24 19:38:57 +01:00
8d3abea6ef [StThemeNode] Fix build after rebase 2010-03-24 14:24:25 -04:00
5060081db5 Move rendering into st-theme-node-drawing.c
The idea behind this move is that we have a lot more control over
rendering if StWidget isn't a big pile of actors, and things are
more efficient.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-24 14:14:03 -04:00
a8fa8a498a Fix dragging of App Well and Places icons
The hover rewrite added a freeze/thaw_notify to
st_clickable_leave_event() (to match the one already in
st_clickable_enter_event()), which broke code in two places that
assumed "pressed" would still be TRUE when "hover" changed to FALSE.
Fix that by exposing the "held" property as well.
2010-03-24 13:48:29 -04:00
5635797cb9 runDialog: use Shell.get_event_state(e), not e.get_state() 2010-03-24 13:16:12 -04:00
468f30e4ab Fix build on x86_64
A pointer does not equal to an int on x86_64
(which results into pointer - pointer not being an int either),
fix that by casting the resulting value  to an int.

Breakage was introduced by commit 909b5ec43c
2010-03-24 17:37:56 +01:00
68b943d8ea [MessageTray] remove bottom rounded corners
https://bugzilla.gnome.org/show_bug.cgi?id=610726
2010-03-24 10:13:48 -04:00
994b4c0007 [MessageTray] Use #StWidget:track-hover
St.Widget's new "hover" property takes reactive children into account
when deciding whether or not the pointer has actually left the actor,
so it works better than the code that used to be here.

https://bugzilla.gnome.org/show_bug.cgi?id=610726
2010-03-24 10:13:36 -04:00
f9e4385e02 [StWidget] add (optional) hover tracking
If track-hover is set, update the hover property automatically, and
the "hover" pseudo class to match, as StClickable used to do. (Remove
the corresponding code in StClickable). Tweak the tooltip handling to
use track-hover, which also makes it slightly more reliable in the
presence of reactive children, etc.
2010-03-24 10:03:50 -04:00
909b5ec43c [StWidget] add list-like methods for style_class and pseudo_class
Since style_class and pseudo_class are space-separated lists of names,
add new methods to add and remove individual names rather than just
re-setting the entire name.

Update existing code to use the new pseudo-class methods where
appropriate. In some cases, this may result in actors having multiple
pseudoclasses where previously they only had one at a time, but there
don't seem to be any visible differences.

(There are some places that could usefully use the new style_class
methods as well, but this patch doesn't change them.)

Also, update test-theme.c to test the new methods.

https://bugzilla.gnome.org/show_bug.cgi?id=604943
2010-03-24 09:40:37 -04:00
7c37e94eda st-widget.h: fix spacing
https://bugzilla.gnome.org/show_bug.cgi?id=604943
2010-03-24 09:40:37 -04:00
874dd14ddc Updated Hungarian translation 2010-03-24 14:26:31 +01:00
d39d7b45e0 Updated Serbian translations 2010-03-24 01:45:46 +01:00
23e11175f8 St: minor gtk-doc fixage (%NULL, %TRUE, %FALSE, not #) 2010-03-23 19:56:10 -04:00
aefa8af60e [runDialog] Don't add duplicates to the history
When the user runs the same command as the last one saved there
is no need to save it again, otherwise we the history might end
up having lots of dupes which makes searching for an old command
harder.

https://bugzilla.gnome.org/show_bug.cgi?id=613731
2010-03-23 20:22:46 +01:00
14a53cc43c Bump version to 2.29.1 2010-03-23 14:12:32 -04:00
a6be7ad6bd Increase minimum versions for dependencies
Require:
 gobject-introspection >= 0.6.9
 gjs >= 0.6
 mutter >= 2.29.1
2010-03-23 14:12:32 -04:00
af05a9e268 Add missing test case to distribution
scroll-view-sizing.js wasn't in Makefile.am
2010-03-23 14:12:32 -04:00
eab96c66fd workspacesView.js: listen to drag signals on all workspaces
https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-03-23 20:09:14 +03:00
2a740448e1 [workspaces] Don't use a clone for the window drag actor
Using a clone for the drag actor causes the animation into
the final position not to work as expected; instead use
the newly added DND parameters to change the original
drag actors size and opacity. (This reverts the change in
011db9f).

Since we are using the original actor, we have to be careful
not to change it during the drag, so don't actually position
dragged window actors in Workspace.positionWindows().

https://bugzilla.gnome.org/show_bug.cgi?id=613367
2010-03-23 11:32:16 -04:00
94472ba9fa [DND] Allow setting drag actor max size and opacity
Add parameters to DND.makeDraggable:

 dragActorMaxSize: Maximum size for actor drag icon
 dragActorOpacity: Opacity of actor during drag

https://bugzilla.gnome.org/show_bug.cgi?id=613367
2010-03-23 11:32:16 -04:00
dfb110cd0f [DND] Use Params for DND.makeDraggable()
Replace boolean 'manualMode' with a params object for
improved readability and future expansion.

https://bugzilla.gnome.org/show_bug.cgi?id=613367
2010-03-23 11:32:16 -04:00
57dd02f6ae fix a gtk-doc typo that giscanner was warning about 2010-03-23 11:28:25 -04:00
0b1430058a Screencast extention should be ogv
http://en.wikipedia.org/wiki/Ogg
"Today video in Ogg is found with the .ogv file extension,
which is formally specified and officially supported."

https://bugzilla.gnome.org/show_bug.cgi?id=611660
2010-03-23 08:16:24 -04:00
f2172c088e Make labels on top bar bold
Trying out making the button label text a little meatier.
2010-03-22 21:02:26 -04:00
b93cb4b976 workspacesView.js: Fix dropping window on +
https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-03-22 23:46:24 +03:00
6744433245 add a missing semicolon
https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-03-22 23:46:18 +03:00
01cd42bd51 fix a missed variable rename in 33dca516 2010-03-22 12:12:04 -04:00
bc3b208f41 Updated Slovenian translation 2010-03-21 21:59:50 +01:00
049fea477b Updated Spanish translation 2010-03-21 16:49:30 +01:00
0ec4c66f96 Updated German translation 2010-03-21 16:29:07 +01:00
8ad1da0db2 Add windowAttentionHandler.js to POTFILES.in
It contains translateable strings.
2010-03-20 23:48:09 +01:00
bd0bd22c63 Updated British English translation 2010-03-20 22:34:01 +00:00
e3b839360a Updated German translation 2010-03-20 23:29:30 +01:00
968679f68c Update Czech translation 2010-03-20 03:14:01 +01:00
5d0e33e267 Remove unused constant 2010-03-19 20:13:20 +01:00
52f1cc6d19 Remove user_data arguments for callbacks
Gjs now removes user_data arguments for callbacks - the existing
code still works because all user_data arguments are unused and
at the end of the argument list, but it's a lot prettier to remove
them.
2010-03-19 20:13:18 +01:00
1b2377370b Updated Polish translation 2010-03-19 13:08:52 +01:00
5a6c9f176e Animate workspace view switches
Replace the hard switch between linear and mosaic workspace view
with a an animated transition between the views.

https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-03-18 23:47:56 +01:00
a9fea8248c Don't destroy and recreate workspaces on view switches
Currently, the workspace objects are destroyed and recreated on
view switches. Instead, keep the objects around and reparent the
workspace actors on view switches.

https://bugzilla.gnome.org/show_bug.cgi?id=610191
2010-03-18 23:47:55 +01:00
47644cad6a [Overview] Switch workspace when dragging the desktop
Depending on screen size and pointer position, the scroll bar used
to switch the active workspace in linear view may not be a convenient
target, so allow dragging the desktop as an alternative.

https://bugzilla.gnome.org/show_bug.cgi?id=610892
2010-03-18 23:47:53 +01:00
b7c6ec4b46 [workspace] Ensure we emit drag-end if we're in a drag during a destroy
Showing the window overlay relies on drag-end being emitted, so do so if we're
in a drag.
2010-03-18 16:58:16 -04:00
908b0fb727 support arrow-up to recall previous commands
runDialog store history in gconf.
https://bugzilla.gnome.org/show_bug.cgi?id=612635
2010-03-18 22:05:09 +03:00
e21aea6e13 [windowManager] Really fix state checking for workspace switcher popup
To be correct just always check at time of use whether the overview
is visible, rather than trying to use whether or not it was
constructed earlier.
2010-03-18 14:53:58 -04:00
6c13ca817d Fix workspaceSwitcherPopup
The check in WindowManager._showWorkspaceSwitcher is supposed
to check if the overview is _not_ visible.

Fix that.
2010-03-18 19:39:09 +01:00
38009309e9 Updated Spanish translation 2010-03-18 19:27:05 +01:00
d98db2bd59 Use Meta.Display.lookup_keyboard_action to enable workspace switches
Also refactor Alt-F2 to use this as well.

https://bugzilla.gnome.org/show_bug.cgi?id=613101
2010-03-18 14:15:07 -04:00
1f274c04fb [placeDisplay] Add missing return statements
Otherwise we get a warning.
2010-03-18 14:04:35 -04:00
ddfe9442fa [placeDisplay] Fix dnd regression
DND from the places section broke with 1c4c3afb when St.Label was
replaced with St.Button.
To fix, replace St.Button with St.Clickable and use a fake_release
when starting a drag.

https://bugzilla.gnome.org/show_bug.cgi?id=609218
2010-03-18 18:15:43 +01:00
8b792f8942 Use one button to toggle between single and grid view
Currently we use two buttons to toggle between the different views,
one of them always being redundant.

Fix that by only use one button that changes it's style depending on
the current view.

https://bugzilla.gnome.org/show_bug.cgi?id=610801
2010-03-18 15:27:40 +01:00
db96437f18 Updated Slovenian translation 2010-03-18 14:06:15 +01:00
a614d72b00 Updated Bulgarian translation 2010-03-18 13:09:15 +02:00
ec6a6727e0 Don't use a gradient on the top menu bar
Now that we don't use pure black for the overview background
there is less incentive to soften or differentiate the top
bar using a gradient.  Without a gradient it blends better
with screen bezels and reinforces the idea of being negative space.
2010-03-17 22:51:49 -04:00
cc8a95572e [placeDisplay] Show a message when unmount fails
When an unmount operation fails, the only feedback given currently
is an exception on stderr. Use the infoBar to display an error
message and allow the user to retry the operation.

https://bugzilla.gnome.org/show_bug.cgi?id=612200
2010-03-18 01:43:18 +01:00
d1108e1e7d [InfoBar] Allow to optionally change the button label
Currently the infoBar's button will always read "Undo" - sometimes
a different label makes more sense, so allow to optionally set the
label to something else.

https://bugzilla.gnome.org/show_bug.cgi?id=612200
2010-03-18 01:43:13 +01:00
744bc996db Add a --version command line option
https://bugzilla.gnome.org/show_bug.cgi?id=613164
2010-03-18 01:43:11 +01:00
22bf4c8a93 [Overview] Make menu sizes relative to workspace area
Instead of setting a fixed size in the CSS which only works well
with a limited range of screen resolutions, assign a relative
size in the code.

While this takes away some flexibility from theme authors, it is in
line with most elements in the overview (workspaces area, dash).

Also expose the menu panes vertical alignment, so that more-apps aligns
to the workspaces area's top and more-docs to the bottom.

https://bugzilla.gnome.org/show_bug.cgi?id=610872
2010-03-18 01:43:05 +01:00
46bce04788 Fix JSObject leak in workspace.js
https://bugzilla.gnome.org/show_bug.cgi?id=612318
2010-03-18 03:27:42 +03:00
9a2d883cf5 [windowManager] Allow extensions to more easily override keybindings
Add an explicit API for overriding keybindings.

https://bugzilla.gnome.org/show_bug.cgi?id=612651
2010-03-17 20:07:32 -04:00
690deeb502 unref theme_node in st_widget_dispose
https://bugzilla.gnome.org/show_bug.cgi?id=612318
2010-03-17 23:44:20 +03:00
367eaf9161 Prevent from being partly offscreen
Limit the AppSwitcher to the screen size by either downscaling or
scrolling.

We scale the icons down up from 96, 64, 48, 32 to 22 and start scrolling
if we still fail to fit on screen.

The thumbnail box is shifted to either left or right, when failing to
fit we scroll here to.
To prevent from being offscreen at the buttom we adjust the thumbnail
height to fit.

The old positioning logic is replaced with a ShellGenericContainer to
implement a custom allocation system.

https://bugzilla.gnome.org/show_bug.cgi?id=597983
2010-03-17 21:34:13 +01:00
f0e531310d Switch Clutter to 1.2 branch
Clutter has now been branched in preparation for 1.3 development,
so build the clutter-1.2 branch instead.
2010-03-17 13:57:11 -04:00
cdef8bf5aa Remove the "Yessir. The compositor is running" code
Mutter does no longer add this, so there is no reason for us to remove it.
2010-03-17 18:57:05 +01:00
e9a9a5243c Fix dropping window on the indicators and at the screen edge for "+"
https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-17 20:41:38 +03:00
ee57dab846 [Workspace] Disconnect reposition handler when leaving overview
As the repositioning after closing a window preview is delayed, it is
possible that the timeout is triggered while leaving the overview. In
that case the previews move to the new overview position and are changed
abruptly to the original window position when the overview zoom is done.
To prevent this, disconnect the handler when leaving the overview.
2010-03-17 16:38:03 +01:00
9f68786547 Update more-docs to look more like more-apps
Disable horizontal scrolling and remove the close button. Update
the CSS to match more-apps.

https://bugzilla.gnome.org/show_bug.cgi?id=612452
2010-03-16 22:22:05 +01:00
c02b57efc3 Move workspace controls into a single object
Rename WorkspacesViewSwitch to WorkspacesControls and let it manage
all workspace controls. Do not destroy and recreate the controls bar
actor on each view change, but add it to the overview once and let it
update itself.

https://bugzilla.gnome.org/show_bug.cgi?id=610189
2010-03-16 18:52:11 +01:00
7183aac362 add ability move window in SingleView
https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-16 18:54:56 +03:00
011db9f34d Shrink windows to small previews when dragging
Hide the original actor during a grab, and create a new
clone.  This is easier than trying to ensure we maintain
the state of the original window clone.

https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-16 11:29:44 -04:00
7d8c3f1ecd Ensure our drag actor is positioned over the cursor
Previously we were looking at the source size, which is
not necessarily the same as the drag actor size.

https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-16 10:59:42 -04:00
087ac8470e [panel.js] Remove duplicated 'let'
Original fix from Maxim Ermilov <zaspire@rambler.ru>
2010-03-16 10:51:05 -04:00
3ce89e3c80 Add missing semicolons noted by jslint
Taken from a patch by Lex Hider on the mailing list
2010-03-15 09:50:05 -04:00
543a41bfea Updated Spanish translation 2010-03-14 23:13:29 +01:00
cb80dc6834 Use CSS for spacing
Use CSS instead of St.Bin actors for spacing.

https://bugzilla.gnome.org/show_bug.cgi?id=612852
2010-03-14 11:11:52 +01:00
b55fd735f4 [StTextureCache] Use size in all cases for cache keys
Otherwise we're going to be returning the wrong sized image to callers,
and Clutter.Texture will scale it, which will look awful.
2010-03-13 13:11:22 -05:00
32fd323153 [ShellApp] When fading, don't read alpha channel if none available 2010-03-13 12:56:15 -05:00
3aea09b614 Fix app icon fading
The way we were loading data into a CoglTexture, then pulling it out
and manipulating it on the CPU, then loading it back into a texture
was a bit lame.

Clean things up a bit here by loading directly into the CPU, doing
the fading, then creating a texture.

Also cache the faded data in StTextureCache.

https://bugzilla.gnome.org/show_bug.cgi?id=612759
2010-03-13 12:50:38 -05:00
374fd35476 src/Makefile.am: fix .gir dependencies
We don't need to rebuild Big-1.0.gir and St-1.0.gir when
libgnome-shell changes.

https://bugzilla.gnome.org/show_bug.cgi?id=612734
2010-03-12 14:05:58 -05:00
20d3b1f8b1 Error out at startup if the GConf schemas are missing
If we don't do this, then boolean/int/list keys will seem to sort of
work (but defaulting to false/0/[] instead of the correct schema
defaults), but string keys will return null, which will usually cause
exceptions or crashes.

https://bugzilla.gnome.org/show_bug.cgi?id=611214
2010-03-12 13:48:58 -05:00
7de5e78977 Updated Slovenian translation 2010-03-12 13:27:59 +01:00
2da6507a87 fix workspace controls for RTL locales
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-03-11 16:51:47 -05:00
5ca665bdde fix minimize animation for RTL locales
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-03-11 16:51:26 -05:00
46f8d913a1 [StTextureCache] Fix an accidentally swapped ref/unref 2010-03-11 21:42:32 +01:00
858a6bf827 [Overview] Update look and feel of the search field
Port the search entry to CSS and update look and feel according to
the latest design.

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-03-11 21:22:31 +01:00
89173544d4 Simplify handling of adjustments
The relationship between adjustments and scrollbars and
scrollable widgets was much more complex than it needed to be.

StScrollView: Have the scroll view own a pair of adjustments,
  set them on the child on add(), remove unnecessary
  change notification signal connections.
StBoxLayout: Remove auto-create of adjustments, just take the
  adjustments from the scrollbars and set them on the scrollable
  child. Notify for hadjustment/vadjustment properties.
StScrollBar: Notify adjustment property.
StScrollable: Document how adjustment setting works.

https://bugzilla.gnome.org/show_bug.cgi?id=611740
2010-03-11 15:08:48 -05:00
163b2d0403 Fixes for dispose and finalize
* Add missing chain-up for dispose and finalize methods
* ShellGenericContainer needs to destroy its children in dispose()
* Fix variable naming and excess casts in st_label_dispose()

https://bugzilla.gnome.org/show_bug.cgi?id=612511
2010-03-11 15:08:48 -05:00
c83883f1f7 Fixes for setting up scrolling adjustments
StScrollable: Document how to set adjustments
StBoxLayout: Make sure that we always have upper >= lower + page_size,
  so that clamping works properly. Set the page_increment to be slightly
  less than the page_size so there is some overlap, as is customary.
StScrollView: Remove unnecessary fabs() calls, rewrite expressions
  for additional clarity.

https://bugzilla.gnome.org/show_bug.cgi?id=611740
2010-03-11 15:08:48 -05:00
f6cbb14393 Incremental fixes for scrollview work
- Fix existing typos and spacing problems
- Get preferred height, not current height, of shadows
- Let shadows overflow don't clamp them when we have too little space
- Remove a now-unecessary stray MAX()
- Fix up scrollview visibility for the pathological case of no child
- Disconnect from adjustments on remove()
- Don't unset the adjustments on the child on remove(), since they
  already existed or were autocreated on add()

  (We should what we are doing and set the adjustments of the
  scrollbars on the child rather than setting the adjustments of
  the child, so we match GTK+'s scrolllable interface, but this
  at least makes it consistent instead of a weird mix.)

https://bugzilla.gnome.org/show_bug.cgi?id=611740
2010-03-11 15:08:48 -05:00
ffd25fe9e4 Fix size negotiation for StScrollView
StScrollable: Document how size negotation now works between the
  parent and scrollable child.

StBoxLayout: Adapt to the new contract for how size negotiation
  works; in particular, handle being allocated less than the
  minimum size when scrolled and treat the minimum size as the
  size of the scrolled area in instead of the natural size.

StScrollView: Substantially rewrite with fixes including:
 - Implement new size negotation contract; this allows us
   to determine scrollbar visibility without having to
   connect to the adjustment.
 - Implement all ALWAYS along with the existing NEVER/AUTO
 - When hiding and showing scrollbars and shadows, don't
   hide and show widgets, just turn on and off including them
   in pick and paint. This avoids queueing relayouts.
 - Cleanups for the code for connecting to adjustments,
   for changing policy, and for turning on and off shadows.

scroll-view-sizing.js: New test case for StScrollView, allowing
  resizing the scroll view interactively, changing the scrollbar
  policies and turning shadows on and off.

https://bugzilla.gnome.org/show_bug.cgi?id=611740
2010-03-11 15:08:48 -05:00
524e2ca8e2 [StScrollBar] avoid queueing a relayout during allocation
When an StScrollView is allocated, allocating the child would
cause the adjustment values to change, which would result in
the scrollbars queueing a relayout, which isn't allowed during
allocation.

To avoid this, instead of queueing a relayout when the adjustment
changes:

 - When we have a valid allocation already, just go ahead
   and reallocate the children.
 - Otherwise do nothing immediately and wait until we get allocated

Because the 'needs_allocation' flag in ClutterActor isn't exposed,
this requires some slightly ugly code to shadow that state locally.

https://bugzilla.gnome.org/show_bug.cgi?id=611944
2010-03-11 15:08:48 -05:00
33dca51650 Rework StDrawingArea not to use ClutterCairoTexture
Having StDrawingArea use ClutterCairoTexture causes circularity
problems with sizing - StDrawingArea wants to use its allocation for
the size of the texture, but ClutterTexture wants to use the size of
the texture to determine the requited size.

Avoid this by making StDrawingArea directly use Cairo and CoglTexture;
while doing this, the API is changed a bit for simplicity and to
match our use case:

 - Instead of clutter_cairo_texture_create(), we have
   st_drawing_area_get_context() to retrieve an already created
   context. This can only be called in the ::repaint signal.

 - The ::redraw signal is changed to ::repaint so we can have
   st_drawing_area_queue_repaint() that doesn't collide with
   clutter_actor_queue_redraw()

 - ::repaint is now emitted lazily when painting the actor rather
   than synchronously at various different points.

https://bugzilla.gnome.org/show_bug.cgi?id=611750
2010-03-11 15:08:48 -05:00
58bb0044b2 Support and require Clutter 1.2
- Specify a minimum version of clutter-1.2.0
 - Switch clutter branch in the moduleset to master
 - Replace deprecated cogl_texture/material_unref() with
   cogl_handle_unref()
 - Use cogl_clip_push_rectangle() rather than cogl_clip_push()
 - Replace cogl_check_extension() with strstr - should be
   accurate enough.

https://bugzilla.gnome.org/show_bug.cgi?id=610679
2010-03-11 15:08:48 -05:00
79865172d3 Adjust more-apps menu to better match the overall theme
https://bugzilla.gnome.org/show_bug.cgi?id=612452
2010-03-11 18:23:10 +01:00
730e8ffdf9 Add get_horizontal/vertical_padding() methods
Add get_horizontal_padding() and get_vertical_padding() methods,
that return the total padding (LEFT+RIGHT or TOP+BOTTOM).

https://bugzilla.gnome.org/show_bug.cgi?id=597983
2010-03-11 18:04:37 +01:00
d128cc5af3 st_widget_get_theme_node: g_error if called on an unparented widget
It's wrong to do anything that requires looking up a widget's style
before you add the widget to the stage, since its final style may
depend on properties inherited from its parents.
st_widget_get_theme_node() used to emit a warning in this case, but
many would-be contributors apparently didn't notice. Help them out.

https://bugzilla.gnome.org/show_bug.cgi?id=610279
2010-03-10 09:29:48 -05:00
b5c2e1c98c Updated French translation
Contributed by Pablo Martin-Gomez and Claude Paroz
2010-03-09 22:55:53 +01:00
2016e08f7b Don't activate workspace when more than one window is open
Currently clicking on an empty spot on the workspace actors switches to the workspace, this has a side effect that when for some reason (like using a touchpad),
the user misses the window he intends to open he will end up with the currently focused window instead.

Disable this behaviour if more than one window is open (in that case the user has to explicitly target a specific window).

https://bugzilla.gnome.org/show_bug.cgi?id=610868
2010-03-09 22:35:51 +01:00
e752193a54 [StTextureCache] The requested size needs to be part of the cache key
Otherwise we'll only render it once, which is clearly wrong.
2010-03-09 14:08:22 -05:00
88a4256ad5 Updated Norwegian bokmål translation 2010-03-09 17:47:30 +01:00
62ca7fb268 [runDialog] Support opening files and folders
Support completion on files and folders in the run dialog and launch
the default application when activated. Assume a path relative to the
home directory if execution as command fails and the input doesn't start
with a slash.
Removed workaround for relayout of error messages.

https://bugzilla.gnome.org/show_bug.cgi?id=611209
2010-03-09 00:12:58 +01:00
765779272f Look at current mouse position for dropping
Previously we used the top-left corner which was not intuitive,
particularly when dragging partially opaque actors.
https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-09 01:53:27 +03:00
3333f30c42 Convert border_width, border_radius to integers
This saves the consumers from having to deal with rounding.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-08 16:46:47 -05:00
732ba8576d Set this._notificationRemoved to false in _hideNotificationComplete()
We used to set this._notificationRemoved to false in _hideNotification().
However, the user focusing on the associated application can result in the
source being removed while the notification is hiding, in which case
this._notificationRemoved was set to true and never unset. This resulted in
the next notification only showing up briefly and hiding. Moving setting
this._notificationRemoved to false to _hideNotificationComplete() fixes this
behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=611122
2010-03-08 16:39:52 -05:00
a4481b38d2 Remove st_widget accessors for background and border actors
StButton animated the background for button transitions; since these aren't
presently part of the shell design, simply remove them.  We can readd
these in the future.

StTooltip should probably have :vertical and :horizontal pseudo classes
to make the arrow work but it should still function.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-08 16:28:34 -05:00
176487834a Add st_texture_cache_load
Function for caching texture data from an arbitrary origin.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-08 15:50:59 -05:00
394e01850b Rework internals to be string based
Rather than having ShellTextureCache know about the type of each
item it's caching, this lays the foundation for simply caching
arbitrary string -> CoglHandle.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-08 15:10:35 -05:00
5f8391314a Add hover style property
Set the entry's pseudo class to "hover" when the pointer enters the
inactive widget and reset it appropriately on leave.

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-03-08 19:33:12 +01:00
d593877548 fix issues with hint text
Add a "hint_visible" private variable to keep track of when the hint text
is visible. Use this to determine whether to return the text from the
internal ClutterText or whether to return an empty string.

Fixes: http://bugzilla.moblin.org/show_bug.cgi?id=6837
       http://bugzilla.moblin.org/show_bug.cgi?id=6836

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-03-08 19:33:11 +01:00
d2bf7ec66c add missing import
https://bugzilla.gnome.org/show_bug.cgi?id=612018
2010-03-08 14:41:54 +01:00
fe0f4060c4 [Overview] Fix click handling of open panes
The top part of the application pane closes the pane, while outside
the menu only the workspace area accepts clicks for closing the pane.
Let the user close the pane by clicking anywhere outside the menu, but
not inside.

https://bugzilla.gnome.org/show_bug.cgi?id=611641
2010-03-07 23:53:06 +01:00
40b0459174 [Overview] Delay repositioning after closing windows
When closing windows in the window picker, the remaining windows
move to their new positions, which prevents the user from performing
additional actions in the picker until the animation stops and the
user adjusts to the new layout.

Instead we try to be smart and delay the repositioning, either until
the pointer stops moving or until it leaves the workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=611167
2010-03-07 23:45:46 +01:00
a0b5a44fe9 [StEntry] Make the cursor size stylable
Just as the cursor color can be styled using the "caret-color"
property, expose the cursor size as "caret-size".

https://bugzilla.gnome.org/show_bug.cgi?id=611095
2010-03-07 23:45:44 +01:00
5ce1e3fe92 Add st_texture_cache_load_file_to_cogl_texture
For StWidget we want the ability to load raw CoglHandle references
rather than having a big pile of actors backing StWidget.

Several bits of StWidget expect to be able to synchronously load
textures; this is a crutch to support that until we can cleanly
make this asynchronous.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-05 17:08:36 -05:00
8b3258cb09 Revert "Clean up definition of dragOffsetX, dragOffsetY"
This reverts commit aa7de264e6.
2010-03-05 16:57:09 -05:00
22948b3d39 Merge St.TextureCache and Shell.TextureCache
Brute force merge these two by essentially replacing St.TextureCache
with a (renamed) Shell.TextureCache.

One function was added for convenience, namely "st_texture_cache_load_file_simple".
St.TextureCache had a function to load a texture from a filename, and it
returned NULL on error but only half the callers actually checked this.  This
function is better.

https://bugzilla.gnome.org/show_bug.cgi?id=607500
2010-03-05 16:19:40 -05:00
aa7de264e6 Clean up definition of dragOffsetX, dragOffsetY
These variables were computed strangely; through cancellation
they'd end up being negative 1/2 the width/height of the actor,
so just use that directly.

https://bugzilla.gnome.org/show_bug.cgi?id=607821
2010-03-05 15:29:29 -05:00
046e0609ab Improve 12/24 clock detection
The current check looks at whether there was some am/pm suffix in the
localized time; however in some cases (locales) that does not seem to
work. this version instead checks whether the localized versions of 05:00 and
17:00 start with the same two digits; if not, it's probably a 24h clock.

https://bugzilla.gnome.org/show_bug.cgi?id=603488
2010-03-05 12:02:18 -05:00
1a0d507316 [ShellGenericContainer] When removing actors, remove them from skip_paint
This fixes a regression introduced by the previous patch.
2010-03-04 17:38:35 -05:00
b5853fe7e5 [ShellGenericContainer] make this an StWidget
https://bugzilla.gnome.org/show_bug.cgi?id=611647
2010-03-04 15:43:02 -05:00
0f81c7efe0 [ShellGenericContainer] minor style fixes
https://bugzilla.gnome.org/show_bug.cgi?id=611647
2010-03-04 15:41:26 -05:00
0f0e3d9644 [ShellGenericContainer] remove example
There are plenty of examples in js/ui/ now

https://bugzilla.gnome.org/show_bug.cgi?id=611647
2010-03-04 15:41:26 -05:00
f6b4fa6e7e [St] share common ClutterContainer implementation code
https://bugzilla.gnome.org/show_bug.cgi?id=611647
2010-03-04 15:41:25 -05:00
fbb88da134 [search] Fix activation of results from custom renderers
The previous commit broke activation when selecting an actor
from a custom renderer.  Fix this by explicitly defining a method
activateSelected on the search renderer.
2010-03-04 15:12:06 -05:00
83f11870da Use AppWellIcon for search results
Switch to using an application icon as per design.

We need to drop the 4 pixels padding to ensure we fit 3 icons.

There was a typo where getVisibleCount should have been getVisibleResultsCount.

https://bugzilla.gnome.org/show_bug.cgi?id=610740
2010-03-04 14:08:13 -05:00
c635cb7016 [ShellGenericContainer] Add method to get number of skipped children
This will be used in search results.

https://bugzilla.gnome.org/show_bug.cgi?id=610740
2010-03-04 14:08:13 -05:00
dd23a61dbb [gnome-shell.modules] Skip all modules in gir-repository except those we need
Otherwise we're much more subject to random build failures from e.g.
GStreamer updates or the like.
2010-03-03 17:18:49 -05:00
2e00bc4aed Add gnome-shell-full target
This basically drops gir-repository, but pulls in GTK+ and stack.

TODO on this - we need to patch GTK+ to (possibly optionally)
pull in stuff like pixbuf loaders and themes from the system as well.

https://bugzilla.gnome.org/show_bug.cgi?id=610993
2010-03-03 16:48:42 -05:00
6423cbfc92 Fix problems on destruction
StScrollBar: Be robust against being disposed multiple times,
  which can happen, and in fact, normally happens when destroying
  the parent.

StScrollView: Implement remove() for the hscroll and vscroll members,
  and just destroy them in dispose() and let them be removed.
  unparent the shadows, instead of just unref'ing them directly.

https://bugzilla.gnome.org/show_bug.cgi?id=611203
2010-03-02 16:37:05 -05:00
ed3e287d91 Updated Finnish translation. 2010-03-02 08:27:50 +02:00
347196d35c [panel] Fix RTL for appMenu, allocation, other misc.
Other misc includes:
* Remove some unused CSS
* Readd comments

https://bugzilla.gnome.org/show_bug.cgi?id=611288
2010-03-01 13:34:20 -05:00
2ab3d069fb (revert autobuilder test break) 2010-03-01 13:34:20 -05:00
21641d8925 Clip workspace area in grid view
When workspaces slide in/out in mosaic view, they may cross with the
workspace controls, which looks pretty weird.

Also adjust the vertical spacing in the grid view so that the grid height
matches the workspace height in the linear view.

https://bugzilla.gnome.org/show_bug.cgi?id=610350
2010-03-01 19:42:55 +01:00
499c5737da [Overview] Base minimum motion on actors
When figuring out where to position window previews, use the clone's
position instead of the the original meta window. There shouldn't be
a difference when entering the overview, but it makes the motion when
opening/closing new windows in the overview tinier and more predictable.

https://bugzilla.gnome.org/show_bug.cgi?id=611167
2010-03-01 19:42:55 +01:00
40a8e9c1a6 Fix tracking of single-process multi app cases
When starting oocalc or ooimpress from oowriter's menu get_app_for_window,
fails to recognize the newly started up as such, which result into the appMenu
still showing "Openoffice.org Writer" as app name.

Fix this by trying to window itself first before using the group for finding the app.

https://bugzilla.gnome.org/show_bug.cgi?id=611288
2010-03-01 19:29:39 +01:00
2e98aab2e7 Revert "(autobuilder test) Really break the build"
This reverts commit 760b6ad9ed.
2010-03-01 10:59:51 -05:00
760b6ad9ed (autobuilder test) Really break the build 2010-03-01 10:52:31 -05:00
14434601a3 (autobuilder test) Test commit to break the build 2010-03-01 10:38:29 -05:00
ae3d1423e5 [panel] Handle async load of icons correctly
Fading the application icon required the texture to have already been
loaded, which was normally the case since we create icons for apps
in the well and browser; but when finding an app not from there,
the cogl-texture for the icon might not be available.

Fix this by watching for the texture and fading when it appears.

https://bugzilla.gnome.org/show_bug.cgi?id=611288
2010-02-28 15:53:22 -05:00
d56fbf6d6a [panel] Fix AppPanelMenu's allocation
Because we were setting the "fixed-position-set" property
on the internal label, its width/height requests weren't
being accounted for in the size request of the overall box.

The way we were hooking up to notify::allocation was hacky; do
this correctly by simply implementing a container.

https://bugzilla.gnome.org/show_bug.cgi?id=611288
2010-02-28 15:53:22 -05:00
b7c60b02d1 [StEntry] Add annotations
All setters in StEntry allow to pass NULL - add appropriate annotations.
2010-02-27 18:03:37 +01:00
d7075d9913 [lookingGlass] Add style information to the picker
Currently the picker displays information on the hovered actor's
position and the object itself. Adding style id and class of
StWidgets to the displayed information can be very helpful for
identifying a particular actor or code segment.

https://bugzilla.gnome.org/show_bug.cgi?id=611211
2010-02-26 23:33:30 +01:00
72cb4bf346 Port Lightbox to CSS and use it in runDialog
Make Lightbox stylable and add a common style. Use it in runDialog.
https://bugzilla.gnome.org/show_bug.cgi?id=604978
2010-02-26 23:16:55 +03:00
bffadf1b6e Improve run dialog
Bind <Ctrl>+<Return> for run in terminal.
Port runDialog to css.
https://bugzilla.gnome.org/show_bug.cgi?id=604978
2010-02-26 20:22:39 +03:00
8552721983 [gnome-shell.in] When we don't have DISPLAY, attempt to pull in running session
This is a convenience for debugging when logging in over ssh.  Longer term
we should stick this code (in a more OS portable fashion) into ConsoleKit.
2010-02-25 14:46:27 -05:00
ec36a0070e fix manual placement for RTL locales
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-02-25 14:45:07 -05:00
216dafd5b1 fix menu position for RTL locales
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-02-25 14:45:05 -05:00
a4feb91644 Fix single-actor widgets
clutter_actor_unparent() is for use by container implementations only,
unlike gtk_widget_unparent()

https://bugzilla.gnome.org/show_bug.cgi?id=588090
2010-02-25 14:42:58 -05:00
778fd72e22 Updated German translation 2010-02-25 10:30:49 +01:00
ff01bf68fd Simulate a focus-app change when leaving the overview
When the currently focused app sends a notification while in the overview,
the corresponding source icon is not removed when the overview is left.
It does make some sense to treat the overview transition the same as a
normal focus change, so we should update the summary view accordingly.
2010-02-24 22:13:36 +01:00
edbfafc5bd Fix clicking on notification icons after updates
When a notification is updated by the application, the corresponding
app in its source is lost, so it is no longer possible to switch to
the application by clicking either the notification or the summary icon.
As the associated application of a source never changes, it appears safe
to leave it alone on notification updates.

https://bugzilla.gnome.org/show_bug.cgi?id=610820
2010-02-24 19:57:35 +01:00
c20a7d4b01 Updated Polish translation 2010-02-24 18:29:24 +01:00
c4e0e4197d [ShellGlobal] Add shell_global_breakpoint
This is useful for debugging with gdb.
2010-02-23 18:51:27 -05:00
71f63962a8 Updated Danish translation 2010-02-23 22:07:06 +01:00
ef4c9b6f1f [StThemeNode] allow "background-gradient-direction: none"
this lets a more-specific CSS rule turn off the gradient inherited
from a less-specific rule

https://bugzilla.gnome.org/show_bug.cgi?id=610856
2010-02-23 14:44:57 -05:00
4d43424efd Remove source icon when a corresponding window is activated
Source icons are no longer needed to inform the user about events
having occured in a particular application when (s)he activates the
window - treat that case just as if the user had clicked the source
icon.

https://bugzilla.gnome.org/show_bug.cgi?id=610494
2010-02-23 19:03:20 +01:00
1f1f4432f6 Use gjs_context_get_native_context()
When exported into a public header, gjs_context_get_context() was
renamed to gjs_context_get_native_context(). Adapt, and remove
local prototype.

https://bugzilla.gnome.org/show_bug.cgi?id=610845
2010-02-23 11:54:56 -05:00
98e60eb7e9 Fix installation of .mo files
The recent cleanup of the configure.ac cleanups accidentally
removed AC_SUBST(GETTEXT_PACKAGE); more precisely restore this
section back to its original state.

https://bugzilla.gnome.org/show_bug.cgi?id=610787
2010-02-23 10:43:39 -05:00
16bdff4f48 Bump version to 2.29.0 2010-02-22 22:09:50 -05:00
565cdf502c Distribute manual page
Switch from man_MANS to dist_man_MANS so gnome-shell.1 is distributed.
2010-02-22 22:09:50 -05:00
2dc8d9b462 Fix include path when building Shell-1.0.gir
Since shell-slicer.h includes st.h, and that includes
<st/*.h>, we need to add -I $(srcdir) to the command line when
running g-ir-scanner to generate Shell-1.0.gir.
2010-02-22 22:07:52 -05:00
ce6dd21cd3 Don't generate st.h in a subdir
For srcdir != builddir, in the builddir, the st/ subdirectory doesn't
exist, so we can't generate st.h there. Just switch to building st.h
directly in the current directory. (The other option would be to
create a st/ subdirectory in the builddir if necessary; might be a
little cleaner, but this works for now and gets things distchecking.)
2010-02-22 19:37:49 -05:00
e7066d12cf Convert the check-for-missing files check to a python script
'git ls-files --exclude=<pattern>' was changed (intentionally!)
not to exclude anything files that are actually in the index.
Since git ls-files by default simply lists the files in the
index, this is a problem. Emulating this in shell went past
the limits of what made sense, so move it to a simple external
python script.
2010-02-22 19:37:49 -05:00
09df6a3818 Clean up unnecessary changes to configure.ac
Remove unnecessary checks for headers and functions, revert
changes to internationalization that introduced duplication.

(Based on a patch by Javier Jardón)

https://bugzilla.gnome.org/show_bug.cgi?id=609205
2010-02-22 19:37:49 -05:00
17d1e06c7c Remove check-news from AM_INIT_AUTOMAKE
Duplicating information from release announcements in NEWS
will quickly result in a huge NEWS file.
2010-02-22 19:37:48 -05:00
e6b80927ad Fix demands attention to work with new messagetray api 2010-02-22 23:43:02 +01:00
f9c5202dd1 Always make notifications with '\n' in bannerText expandable
Right now notifications are expandable if the length of bannerText
exceeds the notification's width - however, if bannerText contains
newlines, it should be expandable regardless of the length.

https://bugzilla.gnome.org/show_bug.cgi?id=610549
2010-02-22 23:41:09 +01:00
a21ba292eb Cancel zoom of non-focused windows when leaving overview
When leaving the overview by hitting escape or super, all windows animate
to their original positions. Zoomed windows are kept above others until
the animation ends, then the focused window is brought to the front; as
this looks odd if the zoomed window does not have focus, cancel the zoom
in that case before leaving the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=609243
2010-02-22 23:41:09 +01:00
5429104f04 Fix problems when leaving the overview with a zoomed window
While zooming, a window clone is reparented to the stage and thus cannot
be destroyed automatically by the "parent" container. To prevent the clone
and the corresponding overlay from leaking, we enforce destroying the clone
with the workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=609243
2010-02-22 23:41:09 +01:00
bb0a977edc Special-handle Empathy to have multiple sources and to queue notifications
We are planning to add Empathy-specific features in the message tray, but in the
meantime we handle Empathy notifications received through the notification daemon
so that their behavior is closer to the eventual design, which is how it was before
we started associating applications with a single source and enabled notification
replacement.
2010-02-22 17:27:23 -05:00
77ed621c74 Associate sources with applications
Use the "appName" parameter in notifications to identify the source
rather than the id - use the latter to enable update and removal of
individual notifications as laid out in the desktop notification spec.

This is a rebase of the patch by Florian Müllner.
2010-02-22 17:21:00 -05:00
fc39919856 Add top and bottom shadows to app browser
Add a 'vshadow' property to StScrollView, which, when turned on,
overlays gradient shadows on the top and bottom of the StScrollView.

Turn this on for the StScrollView used for the app browser.
https://bugzilla.gnome.org/show_bug.cgi?id=609604
2010-02-23 01:12:13 +03:00
d8800c095a NotificationDaemon: add rewriteRules infrastructure, use it for xchat
Changes notifications like:

    XChat: Private message from: danw (GimpNet) blah...

to

    danw: blah blah blah blah

(the "XChat" being unnecessary since there's already an xchat icon
there anyway.)

https://bugzilla.gnome.org/show_bug.cgi?id=608915
2010-02-22 17:09:13 -05:00
e5ba414f2d Add the workspaces view key to the gconf schema
Also rename the key to make it less ambiguous, and change its value
from an int to a string.

https://bugzilla.gnome.org/show_bug.cgi?id=609871
2010-02-22 17:01:47 -05:00
b8a9eec14f Make width of workspace switcher popup dynamic
Make the width of the workspace switcher dynamic in order to make it have the same proportions as the actual screen.

Call redraw after adding indicator to stage to avoid warning.

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

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
2010-02-22 20:29:49 +01:00
059504ca70 Add demands attention support to the messagetray
Inform the user about demands attention events using the messagetray.

Clicking on the notification icon moves the user to the window.

It differentiates between newly started apps and windows of already running apps, by showing different banners for this cases.

It is based on Jon Nettleton's "window attention" extension.

https://bugzilla.gnome.org/show_bug.cgi?id=610594
2010-02-22 20:09:43 +01:00
b2db95380b [MessageTray] Clear bannerText before re-adding on updates
Currently only the old title/summary line is removed from
notifications before setting the updated values - do the
same for bannerText if applicable.
2010-02-22 20:14:44 +01:00
b6bb26e9ae Add additional padding to the view specific workspace controls
In the latest mockup, there is more spacing around the scroll bar than
between the other controls.

https://bugzilla.gnome.org/show_bug.cgi?id=610189
2010-02-22 18:47:04 +01:00
126d02ae90 Fix invalid call to st_widget_get_theme_node() in WindowOverlay
WindowOverlay has two actors, both with custom style properties, which
share a common _onStyleChanged() handler. This is not a problem when
entering the overview, because the actors' parent (the workspaces group)
is hidden while the actors are added. However, when windows are added to
the workspace while in the overview (e.g. when opening a new window or
dragging a window from one workspace to another), adding the first actor
to the workspaces group triggers a style-changed signal - the handler
then calls st_widget_get_theme_node() on both actors, which triggers a
warning as the second actor has not been parented yet.

https://bugzilla.gnome.org/show_bug.cgi?id=610279
2010-02-22 18:33:58 +01:00
8d76e362a0 _computeWindowMotion calculate difference between relative positions
https://bugzilla.gnome.org/show_bug.cgi?id=607826
2010-02-22 20:14:13 +03:00
004cf3da5c [appDisplay] Use AUTOMATIC for apps-more, not ALWAYS
No need to display a scrollbar if we don't need to, and ALWAYS
isn't yet implemented anyways.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-22 12:07:23 -05:00
fb9fd6925a [StScrollView] Fix incorrect assertion, defaults, and test case
The type we don't currently handle is _ALWAYS, my original use
of g_return_if_fail was wrong.

Also the default should be AUTOMATIC in the properties, not ALWAYS.

Finally the test case was still using the incorrect St.ScrollPolicy.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-22 12:06:56 -05:00
ec725cc6d4 [Notification] Replace all newlines in body with spaces
Accidentally we only replaced the first newline of the body text with
spaces - replace all occurrences instead.

https://bugzilla.gnome.org/show_bug.cgi?id=610549
2010-02-21 03:54:13 +01:00
79fe60e6fb [messageTray] Fix text with ampersands not being displayed
If the notification body contains '&' it ends up empty and a warning
about an invalid entity is printed on stderr, so our escape code must
handle ampersands as well.

https://bugzilla.gnome.org/show_bug.cgi?id=607375
2010-02-21 03:54:06 +01:00
c793d7d0a4 get_app_for_window_direct search ShellApp by window, before create.
https://bugzilla.gnome.org/show_bug.cgi?id=610324
2010-02-21 03:19:24 +03:00
1b7c3580e6 Show/hide the summary during the overview transition
Right now, the summary starts popping up when the overview has been
shown and starts to disappear when the overview is hidden. Instead,
animate the summary during the overview transition.

https://bugzilla.gnome.org/show_bug.cgi?id=610520
2010-02-20 20:05:50 +01:00
3c3e0b6f20 Updated Bulgarian translation 2010-02-20 14:30:00 +02:00
fd6863dda4 Add missing section-more-open file from previous commit 2010-02-19 15:52:56 -05:00
690be611ee Implement newer design for "more apps" view
Replace the old GenericDisplay-based system with one which reuses
the WellGrid class and uses a new scrolling container.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-19 15:39:26 -05:00
18c5405b79 [StScrollView] Add support for GtkPolicyType for scrollbars
Previously we were hacking out the vertical scrollbar, this patch
allow us to sanely say in which directions we want to scroll.

Note this patch intentionally changes St to depend on GTK+ in the
API.  I believe this is a correct long term change where we should
view St as co-evolving with GTK+ rather than replacing or paralleling.

https://bugzilla.gnome.org/show_bug.cgi?id=609015
2010-02-19 15:37:40 -05:00
cfd63c7d4c fix selection of all-workspace windows
all-workspace windows can be active on every workspace.
https://bugzilla.gnome.org/show_bug.cgi?id=603078
2010-02-19 21:29:46 +03:00
49a9335f68 fix sizing of all-workspace windows in the overview
Window can have more then one clones on different workspaces.
https://bugzilla.gnome.org/show_bug.cgi?id=603078
2010-02-19 21:29:35 +03:00
5b1d52c5e7 Fix build problem with mutter 2.29
Query mutter's version more or equal 2.29.0
2010-02-19 20:54:47 +03:00
9f43ed3f95 Use _onDestroy() handlers for cleanup in delegates
Unify the style of <delegate>.destroy() methods to only contain a
call to <delegate>.actor.destroy() and handle additional cleanup
in a _onDestroy() signal handler.

https://bugzilla.gnome.org/show_bug.cgi?id=609454
2010-02-18 22:50:34 +01:00
0770fd5be5 Use St.Button for preview close buttons
Originally, we used St.Bin for the preview close buttons - using
St.Button instead adds support for pseudo classes to style different
button states.
2010-02-18 19:25:28 +01:00
3c8ba348c2 Slide out removed workspaces in linear view
Instead of deleting workspaces immediately, animate the removal - it may
be useless eye-candy, but it's pretty sexy nonetheless ...
More seriously, the animation improves consistency with both workspace
additions and the mosaic view.

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:37:05 +01:00
b84a7042f1 Make spacing between workspaces stylable
Currently the width of the gaps between workspaces in both linear
and mosaic view are defined as constants. Move these to the theme's
CSS instead.

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:37:05 +01:00
8ef75524ea [Workspaces] Clean up scrolling in linear view
Reorganize the code to break up positioning into:

1) updating workspace object's scale and position
2) applying the updated parameters to the workspace actor
3) scrolling the view to a particular workspace
4) handling dragging of the scroll bar

With these cleanups, it becomes much easier to fix
the following issues:

- use animations consistantly instead of doing hard breaks
  for some actions and smooth transitions for others
- snap to the closest workspace when scrolling stops
  (https://bugzilla.gnome.org/show_bug.cgi?id=607823)
- fix the regression of the zoomFromOverlay animation when
  the selected app is on another workspace
  (https://bugzilla.gnome.org/show_bug.cgi?id=609081)

https://bugzilla.gnome.org/show_bug.cgi?id=609673
2010-02-17 23:36:58 +01:00
cec62a7ca5 Main.activateWindow: always exit the overview if it's currently open
This way, clicking a message tray icon while the overview is open will
close the overview when activating its window.

Remove some other overview-related activation code which is now
redundant.

Also, remove calls to "global.get_current_time()" when calling
Main.activateWindow, since it's unnecessary (activateWindow will call
it itself if you don't pass in that arg).

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:08:28 -05:00
77fe0db623 [MessageTray] Show the message tray in the overview
Also, make the summary area always visible when in the overview

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:08:24 -05:00
e86c821878 [MessageTray] reimplement the state machine
Previously, every time _updateState was called, it would make some
change, and so it was necessary to very carefully set up all the calls
to it, to ensure it was always called at exactly the right time. Now,
instead, we keep a bunch of state variables like "_notificationState"
and "_pointerInSummary", and potentially multiple timeouts, and
_updateState looks at all of them and figure out what, if anything,
needs to be changed.

By making the rules about what causes changes more explicit, it will
be easier to change those rules in the future as we add new
functionality.

Also, update the rules a bit, so that notifications can appear while
the summary is visible, and the summary only shows after a
notification if the summary has changed.

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 17:06:17 -05:00
02f67af464 [MessageTray] Fix summary to be initially-hidden
Some recent change broke it so that the first time a notification pops
up, the summary will be visible alongside it.

https://bugzilla.gnome.org/show_bug.cgi?id=609765
2010-02-17 14:45:59 -05:00
fd310bc7b9 Correct position of window previews.
align the bottoms of the window previews.
window previews always fit in the slot.
https://bugzilla.gnome.org/show_bug.cgi?id=610070
2010-02-17 19:56:45 +03:00
94d3e27c53 [Overview] Fix tiled background images
Tiled backgrounds are only displayed once in the upper left corner when
in the overview - they should be tiled just like outside the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=610203
2010-02-17 17:34:38 +01:00
6aa02c5edc [AppSwitcher] Make sure that fallback icons have correct box sizes
Fallback icons (i.e icons < requested size) cause the box in the switcher
to be a smaller rectangular item instead of the normal sized square one.

Fix that by putting the icons in a St.Bin with the correct size.

https://bugzilla.gnome.org/show_bug.cgi?id=609777
2010-02-17 10:52:11 +01:00
97e19d7d4a Adjust behavior of search results to match app well
Currently, activating a search result always opens a new window. Change
this behavior, so that if an application has open windows, the most
recently used one is activated instead.

Also change the implementation of dnd of search results to allow providers
to treat results activated via dnd differently.

https://bugzilla.gnome.org/show_bug.cgi?id=610027
2010-02-16 23:50:35 +01:00
94f32030e6 [MessageTray] notification size/wrapping fixes
Make the font match the panel.
Make the max width be em-based rather than screen-size-based.
Fix it to break lines mid-word if needed.

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-16 14:08:17 -05:00
721e1ea863 [St] Implement max-width/max-height in the CSS parser
st_theme_node_adjust_preferred_width/height now limit the content area
of an actor to the max, if given. (The requested width/height may be
larger to make room for borders, etc.)

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-16 14:08:17 -05:00
5331d3e360 [St] Make allocation handling more consistent
In StBin, StBoxLayout, and StTable, if a child has a potential
allocation that is larger than its preferred size, we give it its
preferred size instead. However, the corresponding
get_preferred_height/width methods were not making the same
assumption, which meant that if we had more width than the widget
wanted, we would allocate it its preferred width, but with the height
that corresponded to the larger width.

Fix this by defining new helpers _st_actor_get_preferred_width() and
_st_actor_get_preferred_height() and using them everywhere. Also, make
StBin and StTable use _st_allocate_fill() rather than having
nearly-identical duplicate copies of the code.

https://bugzilla.gnome.org/show_bug.cgi?id=609848
2010-02-16 14:06:39 -05:00
f52744cfbc [StTable] fix x-align/y-align properties to be StAlign, not double
This puts it in sync with StBin and StBoxLayout

https://bugzilla.gnome.org/show_bug.cgi?id=609848
2010-02-16 14:06:39 -05:00
4749393ab5 Remove panel-run-dialog/main-menu handling from shell-global
This is handled by the shellwm (takeover_keybinding) nowdays.

https://bugzilla.gnome.org/show_bug.cgi?id=610039
2010-02-16 16:50:40 +01:00
975603d608 Updated Vietnamese translation 2010-02-16 19:36:49 +07:00
99346522e9 Hungarian translation updated 2010-02-16 10:10:45 +01:00
090335ad8b [MessageTray] fix notifications with short banners and action buttons
Previously the banner was only promoted to the body if it got
truncated, but the banner was *always* hidden when expanding the
notification. This meant a message with a short banner, plus
notification buttons, would have no banner text visible when it was
expanded. Fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-15 17:28:23 -05:00
d8af8f7305 [CSS] Update overview style to match latest mockup
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-15 22:14:31 +01:00
2a2b597e09 [Overview] Make background color stylable
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-15 22:14:28 +01:00
da1d43fc61 Updated Spanish translation 2010-02-15 21:46:19 +01:00
03a750176b Fade out desktop icons when showing overview
As desktop icons don't have any purpose in the overview (except for
distracting the user), fade them out when entering the overview.

Unfortunately, the fading effect affects performance, therefore hide
icons directly when there are maximized windows on the desktop.

https://bugzilla.gnome.org/show_bug.cgi?id=600999
2010-02-15 21:49:11 +01:00
1d2bb5c51c Updated Slovenian translation 2010-02-15 19:04:25 +01:00
60046aaa4f Switch to the corresponding app when the notification icon is clicked
This adds some meaningful functionality to the notification icons in the tray
and in the notification pop-up and allows to switch to the application that
sent the notification.

We get the application from the notification context and set it on the source
for the notification.
2010-02-15 12:27:28 -05:00
a6df234528 Make workspace indicators drop targets
Allow dropping on the workspace indicators to open apps on specific workspaces.

https://bugzilla.gnome.org/show_bug.cgi?id=609913
2010-02-15 17:24:44 +01:00
5ead0de7ca .gitignore: add po/gnome-shell.pot 2010-02-15 08:35:16 -05:00
229cfd9f80 xgettext only recognizes _("foo"), not _('foo') in .js files. Fix
Noted in https://bugzilla.gnome.org/show_bug.cgi?id=609838
2010-02-15 08:33:35 -05:00
01c267b095 POTFILES.in: add missing files that have translatable strings
https://bugzilla.gnome.org/show_bug.cgi?id=609838
2010-02-15 08:10:28 -05:00
33a6c41810 Updated Spanish translation 2010-02-15 11:26:12 +01:00
7040e9a63b Updated Norwegian bokmål translation 2010-02-14 13:46:32 +01:00
901eabb82d Fix problem with make system.
https://bugzilla.gnome.org/show_bug.cgi?id=609811
2010-02-13 18:41:13 +03:00
b11aa5f676 vi.po: Updated "favourites" translation 2010-02-13 22:01:28 +07:00
ccaa11bb6b Added Vietnamese translation 2010-02-13 21:23:29 +07:00
dd0fba4270 Revert "Add workspaceSwitcherPopup.js to Makefile.am"
This reverts commit 3f6759061d.

Proper fix is in https://bugzilla.gnome.org/show_bug.cgi?id=609811
2010-02-13 15:16:53 +01:00
3f6759061d Add workspaceSwitcherPopup.js to Makefile.am
Re add accidentally omitted change.

https://bugzilla.gnome.org/show_bug.cgi?id=609187
2010-02-13 15:12:39 +01:00
abc7b1ff02 New workspace switcher popup
Replace the current workspace switcher popup (which is still the old metacity popup), with a clutter based one, which fits better into the overall shell design.

https://bugzilla.gnome.org/show_bug.cgi?id=609187
2010-02-12 23:52:15 +01:00
75a677701d .gitignore: add m4/ 2010-02-12 10:19:31 -05:00
11656ebd89 Remove duplicate GETTEXT_PACKAGE 2010-02-11 15:29:58 -05:00
d62b4cf130 Modernize autotools configuration
New requirements:
autoconf >= 2.63
libtool >= 2.2.6
intltool >= 0.40.6
pkg-config >= 0.22

Fixes https://bugzilla.gnome.org/show_bug.cgi?id=609205
2010-02-11 21:02:21 +01:00
c4b3d18e26 Updated Slovenian translation 2010-02-11 20:56:03 +01:00
38b7904f92 Distinguish translator comments for date formats
Don't say 'This is a time format' for both time formats, but
label them as 24-hour and AM/PM.
2010-02-11 14:53:14 -05:00
c89ee2f8f2 [panel] Fix typo in previous clock patch
We shouldn't be displaying hours as 24 in am/pm case
2010-02-11 14:42:12 -05:00
res
c21e692652 [panel] Detect clock AM/PM from locale
Look at whether a localized time string from JS includes am/pm to
determine whether we should show it in the UI.
2010-02-11 14:01:19 -05:00
071efd826c Updated Italian translation 2010-02-10 22:31:39 +01:00
d27f19a561 [MessageTray] Provide more control over Notification layout
This will be used by, eg, the chat notifications

https://bugzilla.gnome.org/show_bug.cgi?id=609453
2010-02-10 16:04:41 -05:00
7642040fc0 [MessageTray] rename some fields
"fooText" suggests it might be a string, but it's actually an St.Label

https://bugzilla.gnome.org/show_bug.cgi?id=609453
2010-02-10 16:02:25 -05:00
67e70df0c9 [dash] Enable DND of search results
Allow dragging search results to a specific workspace to launch them
on that workspace; the drag icon is the icon from the search result.

https://bugzilla.gnome.org/show_bug.cgi?id=609218
2010-02-10 17:11:45 +01:00
fc0acc9e37 Update the look of panel buttons
Change the look of panel buttons to match the running indicators used
in the app well.

https://bugzilla.gnome.org/show_bug.cgi?id=609357
2010-02-10 16:36:22 +01:00
3a7dc32659 Fix up "window-added/removed" callbacks
Currently the window-added and window-removed callbacks in
main.js:_onWorkspaceSwitched access the first parameter as metaWindow object,
but in fact the first one passed is the workspace (metaWorkspace).

Fix it by using the second parameter instead (which is a metaWindow object).

https://bugzilla.gnome.org/show_bug.cgi?id=609521
2010-02-10 15:34:44 +01:00
36e761b7a5 Fix annotation of shell_recorder_set_pipeline()
There are two minor errors here: the documented parameter name does not
match the real one, and there should be an (allow-none) annotation.

https://bugzilla.gnome.org/show_bug.cgi?id=609522
2010-02-10 13:18:24 +01:00
9a1cb9c3db [InfoBar] Make spacing between message and button stylable
https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-10 10:16:45 +01:00
32e2ff7573 [StScrollbar] Allocate steppers according to size requests
The forward/backward steppers are always allocated a square region at the
scroll bar's ends. Change the allocation to be based on the steppers' size
requests instead.

https://bugzilla.gnome.org/show_bug.cgi?id=609401
2010-02-10 10:13:00 +01:00
ea4b1c6c29 Add an initial version of a manpage
https://bugzilla.gnome.org/show_bug.cgi?id=605249
2010-02-09 18:19:41 -05:00
2d574047e4 Don't show chrome when a fullscreen window is open
Currently the check in chrome.js checks if a window is on the
primary screen by checking its coordinates, width and height.

This check misses the case where windows just set
_NET_WM_FULLSCREEN without changing their position and
size (examples are Flash and ooimpress's presentation window).

Fix this by separating the check for fullscreen windows from the
override redirect one, and only check whether the window is
anywhere on the primary screen in the fullscreen case.

https://bugzilla.gnome.org/show_bug.cgi?id=597271
2010-02-09 21:35:45 +01:00
8ded91e975 Limit activation to summary area and notifications
Currently the messagetray opens up everytime the user hits the bottom of the screen.

To avoid this "opening by accident" this patch changes the behaviour so that:
1) It only opens when there is a notification showing or
2) When the user hits the summary area (assuming he wants to interact with it)

Includes fixes from https://bugzilla.gnome.org/show_bug.cgi?id=607244#c17

https://bugzilla.gnome.org/show_bug.cgi?id=607244
2010-02-09 19:31:39 +01:00
0b2eeccd4b Add "InfoBar" and undo capability to overview
It allow to show some information to user and Undo his actions.
https://bugzilla.gnome.org/show_bug.cgi?id=608933
2010-02-09 01:59:26 +03:00
fa5b0efdb4 Updated Norwegian bokmål translation 2010-02-08 22:58:10 +01:00
7555915441 [Overview] Update window titles when they change
Have window title captions in the overview window picker update on
window title changes.

https://bugzilla.gnome.org/show_bug.cgi?id=609206
2010-02-08 21:45:01 +01:00
3e1b1d5789 Make parameters configureable
Make the framerate, file extension and gstreamer pipeline used by the
screencast recorder configureable using gconf.

This patch does not change the defaults, it justs provides a way for
the user to override them.

https://bugzilla.gnome.org/show_bug.cgi?id=608995
2010-02-08 21:31:30 +01:00
8e759d7f32 Initialize global->root_pixmap to the stage color
Fixes drawing of the overview in the case where there is no root pixmap
(eg, --xephyr mode).

(And the workaround for not drawing an unintialized ClutterTexture can
be removed now, since the texture will always have been initialized.)

https://bugzilla.gnome.org/show_bug.cgi?id=609339
2010-02-08 14:47:04 -05:00
caaa543385 Draw a ripple when the hot corner is hit
Animate an expanding ripple from the hot corner using multiple
scaling copies of a PNG of a single ripple. The idea here is to
give the user a clue as to what happened.

Based on initial version implemented live at MIT IAP GNOME Shell
intro session; thanks to all the attendees for coming!

https://bugzilla.gnome.org/show_bug.cgi?id=609135
2010-02-08 14:04:45 -05:00
dce4b2f325 Remove C99 use of non-constant initializers
To comply with C89, structure initializers should have
only constant values.

(Not a thorough check for this throughout the codebase, just
StWidget is fixed up in this commit.)

https://bugzilla.gnome.org/show_bug.cgi?id=608746
2010-02-08 14:04:45 -05:00
fb7ed1ee28 [ShellEmbeddedWindow] Set window type in g_object_new
As of 2a78adc5e3, gobject no longer allows for setting construct-only
properties via g_object_set() during object initialization; set the
properties in a custom constructor instead.

https://bugzilla.gnome.org/show_bug.cgi?id=608802
2010-02-08 18:50:05 +01:00
a74cef9d2f [altTab] Position on the currently focused monitor
Show the popup on the currently focused monitor rather than on the primary.

https://bugzilla.gnome.org/show_bug.cgi?id=609257
2010-02-07 19:28:35 +01:00
c88d21d487 Use GL_MESA_pack_invert if available
Use GL_MESA_pack_invert if available to avoid doing flipping in software.

https://bugzilla.gnome.org/show_bug.cgi?id=609053
2010-02-05 22:25:40 +01:00
6f83b39ee4 Consume windows by the Activities button on minimize
The design document states:
"Animate the action as shrinking into or being consumed by the Activities Item"

This makes it clear what happens to the window (i.e it doesn't vanish but can be brought back by going to the overview).

https://bugzilla.gnome.org/show_bug.cgi?id=609079
2010-02-05 17:01:18 +01:00
f5c4e23c9c Fix drag point for application icons
We need to return the "thing that is being dragged" from
getDragActorSource() so that dnd.js can figure out the right
relationship between the dragged object and cursor.

https://bugzilla.gnome.org/show_bug.cgi?id=607351
2010-02-05 10:57:17 -05:00
f1fb0d32c6 [MessageTray] fix ellipsization when the title is too long
The code previously assumed that an StLabel with a 0-width allocation
would not be visible; this is apparently not true.

Part of https://bugzilla.gnome.org/show_bug.cgi?id=608915
2010-02-03 19:21:48 -05:00
ed129b40a3 [ShellWindowTracker] Add shell_window_tracker_app_from_pid
In some situations we might need to look up an application from
a process identifier, such as the notification system where we
will determine application from the message sender.
2010-02-03 19:07:22 -05:00
fd1ce40ee7 Improve handling of gradients
By calling clutter_actor_get_allocation() in st_widget_recompute_style()
to determine whether to redraw gradients, we triggered a complete
reallocation of the stage for each gradient.

As gradients are processed in st_widget_real_style_changed() anyway, the
additional checks in st_widget_recompute_style() are redundant and can
be removed altogether.

https://bugzilla.gnome.org/show_bug.cgi?id=608847
2010-02-03 23:38:42 +01:00
2b15f38730 Pick up change from gradient to solid background
On style changes from gradient to solid backgrounds, the new background
must be drawn unconditionally, not depending on whether old and new
background color differ.

https://bugzilla.gnome.org/show_bug.cgi?id=608914
2010-02-03 21:16:40 +01:00
86515f3943 show background when nautilus isn't drawing the desktop.
If window with type Meta.WindowType.DESKTOP doesn't exist, then draw
background.
https://bugzilla.gnome.org/show_bug.cgi?id=591912
2010-02-03 22:52:25 +03:00
9afb09128b Fix resizing problems with DashDocDisplay
- Handle non-uniform child heights properly - use a constant
  grid size as the maximum of all child heights; with the
  previous code, the children might not line up in the two
  columns and the last item could be lost if the second column
  was taller than the first column.

- Call set_skip_paint(child, false) on children that we do
  want visible to override any previous hiding of that child.

- Correctly handle the DashDocDisplay not being allocated at 0, 0;
  children should be allocated starting at 0, 0, not at origin
  of the allocation box passed in.

- Remove an unused skipPaint variable.

https://bugzilla.gnome.org/show_bug.cgi?id=608801
2010-02-03 13:51:02 -05:00
e40063fc34 [MessageTray] add support for notification actions
https://bugzilla.gnome.org/show_bug.cgi?id=606979
2010-02-03 13:43:17 -05:00
d20d815b45 [MessageTray] Merge Notification and NotificationBox
This will (eventually) give sources more control over the form of
notifications

https://bugzilla.gnome.org/show_bug.cgi?id=606979
2010-02-03 13:43:17 -05:00
ed36517615 [ShellGenericContainer] Simplify tracking of skip-paint children
The current way we keep track of skip-paint children is more
difficult than it needs to be, and can lead to subtle bugs.
(For one, the skip-paint state of a child is remembered
when it is removed then added back again, which is completely
unexpected.)

Instead of using weak references to track children, just remove
items from the skip-paint list by overriding the remove() virtual
function of the ClutterContainer interface.

The 'skip_paint' hash table is then destroyed in finalize rather than
dispose since it doesn't hold references to memory any more but just
passively tracks an attribute of the children that are currently in
the container.

https://bugzilla.gnome.org/show_bug.cgi?id=608848
2010-02-03 12:00:56 -05:00
fa60165764 [MessageTray] do pop-out on hover for long notifications
https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-02 14:00:17 -05:00
3c9d0fbca6 [MessageTray] fix up allocation, ellipsize long notifications
https://bugzilla.gnome.org/show_bug.cgi?id=606755
2010-02-02 14:00:07 -05:00
8d31c2f4dc change a few stray tabs to spaces 2010-02-02 10:31:38 -05:00
eaa1f9a0f4 [MessageTray] Fix positioning for multi-monitor environments
We can't assume that the primary monitor is at position (0, 0);
there may be another monitor configured at the left or at the top.
2010-02-02 14:02:32 +01:00
3e19f41cba [StWidget] Limit gradient redraws to size changes
When moving a widget with a gradient, its allocation changes
continuously, resulting in constant redraws.
Checking for actual size changes before the operation avoids
unnecessary redraws.

https://bugzilla.gnome.org/show_bug.cgi?id=608715
2010-02-02 00:24:35 +01:00
e6902a1f1c "Fix" prelighting of the scroll bar handle
By default buttons fade from the hover to the normal state, by animating
the opacity of a copy of the previous border-image. This works as
expected for opaque and fully transparent pixels, but results in a
flickering effect for others.
Making StButton's fade effect work with partly transparent pixels is
hard, not using images with transparency is easy ...

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 22:50:25 +01:00
b1007ed811 Add shell_global_gc
Primarily useful for debugging.  This was originally a patch against
gjs: https://bugzilla.gnome.org/show_bug.cgi?id=595323

But rather than add a random toplevel module just for this function
effectively, we can easily enough define it here.  Adding toplevel
modules to GScript should have a bit more formal process to it.

https://bugzilla.gnome.org/show_bug.cgi?id=608095
2010-02-01 16:08:43 -05:00
54d385a0a9 [AppSwitcher] tweak the sizing code, which depended on the previous bug 2010-02-01 12:31:26 -05:00
df48e9d1c0 Fix misuse of ShellGenericContainerAllocation in two places 2010-02-01 11:54:47 -05:00
e3be74a31a Fix invalid unreference of CoglTexture
cogl_texture_get_data doesn't increase the refcount, so don't try
to decrement it.

Signed-off-by: Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=608512
2010-02-01 10:15:15 -05:00
a8aa0c085f CSS tweaks to match mockups better
- add some spacing between buttons
- move controls closer to the workspaces view (we'll need that space
  for the message tray)
- fix the look of the scrollbar background
- adjust sizes of theme images
- some general CSS cleanup

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
cd78f1158c Reduce the gap between workspaces in linear view
https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
d9668bd425 Make inactive workspace buttons insensitive
Update sensitivity instead of hiding buttons - hiding the
add workspace button looks especially weird.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
dc3ff10c6f Fix slightly misplaced overlays in single view
Correct the positioning of window captions and close buttons for
non-active workspaces in single view.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
31f9da7b8f Fix transition to zoomed window in single view
Fix messed up transition from overview when activating a zoomed in
window.

https://bugzilla.gnome.org/show_bug.cgi?id=607872
2010-02-01 10:13:19 -05:00
05e3a747d0 Remove images of old workspace buttons 2010-01-30 00:01:35 +01:00
8db212db99 ShellRecorder: Fix interaction of glReadPixels with Cogl
The screen recording wasn't working because of two bad interactions
with Cogl:

 - Buffered primitives weren't being flushed out
 - Cogl changes the pixel store values away from their default values

Thanks for Jon Nettleton for tracking down the source of the
problems with the recorder.

https://bugzilla.gnome.org/show_bug.cgi?id=598390
2010-01-28 13:54:58 -05:00
2494cc1637 Show summary mode briefly after notification
This helps illustrate that expired notifications move to the summary view.

Animate the separate components of the message tray individually
as in http://www.gnome.org/~mccann/shell/mockups/20090630-demo

Based on the patch from Florian Müllner.
2010-01-28 13:39:00 -05:00
ee75355e71 Replace direct call to MessageTray::showNotification() with 'notify' signal in Source::notify()
This decouples Source and MessageTray, so Source doesn't need to know how
MessageTray works.
2010-01-28 13:20:17 -05:00
863f9f285b Updated Bulgarian translation 2010-01-28 05:04:53 +02:00
d7e0051bc6 [StButton] Hold ref to self until animation completes
StButton has an internal animation for the border-image actor, then
it connects to the "completed" signal passing itself as data.  However,
if the button is destroyed, nothing prevents the animation's completed
signal from then causing a reference to freed memory.

Holding a reference to the button is the most straightforward fix here.

https://bugzilla.gnome.org/show_bug.cgi?id=607825
2010-01-26 14:28:57 -05:00
2aa305b51d [StShadowTexture] Fix invalid unref of CoglHandle
This code appeared to treat the return value of clutter_texture_get_cogl_texture
as having a new reference, but in fact it doesn't.

https://bugzilla.gnome.org/show_bug.cgi?id=608119
2010-01-26 13:03:43 -05:00
4006d7d57f Adjust message-tray on resolution changes
https://bugzilla.gnome.org/show_bug.cgi?id=608058
2010-01-25 21:26:47 +01:00
0a566f70b6 [AppIcon] Leave overview when launching apps
There was an unintentional regression at some point where we ceased
leaving the overview when launching applications.  Fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=608062
2010-01-25 14:16:05 -05:00
be2801d1fa Nicer animation of hidden windows when transitioning to/from the overview
Hidden windows used to appear/disappear abruptly in the beginning/end of the transition and the new animation is a lot smoother.

https://bugzilla.gnome.org/show_bug.cgi?id=571109
2010-01-23 11:26:30 -05:00
648126e598 Move 'workspace_relative' definition to workspace.js
'workspace_relative' is used in workspace.js, not in workspacesView.js

Change a couple strings to have single quotes instead of double quotes to indicate that
they don't need to be translated.
2010-01-22 20:04:18 -05:00
8184b2c57b [Overview] Correct scroll directions on indicators
When using the scroll wheel on the workspace indicators in single view,
make them use the same interpretation as the scrollbars: scrolling up
moves to the previous workspace, scrolling down to the next one.

https://bugzilla.gnome.org/show_bug.cgi?id=607824
2010-01-23 01:15:45 +01:00
337eab614e [WorkspaceView] Allow workspace switching using mousewheel + indicators
Allow the user to switch between workspaces by scrolling on the indicators.
Up = next workspace
Down = previous workspace
2010-01-22 20:49:52 +01:00
20abc4cb99 New workspaces view
Matching the 20091114 mockup, the default workspace view
is now a scrollable horizontal list, with a control to
switch between this and the previous grid view.

https://bugzilla.gnome.org/show_bug.cgi?id=593844
2010-01-22 13:47:52 -05:00
5aca0b7704 Updated Hungarian translation 2010-01-22 00:57:46 +01:00
74446ce3e0 [Places] Hide desktop icon when desktop_is_home_dir
With the above preference set to true, the home and desktop entries
both represent the same location. Hide the desktop icon in that case
to avoid redundancy.

https://bugzilla.gnome.org/show_bug.cgi?id=606922
2010-01-20 23:36:14 +01:00
7bb14bd8da calendar.js: switch buttons direction in RTL mode
also don't hang if translation of 'calendar:week_start:0' is incorrect

https://bugzilla.gnome.org/show_bug.cgi?id=584662
2010-01-20 17:24:22 -05:00
ed75f0da63 [dnd] revert the change to only allow dropping on reactive actors
Workspace.actor is non-reactive, and there's probably some good reason
for this. So just have the add workspace button check its own reactivity.
2010-01-20 14:01:37 -05:00
d9008054cf Handle resolution changes
Added signal 'screen-size-changed' to ShellGlobal.
Connect to this signal in main.js and run the _relayout() method.
If Overview or calendar are visible when this signal emit, they will be hiding.
https://bugzilla.gnome.org/show_bug.cgi?id=584526
2010-01-19 21:32:36 +03:00
b10d9c9ad7 Added Norwegian to the list 2010-01-19 17:43:35 +01:00
5f855045a2 Added Serbian translation 2010-01-19 00:18:38 +00:00
88737b2083 [dnd] Don't allow dropping on non-reactive actors 2010-01-18 14:58:31 -05:00
a50d64e8e9 [overview] disable the AddWorkspaceButton if there are >= 16 workspaces
https://bugzilla.gnome.org/show_bug.cgi?id=606460
2010-01-18 14:58:26 -05:00
4deef2a9ef [Overview] Allow selecting windows in lightbox mode
Make the event blocking done by Lightbox optional - leave it activated
when displaying the run dialog, but deactivate it when highlighting
windows in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=602774
2010-01-18 13:53:31 +01:00
dd9a29633a Updated Arabic translation 2010-01-17 11:30:43 +02:00
4407f0bd65 Updated Simplified Chinese translation. 2010-01-17 15:30:54 +08:00
73fd896f3c [tests/borders.js]
Shrink stage size to 640x480 to fit on netbook screen.

Make the area scrollable.

Add a few more tests.
2010-01-15 18:33:36 -05:00
f8acd0f6f6 Match on executable names as well
Include matches on desktop entries' exec property in addition to the
name and comment ones.

https://bugzilla.gnome.org/show_bug.cgi?id=606743
2010-01-15 23:03:18 +01:00
ccc6a23f68 Fix missing translations for 'time ago' strings
Replace ngettext with dngettext and set the correct translation
domain, so gnome-shell's domain is searched for translations
rather than mutter's.

https://bugzilla.gnome.org/show_bug.cgi?id=597882
2010-01-15 17:14:03 +01:00
c236c501e7 Updated German translation 2010-01-15 16:56:41 +01:00
2a0e0ae66f Fix crash in runDialog
The run dialog crashes when PATH contains non-existing directories (some
distros seem to do that ...).
Fix by filtering those out before setting up file monitors.

https://bugzilla.gnome.org/show_bug.cgi?id=606418
2010-01-14 13:16:55 -05:00
11276a3505 Initial implementation of the message tray and notification daemon
From the message-tray branch. Most of the UI parts were written by
Marina, and most of the D-Bus parts by me.
2010-01-13 15:13:20 -05:00
c90371d9d5 [ShellTextureCache] add methods for caching raw image data
shell_texture_cache_load_from_data() takes the contents of an image
file, while shell_texture_cache_load_from_raw() takes the actual pixel
data.
2010-01-13 15:13:20 -05:00
038a32330f [St] Add st_box_layout_move_child and st_box_layout_insert_actor 2010-01-13 15:13:20 -05:00
fa1fe4fdd1 Updated Czech translation 2010-01-12 21:58:45 +01:00
59d6029f47 Implement radial gradients for StWidget
Some theme authors have stated interest in radial gradient backgrounds.
The w3c has some draft:

http://dev.w3.org/csswg/css3-images/#radial-gradients

As this is rather complex, we add only some very basic support, which
extends our syntax for linear gradients:

background-gradient-direction: [vertical|horizontal|radial]

Gradients are centered circles, whose size is determined by the closest
side.

https://bugzilla.gnome.org/show_bug.cgi?id=604945
2010-01-11 23:38:34 +01:00
33b3d05039 Update running app indicator to match latest mockup
https://bugzilla.gnome.org/show_bug.cgi?id=606257
2010-01-11 23:38:34 +01:00
7486c09fbb Change handling of gradients
Some changes to the way we handle CSS gradients:

 * draw without padding, thus interpreting gradients as part of the
   background rather than as content

 * clip to (rounded) border area

 * draw the border along the gradient instead of trying to align the
   gradient layer with the background/border layer

 * use the border_image actor instead of the background_image one

https://bugzilla.gnome.org/show_bug.cgi?id=606257
2010-01-11 23:38:34 +01:00
3f750a5637 Updated Slovenian translation 2010-01-11 15:29:12 +01:00
e54fe59723 Updated Spanish translation 2010-01-09 09:16:56 +01:00
38b20ca0a4 autohide sidebar in compact mode (v3)
https://bugzilla.gnome.org/show_bug.cgi?id=604118
2010-01-08 16:32:51 -05:00
8c178378ae [appIcon] Delete; this file is obsolete
Was moved into appDisplay.js.
2010-01-08 15:58:44 -05:00
341b9a80c5 Do not reset window zoom when leaving the overview
https://bugzilla.gnome.org/show_bug.cgi?id=598319
2010-01-08 18:43:34 +01:00
45e89bf34a [main] Print a starting message to stdout
This helps developers delineate error streams between "Alt-f2 r",
among other things.
2010-01-08 11:39:02 -05:00
c17e1249d5 [panel] Scale up, center and fade application icon in app menu
Per 20091114 design.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:01 -05:00
262f92e0be [ShellSlicer] New class to display center of child
A #StBin that has 0 minimum size, and will clip its child
in the middle.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
da797dff35 [Makefile-st.am] Generate st/st.h
All of the st-$foo.h files say to include st.h, but we didn't have
one.  Therefore, generate it.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
7043215f5e Misc. style changes
Matching 20091114 mockup.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
5202dd5157 [dash] Change section titles to match 20091114 mockup
Documents is changed to Items, and add "& Devices" to Places.

https://bugzilla.gnome.org/show_bug.cgi?id=605491
2010-01-07 18:33:00 -05:00
7c4765d053 Updated Slovenian translation 2010-01-07 18:51:30 +01:00
69c8aef6c2 Show "No matching results" if that's the case
This also fixes backtracking from no matching results.

https://bugzilla.gnome.org/show_bug.cgi?id=606209
2010-01-06 16:20:01 -05:00
71786e50cf [build setup] Add -L to curl invocations
To follow redirects, otherwise we might be downloading 301 HTML pages
instead of the data we want.
2010-01-06 13:56:47 -05:00
e5647c4f83 [build setup] Add gcc-c++ on Fedora 2010-01-06 13:54:12 -05:00
98a8dd682d [ShellAppUsage] Fix use-after-free
We were holding on to UsageData structure pointers in previously_running,
but those can be purged by the unused app cleanup.  Instead just hold
onto dup'd copies of the application id strings.
2010-01-06 13:34:11 -05:00
af3b965e00 [Overview] Add drop shadows to close buttons
https://bugzilla.gnome.org/show_bug.cgi?id=603691
2010-01-05 21:48:10 +01:00
2dfe113a42 Implement -st-shadow for StWidget
Add support for a new -st-shadow property, which is based loosely
on the CSS3 box-shadow property:
http://www.css3.info/preview/box-shadow/

It defers from the specification as follows:

 * no multiple shadows
 * the optional color argument may be placed anywhere
 * the shape is not determined by the widget's bounding box,
   but by the background-image property

https://bugzilla.gnome.org/show_bug.cgi?id=603691
2010-01-05 21:48:09 +01:00
a2cae50e0e Updated Slovenian translation 2010-01-05 16:56:33 +01:00
9423cc7fae Fix application thumbnail sizing when the height is greater than the width of a window.
This bug happened because the thumbnail box was only maxed, not set to 256x256.
Standard window thumbnails would max out only the width to 256. Having a window with
its height greater than its width meant that the height would max out, but not the
width, causing thumbnails to look uneven.

https://bugzilla.gnome.org/show_bug.cgi?id=604963
2010-01-04 20:21:28 -05:00
767fe0ebc2 [St] Don't leak the font family name
A copy of the string is made by pango_font_description_set_family()
and we don't need the string anymore, so we should free it

https://bugzilla.gnome.org/show_bug.cgi?id=605035
2010-01-04 13:49:47 -05:00
edce0e8feb Updated Italian translation 2009-12-28 21:59:19 +01:00
554549338a Updated Galician Translation 2009-12-28 17:07:26 +01:00
350e958383 position sidebar centerd on the left side of the primary monitor
https://bugzilla.gnome.org/show_bug.cgi?id=604177
2009-12-21 12:12:44 -05:00
0e5c83bd2a Fix URLs pointing to git.gnome.org/cgit
git.gnome.org/cgit was relocated to git.gnome.org/browse; adjust
URLs in our build script to match.
2009-12-20 11:36:10 -05:00
6e1a791273 Allow clicking on any part of section header to browse
This is more intuitive, though we need to make the whole thing feel more like a button.

https://bugzilla.gnome.org/show_bug.cgi?id=596985
2009-12-20 01:06:24 +01:00
2435c603ec Updated Spanish translation 2009-12-19 14:55:33 +01:00
44cc42484f [appDisplay] Switch to using global.get_current_time()
Main.currentTime() moved into ShellGlobal.
2009-12-18 17:35:48 -05:00
44712c274e Change event handling so Escape always works
Until now LookingGlass could only be closed using the Escape
key when the Evaluator class was active, as the relevant code
was associated to the text input field; this moves it into a
global event handler instead which works everywhere in LG.
2009-12-18 21:53:25 +01:00
1c4c3afb27 Add eject buttons in places menu for places which support it
https://bugzilla.gnome.org/show_bug.cgi?id=602976
2009-12-18 15:12:53 -05:00
e326202477 Use the preferred text editor when opening an extension's .js file
Change "./src/gnome-shell --create-extension" to use "gnome-open"
when opening the newly created .js file, so that it is launched
with the user's preferred text editor, instead of hardcoding gedit.
2009-12-18 20:26:41 +01:00
45f4292259 Make "gnome-shell --create-extension" compatible with Python 2.5
Fallback to using the json-py module on systems with a Python
version older than 2.6 (which introduced native JSON support).
2009-12-18 20:22:51 +01:00
288eae91e2 [ShellAppSystem] Initialize collation keys for info on-demand
In case of duplicate infos structures with the same id, the
info structures we get from looking up the id in app_id_to_info
aren't necessarily the same as those we used to match, so we
can't rely on matching to implicitly initialize info->casefolded_name.

Since the name collation key isn't used in matching results,
just in sorting, init it on-demand in the sorting which is also more
efficient.
2009-12-18 12:36:16 -05:00
f4c05deb2d Completion in alt+F2
Bind <Tab> for command's completion and path's completion.
https://bugzilla.gnome.org/show_bug.cgi?id=597677
2009-12-18 11:31:17 -05:00
1cd9a15ac0 [js/ui/Makefile.am] Install extensionSystem.js 2009-12-18 11:28:39 -05:00
d1edefdc39 Reposition items at start of fade in
We need to set the positions after the animation ends (and
fadeIn starts), not before when allocation is changed.

As the window may still be in motion when the overlay is
repositioned, it is safer to pass the calculated values
as parameters.

https://bugzilla.gnome.org/show_bug.cgi?id=602598
2009-12-18 11:27:21 -05:00
2cb4dfb4a4 [lookingGlass] Add primitive extensions list
In the future this should be more like the Firefox Addons UI
probably with enable/disable/update checking, but stub it out
here for now.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
c0ff0066e6 Make link.js into a St.Button, delete unused link imports
It's actually totally unused at the moment, but a future patch will use it.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
55fbb9d0af [St] Implement text-decoration: [underline|strikethrough]
Move CSS handling of StLabel and StButton for their underlying
ClutterText objects into st_private, and implement support for
the underline and strikethrough St text-decoration properties.

Overline isn't implemented for lack of a corresponding Pango
attribute, and blink, well...

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
c4a49b4de2 Port more to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:20:05 -05:00
aa9d3515a1 Add extensionSystem
Consumer documentation will live at http://live.gnome.org/GnomeShell/Extensions

In terms of implementation; basically we load extensions from the well-known
directories.  Add a GConf key to disable extensions by uuid.  There is a new
option --create-extension for the gnome-shell script which takes a bit of
interactive input, sets up some sample files, and launches gedit.

No extensions UI in this patch; that will come later.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-18 11:19:59 -05:00
4394bc3e40 [dash] Avoid infinite recursion in keynav 2009-12-18 10:39:02 -05:00
6b1c3d323b [js/ui/Makefile.am] Install search.js 2009-12-18 10:25:06 -05:00
b7646d18ae Add search.js, rebase search system on top
The high level goal is to separate the concern of searching for
things with display of those things; for example in newer mockups,
applications are displayed exactly the same as they look in the
AppWell.

Another goal was optimizing for speed; for example,
application search was pushed mostly down into C, and we avoid
lowercasing and normalizing every item over and over.

https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:07:22 -05:00
f5f92b2e79 [appDisplay] Unify Inactive/RunningWellItem, split into AppIcon, AppWellIcon
The distinction between the inactive and running was silly; just
have one class which can handle both running states.  However for
a future search patch, we do want a separation between an icon which
just has icon + name + glow, and a well icon which does the menu
integration.

https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:02:19 -05:00
14df7cd62c [StOverflowBox] Vertical box which skips painting underallocated children
https://bugzilla.gnome.org/show_bug.cgi?id=603523
2009-12-18 10:01:36 -05:00
c2fe9e57b1 Added Hebrew translation 2009-12-18 00:36:50 +02:00
5a3c3efbeb [ShellDocSystem] Check GTK+ version for constness of argument 2009-12-15 16:29:21 -05:00
a8d18ac18a Limit dash docs to 50
We has poor performance if we try to allocate hundreds of actors;
a bit more ideally, we'd keep pulling as much as we can, but really
no one should have more than 50 in the list as is now except on
unreasonably large screen sizes.

In the future we should change this to be pull-on-demand thing
in a chunked fashion.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 16:08:15 -05:00
949f67469c Rebase recent documents on top of ShellDocSystem
Rather of calling .exists() synchronously for all documents, use
ShellDocSystem's async API to only stat docs we're showing.

Use the doc opening functionality in ShellDocSystem.

Also, more intelligently do redisplay(); don't recreate actors
for recent docs if we already have one for that URI.  We may
need more intelligent caching here; if e.g. just the associated
application changes, we should probably reread the info.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 16:08:12 -05:00
a442dfea14 Add class for handling recent docs
Push some of the JS docInfo down into C; crucially, this lets us
use the GIO async API.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:54:42 -05:00
42757a0c87 Move Main.currentTime() and Main.createAppLaunchContext() into ShellGlobal
Primarily motivated by wanting these functions accessible from C.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:54:38 -05:00
81b7c0170d Add set_skip_paint method
Ideally we'd be able to override _paint, but given that we can't
at the moment, this method gives a way to implement containers
which don't happen to paint all of their children.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:53:08 -05:00
d624db18c5 Add deferred work system
Previously we had various things watching for notify::mapped so
we could be more lazy about updating non-visible actors, but it
was fairly ad-hoc.

The deferred work system unifies these callbacks, and also adds
a timeout so that we don't delay changes arbitrarily; this way we
avoid a storm of work if you stay out of the overview for a while,
then go in.

https://bugzilla.gnome.org/show_bug.cgi?id=603522
2009-12-15 15:53:05 -05:00
b03fa1ebf7 Add missing "fi" to po/LINGUAS 2009-12-11 18:52:17 +01:00
478dba8502 Remove non-existing src/shell-status-menu.c from POTFILES.in 2009-12-11 18:50:44 +01:00
20294f2c92 Updated French translation
Contributed by Pablo Martin-Gomez
2009-12-05 16:44:19 +01:00
34003a1f6b Updated Swedish translation 2009-12-01 23:54:05 +01:00
a4405be71c Add global.log, global.logError functions
These log to a display in lookingGlass; rough equivalent of
the Firebug "console.log".

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-01 15:15:12 -05:00
b6cc9c7ff6 Add functions to dynamically load/unload stylesheets
For implementing extensions, we want the ability to add a stylesheet
dynamically, and unload it as well.

https://bugzilla.gnome.org/show_bug.cgi?id=599661
2009-12-01 15:00:56 -05:00
368d484dee Avoid variable redeclaration
https://bugzilla.gnome.org/show_bug.cgi?id=603327
2009-12-01 14:54:25 -05:00
7b0526dc5c [chrome] only hide chrome if fullscreen window is on the same monitor
https://bugzilla.gnome.org/show_bug.cgi?id=599926
2009-12-01 12:26:41 -05:00
236a9b184f Updated Brazilian Portuguese translation 2009-11-25 17:25:50 -02:00
6b816fa7dc Replace includes of glib/gi18n.h with glib/gi18n-lib.h
https://bugzilla.gnome.org/show_bug.cgi?id=602802
2009-11-24 15:26:09 -05:00
e2ac769fd1 Bump save timeout to 5 minutes, close output asynchronously
The synchronous close causes us to block in fsync() which has extremely
poor interactivity implications on ext3.

Also, the 5 second timeout was an accidental commit from debugging, 5
minutes is fine.

https://bugzilla.gnome.org/show_bug.cgi?id=602456
2009-11-24 13:22:32 -05:00
dd8f05c81d include "config.h" in all .c files
Also, fix shell-global.c to actually compile with config.h included.

Was supposed to fix bug 602802, but doesn't...
2009-11-24 09:15:35 -05:00
f0e3b87330 Fix disappearing close button
Show the close button after zooming a window in the overview when the
window clone has the pointer focus.

https://bugzilla.gnome.org/show_bug.cgi?id=602772
2009-11-23 19:37:56 -05:00
1d2dc09ede [panel] Port to CSS
With some tweaks from JP St. Pierre to center things in case we ever
have a larger panel.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
73cd9513bd Remove information icon
It wasn't really useful, not obviously in the current mockups, and
depended on button.js.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
907fc2f067 Port AppWell to CSS; delete appIcon.js
The altTab.js and app well code weren't sharing really
any functionality anymore; un-merge the appIcon code back
into appWell, and have a simple icon + text display for
altTab.

Port AppWell to St and CSS.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
2f1ca7bf28 Remove ShellButtonBox, button.js; Use St.Clickable in panel.js
StClickable replaces ShellButtonBox.  Reduce the number of
button-like things by deleting button.js.

To do so, add CSS style for the actitivies button.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:49 -05:00
93f3412f70 Import ShellButtonBox as StClickable
Now a StBin, and add hover/active style properties.  Also, add the
event to the CLICKED signal.  Otherwise a straightforward namespace
transformation.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:48 -05:00
f815844eb4 Move ShellDrawingArea to StDrawingArea
It's nicer to have ShellDrawingArea as a St widget so it can
participate more cleanly in CSS styling, such as queuing a redraw
automatically on style changes, and allowing subclasses to use
CSS styling.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-23 14:33:48 -05:00
b0cb8fb85a [Chrome] clean up APIs and remove workarounds
https://bugzilla.gnome.org/show_bug.cgi?id=597044
2009-11-23 13:49:18 -05:00
e9787c0f1e Add params.js, for function param object parsing. 2009-11-23 13:48:59 -05:00
efc291ac5b Switch to confirm dialog when closing
Some applications show a confirm dialog before closing, which the close
button happily ignores.

Detect newly created windows which are transient for the window we try to
close and switch to them.

https://bugzilla.gnome.org/show_bug.cgi?id=602532
2009-11-21 18:18:15 -05:00
1cc78fdf60 Clear text when closing run dialogue
Signed-off-by: Colin Walters <walters@verbum.org>
2009-11-21 15:50:57 -05:00
8c59bc71b0 [dash] Switch to using StWidget gradients
https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-20 19:51:46 -05:00
7b9f5b7643 Implement gradients for StWidget
Rather than having gradients be individually implemented by higher
level JS widgets, move basic gradient functionality into StWidget.
There is prior art in WebKit for CSS gradients:

http://webkit.org/blog/175/introducing-css-gradients/

However, implementing this would be quite a lot of work; all we
need in the Shell design at the moment is basic horizontal/vertical
linear gradients.  So, the syntax now supported is:

background-gradient-type: [vertical|horizontal]
background-gradient-start: color;
background-gradient-end: color;

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-20 19:51:41 -05:00
0bc578230f [workspaces] Add an idle timeout for close button
Add a grace period for the close button so if you happen to move your
mouse outside the target it doesn't vanish and force a Z motion.
2009-11-19 19:39:00 -05:00
bb366f8fbe Window selector refinements
* Remove window icons
 * Add a close button to window previews
 * Position caption underneath the window
 * Port caption from Big.Box to St.Label

https://bugzilla.gnome.org/show_bug.cgi?id=598324
2009-11-19 18:40:44 -05:00
8ac97fe1a0 [StThemeNode] Re-add erroneously deleted (out) annotations
An earlier commit was overzealous in removing (out) annotations;
introspection supports (out) for integral types just fine, we
only need to remove them for (out) types where the caller needs
to allocate a boxed type.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
2009-11-17 18:43:34 -05:00
2c914374e0 Integer align workspace and pane positioning
We had previously been leaving the scaled workspace at a non-integral
position which didn't look obviously ugly, but now that we're
constraining the popup pane to the workspace size, we really need
to ensure that we're using integral positions here.

https://bugzilla.gnome.org/show_bug.cgi?id=601854
2009-11-16 14:13:14 -05:00
1526500079 [placeDisplay] Fix inverted logic for desktop-is-home case
We only want to hide the Desktop link if it desktopIsHome, not
if it isn't.
2009-11-16 14:13:14 -05:00
9ba5ca0193 environment.js: set default direction for St widgets
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:35 -05:00
3529b8c915 [StTable] now RTL aware
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:29 -05:00
4e8206d60e [StBoxLayout] now RTL aware
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:22 -05:00
a5edc78fac [StWidget] add API support for right-to-left UI
https://bugzilla.gnome.org/show_bug.cgi?id=584662
2009-11-16 11:46:09 -05:00
cdd508e12d Darken workspace indicator when doing lightbox effect
Adjust the opacity of the workspace indicator to not having it stand out too badly when in lightbox mode.

https://bugzilla.gnome.org/show_bug.cgi?id=594556
2009-11-16 11:22:46 -05:00
931cbc6ae3 Fix sidebar enable/disable menu item
https://bugzilla.gnome.org/show_bug.cgi?id=601875
2009-11-14 10:31:41 -05:00
ab809faaf0 Updated Slovenian translation 2009-11-14 11:18:02 +01:00
8334b063f1 Deal with title-less windows
https://bugzilla.gnome.org/show_bug.cgi?id=601290
2009-11-13 16:04:17 -05:00
21f15246a6 [genericDisplay] Fix selection not being set correctly
We need to check if the display actor is an instance of Shell.OverflowList
or St.BoxLayout to use the appropriate function for getting its child
with a given index.
2009-11-13 14:49:45 -05:00
050e710770 Use gnome-terminal rather than xterm+xeyes+xlogo in --xephyr mode
https://bugzilla.gnome.org/show_bug.cgi?id=588056
2009-11-13 14:43:10 -05:00
bb63d513fd Add Presence items to the status menu
https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:21:36 -05:00
985d707788 Port ShellStatusMenu to javascript
https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:21:31 -05:00
9ddebf0480 Introspect src/gdmuser
In addition to the Makefile changes, we also change uid_t to gulong in
the public API (which matches how it was already represented in the
gobject properties).

https://bugzilla.gnome.org/show_bug.cgi?id=601458
2009-11-13 14:20:45 -05:00
8c05003acf Add gnome-shell --eval-file
Convenience utility function for evaluating an arbitrary
JavaScript file.
2009-11-13 12:45:46 -05:00
7c796b2d2a [shellDBus] Avoid sending undefined over DBus
DBus doesn't have a notion of null/undefined, so do the lame
thing and return the empty string.
2009-11-13 12:45:46 -05:00
48f8e4943d Rename places.js to placeDisplay.js
places.js was renamed in the code
2009-11-12 16:33:03 -05:00
fec2ea5e9c [dash] Convert pane close to St.Button, avoiding release event propagation
The workspaces was handling the release event after closing the pane,
catch it before closing by using St.Button.
2009-11-12 13:09:20 -05:00
4014313910 [dash] Swap More for triangle
In newer mockup.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
06cf6c51f3 [placeDisplay] Port more to CSS, lower spacing
Newer mockups have smaller spacing here.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
426d7bc515 [dash] Port search section headers to CSS
Experimented with moving the (see all) into a tooltip, but
given that we're not emphasizing the drilldown, removed for now.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:02 -05:00
bf68f9f0cf [dash] Port section container to CSS, lower spacing
Newer mockup has smaller spacing.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
ce90dda76f [overview] Constrain popup panes, dim workspaces when active
Rather than the popup panes taking up the whole non-panel height,
constrain them to the height of the workspaces, which is also the
"dash content area".

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
66cab3b8ed [genericDisplay+other] Port to CSS, style cleanups
Mostly a straightforward porting of style code to CSS, except
that various bits of other code referenced a few GenericDisplay
constants, so those needed to be ported as well.

Add some padding at the top between the close button and the items.

Center the text and description.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
bc255a525f [overview] Port pane to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:01 -05:00
d51384fb86 switch to scrolling GenericDisplay, remove menus from apps
Temporarily removed search-by-menu from apps as well, will readd
later as a ShellApp feature.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
1626e8c09a [StTooltip CSS] Add some style
Not final, but stands out and doesn't look completely wrong, at least.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
263d738ef6 [StTooltip] Fix _get_preferred_width
It was ignoring the label width.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
8040ad61c6 [StBoxLayout] Add missing _queue_relayout in _add_actor
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
057f0effed [StBoxLayout] Add st_box_layout_get_n_children
https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
bf7b166237 [StBoxLayout] Add st_box_layout_remove_all, st_box_layout_destroy_children
In a variety of places we're using boxes as data-modeling displays,
and in doing so we often want to either remove the children or
explictly destroy them.

Now ideally Gjs would support callbacks, and this would make using
the for_each functions possible, but even then these functions
are more efficient and shorter to type, at least.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-12 11:42:00 -05:00
ae744bf206 Don't require applications to accept URIs for recent files
This should not be required, since glib correctly deals with such
applications by giving them the local gvfs path, and those
applications which do support URIs keep being able to use the URIs in
GFiles.

Based on original work by Guido Günther <agx@sigxcpu.org>.

https://bugzilla.gnome.org/show_bug.cgi?id=601287
2009-11-12 14:25:42 -02:00
af35dea019 [dash] Move BackLink to CSS
The previous commit 626f679947 broke the back links on
search drilldown.

https://bugzilla.gnome.org/show_bug.cgi?id=601413
2009-11-12 11:21:20 -05:00
1b75ae0184 [lookingGlass] Paint border around current result if instanceof Clutter.Actor
It's very convenient to drill down through object properties and
be able to see exactly which portion of the screen those actors
correspond to, without trying to guess with the inspector tool.
2009-11-11 16:36:42 -05:00
07a8d5ed2d When setting a search, do a redisplay immediately
Commit 94bd6f1718 introduced a trick
where we only do the heavy lifting for "redisplay" when we're mapped.

However, the search system wants to get the count of matched items,
and control the visibility of the display based on that.  This introduces
a circularity; avoid it by forcing the search to do a redisplay.

In the future we should avoid this by separating out the "get matched
things for search" from "display list of things".

https://bugzilla.gnome.org/show_bug.cgi?id=600890
2009-11-10 10:19:00 -05:00
2f27f61a1f Remove trailing whitespaces in dash.js
Trailing whitespaces cause warnings.
2009-11-09 17:49:01 -05:00
585bfe5b5a Make places results available in search
Places is one of the dash sections and it should be included in search results.

Factor out the code for getting and updating the information about places from
Places to PlacesManager.

Introduce PlaceInfo class that contains information about the place and can be
used by classes that display it in different ways. Rename classes so that their
names are consistent with corresponding classes in appDisplay.js and
docDisplay.js

https://bugzilla.gnome.org/show_bug.cgi?id=599125
2009-11-09 16:57:49 -05:00
5ee72d807d Updated Arabic translation 2009-11-08 20:56:26 +02:00
fcac7ac0b3 [gnome-shell.css] Remove blue background from scrollbars
This makes it slightly less ugly.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-05 15:39:26 -05:00
dcd7762253 [StThemeNode] Don't give negative width/height for content boxes
If the space we're allocated is too small for our border + padding
constraints, don't give negative allocations to callers.  Squash
to zero.

It isn't really useful for callers to get negative content sizes,
and certainly breaks most allocation code.

https://bugzilla.gnome.org/show_bug.cgi?id=600734
2009-11-05 15:28:56 -05:00
869e744670 Updated Czech translation 2009-11-05 18:04:36 +01:00
626f679947 Port Dash section headers to CSS
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:45 -05:00
4f456b9689 Implement non-uniform borders (when not using corner_radius)
StTheme CSS supports different border widths for different sides.  Implement
it for StWidget by drawing the border internally.  However, we don't support
a nonzero corner-radius with nonuniform borders.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
e2e513ff08 Remove (out) "caller-allocates" annotations
GObject Introspection+gjs doesn't presently support (out) for caller-allocates
scenarios.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
37a948e4eb Add missing allow-none for set_style_pseudo_class
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
b8d9319c32 Add missing allow-none for st_bin_set_child
https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:17 -05:00
f549269934 [StBoxLayout] Implement raise and lower
Code copied from ClutterGroup.

https://bugzilla.gnome.org/show_bug.cgi?id=599442
2009-11-04 16:47:11 -05:00
dc232d4631 [AppSwitcher] Add a separator between windows in current and other workspaces.
This make it is easier for the user to figure out on which workspace the
windows are. For instance, terminals related to various activities and put on
different workspaces were previously displayed as an uniform list, with no
visible distinction between the ones from the current workspace and the others.
Now they are physically separated by a thin gray line.

This is also consistent with the way applications are displayed in the
AppSwitcher.

https://bugzilla.gnome.org/show_bug.cgi?id=597944
2009-11-04 19:25:37 +01:00
930a0b52f3 Added Finnish translation. 2009-11-04 11:17:20 +02:00
f14d7f891b Updated Italian translation 2009-11-03 22:29:36 +01:00
01138d55ca Added Romanian translation 2009-10-28 22:39:57 +02:00
2103a4da24 Add shell-global-private.h to Makefile.am
Distribute shell-global-private.h (as a non_gir_sources, since it
includes gjs.h and isn't scannable by gobject-introspection.)
2009-10-28 15:46:46 -04:00
627f86a9dc shell-global-private.h fixes:
- Include private header so shell-global.c compiles
- Move _shell_global_set_plugin to private header
2009-10-28 12:59:01 -04:00
baf823c466 Store GjsContext pointer in ShellGlobal
Future functionality in ShellGlobal needs access to the GjsContext.

https://bugzilla.gnome.org/show_bug.cgi?id=599561
2009-10-28 12:31:58 -04:00
94bd6f1718 Only do redisplay when mapped
If we're not mapped, only queue up a redisplay.  This avoids
e.g. changes in recent documents such as saving a file in GEdit
causing a lot of blocking I/O in the shell (we need to make
recent loading async as well).

https://bugzilla.gnome.org/show_bug.cgi?id=599560
2009-10-28 12:20:02 -04:00
c8b1afbad6 Updated Spanish translation 2009-10-27 23:58:48 +01:00
395f45c570 Updated Spanish translation 2009-10-27 21:37:46 +01:00
3ebb0f149d Removing all favorites makes it impossible to add new ones
Show the placeholder when all favorites are gone.
https://bugzilla.gnome.org/show_bug.cgi?id=591854
2009-10-27 11:32:30 -04:00
6d9aadfa4d Add emacs modelines to all .c and .h files that were missing them 2009-10-27 11:27:45 -04:00
22e26bea8f Updated Slovenian translation 2009-10-26 14:47:54 +01:00
d9ff1f2ec1 [ShellApp] Ignore removal of windows we're not interested in
Previously shell_app_remove_window assumed that it was being
passed a window in its list; rather than having callers check
whether a window is interesting and only if so removing it
from the app, just ignore removal of windows we aren't interested
in, like how we ignore addition of windows we already have.

https://bugzilla.gnome.org/show_bug.cgi?id=598502
2009-10-23 13:19:29 -04:00
10991d363d [ShellWindowTracker] Create fallback apps again
Creating window-based apps got lost in the code refactoring.
2009-10-23 12:26:05 -04:00
0c37a5bd6f [AppIcon] Keep glow up to date directly
AppWell was changed to only do updates on application running state
changes, so we need to update the glow on window count changes.

https://bugzilla.gnome.org/show_bug.cgi?id=599412
2009-10-23 10:59:05 -04:00
369e0c2c6f [ShellApp] Signal windows-changed when removing a window
https://bugzilla.gnome.org/show_bug.cgi?id=599412
2009-10-23 10:59:04 -04:00
17c8173640 Fix minimum height request, handle 0 allocation better
First, fix a problem where though we intended to request a minimum
height of 0 for the docs content, we were actually requesting
spacing for all items.

On low resolution screens, we were still attempting to allocate
an item even when we were given 0 height.

https://bugzilla.gnome.org/show_bug.cgi?id=596984
2009-10-22 22:08:56 -04:00
8fd00ac6cc [AppSwitcher] misc refinements
https://bugzilla.gnome.org/show_bug.cgi?id=597900
2009-10-22 12:14:24 -04:00
4f4e54cbf7 Reset page when doing a FULL redisplay
This fixes an issue where the app display would remember the page
between switching menus.

https://bugzilla.gnome.org/show_bug.cgi?id=597577
2009-10-21 17:50:35 -04:00
16cb878f4e [docInfo] Pass correct object to remove deleted info
We need to pass the actual RecentInfo boxed, not the DocInfo JS Object.
2009-10-21 17:34:52 -04:00
d5adfa6445 Updated Danish translation 2009-10-21 22:51:10 +02:00
8e9549c6f1 [AppSwitcher] Reimplement the separator using St.Bin
This way it can be styled using CSS.
This can help to fix bug 597362.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:19:46 +02:00
7239eb2f90 [StThemeNode] Add support for 'width' and 'height' CSS properties.
The behavior in respect to borders matches CSS - the properties set the size of
the content exclusive of the borders (CSS3 box-sizing property - not implemented
here - changes this).

min-width/min-height correspond very closely to the CSS meanings.

width/height are a little different from the CSS meanings - the CSS meaning is
"exactly this size unless overridden by min/max-width/height" - but within the
realm of our layout algorithm, making them control natural size is pretty
close.

This way we can force elements to have a fixed natural or minimum size.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:18:32 +02:00
5b769138b6 [StThemeNode] round padding values intead of truncating them.
This way, 49.9999 will end up as 50 instead of 49.

https://bugzilla.gnome.org/show_bug.cgi?id=598651
2009-10-21 20:17:28 +02:00
81d579aca0 Disconnect from window signal handlers when removing a window
We need to remove all of our signal handlers attached to a window
when being disposed.

https://bugzilla.gnome.org/show_bug.cgi?id=598502
2009-10-21 11:44:07 -04:00
7548f2d71e [ShellWindowTracker] Don't skip "uninteresting" windows for focus
For the purposes of determining which application is focused, don't
skip "uninteresting" windows.  The old get_focused_window code
was used for usage tracking, but here we want reliable application
association.

Also convert a .text= to .set_text that was missed with the last
patch.

https://bugzilla.gnome.org/show_bug.cgi?id=599206
2009-10-21 11:30:13 -04:00
bda7d3994b [appIcon] Fix reference error when favoriting an app 2009-10-20 18:50:18 -04:00
a336ed79ae [panel] Work around Clutter bug causing missing name
The .text property doesn't queue a resize, see:
http://bugzilla.openedhand.com/show_bug.cgi?id=1851
2009-10-20 16:52:57 -04:00
416fbc775e add appFavorites.js to js/ui/Makefile.am 2009-10-20 15:09:23 -04:00
e941e8088b Split ShellAppMonitor into ShellWindowTracker, ShellAppUsage
The two parts were mapping windows to applications, and
recording application usage statistics.  The latter part
(now called ShellAppUsage) is much more naturally built on top of
the former (now called ShellWindowTracker).

ShellWindowTracker retains the startup-notification handling.

ShellWindowTracker also gains a focus-app property, which is
what most things in the shell UI are interested in (instead of
window focus).

ShellAppSystem moves to exporting ShellApp from more of its
public API, rather than ShellAppInfo.  ShellAppSystem also
ensures that ShellApp instances are unique by holding
a hash on the ids.

ShellApp's private API is split off into a shell-app-private.h,
so shell-app.h can be included in shell-app-system.h.

Favorites handling is removed from ShellAppSystem, now inside
appFavorites.js.

Port all of the JavaScript for these changes.

https://bugzilla.gnome.org/show_bug.cgi?id=598646
2009-10-20 12:55:07 -04:00
77cf9ae077 Added Greek translation 2009-10-20 13:49:40 +03:00
358175e998 Added el to po/LINGUAS 2009-10-20 13:48:21 +03:00
7f5c600133 Use a fixed ordering for well-known icons
Define the ordering for well-known icons; see
the page http://live.gnome.org/Features/StandardIconOrdering

https://bugzilla.gnome.org/show_bug.cgi?id=598313
2009-10-19 14:57:02 -04:00
56bcdd41fd Updated German translation 2009-10-18 11:36:34 +02:00
cd33dc7f22 Annotate list setters
Without these bindings don't know the type of list elements.

https://bugzilla.gnome.org/show_bug.cgi?id=598691
2009-10-16 16:04:46 -04:00
2eef17bcdc [.gitignore] Add *~, .patch 2009-10-16 11:50:29 -04:00
79a614240b [ShellApp] fix app/window sort order
The window lists were not being resorted when user-time changed, and
the app list was mistakenly "penalizing" apps for having *any*
minimized windows, rather than for having *only* minimized windows.

https://bugzilla.gnome.org/show_bug.cgi?id=598389
2009-10-16 11:15:21 -04:00
7c954898a2 Support fixed position children
When doing layout, check for whether x/y have been explicitly
specified, and if so honor those positions.

https://bugzilla.gnome.org/show_bug.cgi?id=598462
2009-10-15 17:40:58 -04:00
497c74f4d8 Minor code cleanup: use child variable consistently
Preparation for a subsequent patch.

https://bugzilla.gnome.org/show_bug.cgi?id=598462
2009-10-15 17:40:58 -04:00
51c41aed90 [workspaces] Don't crash trying to get an icon for untracked app
Use ShellApp directly rather than trying to handle null-safety
with .get_info().
2009-10-15 17:31:57 -04:00
d705c1bb52 [ShellApp] Fix handler signature for workspace switch
This was causing crashes or undefined behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-15 14:05:19 -04:00
d9df7c1b1e [AppWell] Fix D&D for ShellApp
The drag and drop case needed to be updated to use ShellApp
correctly.  Export _is_transient for better compatibility.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-15 13:24:19 -04:00
49eb687713 Updating for Punjabi by A S Alam 2009-10-15 06:20:34 +05:30
7bec02dcb1 [AppWell] Don't duplicate running+favorite
Regression introduced with previous patch.
2009-10-14 15:36:58 -04:00
38c06ca837 Create ShellApp, rebase things on it
Previously, we had ShellAppInfo, which contains fundamental
information about an application, and methods on ShellAppMonitor
to retrieve "live" information like the window list.

AppIcon ended up being used as the "App" class which was painful
for various reasons; among them that we need to handle window
list changes, and some consumers weren't ready for that.

Clean things up a bit by introducing a new ShellApp class in C,
which currently wraps a ShellAppInfo.

AppIcon then is more like the display actor for a ShellApp.  Notably,
the ".windows" property moves out of it.  The altTab code which
won't handle dynamic changes instead is changed to maintain a
cached version.

ShellAppMonitor gains some more methods related to ShellApp now.

In the future, we might consider changing ShellApp to be a GInterface,
which could be implemented by ShellDesktopFileApp, ShellWindowApp.

Then we could axe ShellAppInfo from the "public" API and it would
return to being an internal loss mitigation layer for GMenu.

https://bugzilla.gnome.org/show_bug.cgi?id=598227
2009-10-14 14:37:34 -04:00
6623ca1287 Bump version to 2.28.1 2009-10-14 17:03:18 +01:00
d1bdd6f11d [search] Finish queued search on Return
If we had a pending search processing, finish it when the user
activates the entry.

This is a small conceptual change; the large diff is simply
moving the search implementation (unedited otherwise) from
an anonymous inline to a named function so it can be called
sanely in _activate.

https://bugzilla.gnome.org/show_bug.cgi?id=598111
2009-10-13 16:57:39 -04:00
39edf54aa9 Scroll to bottom when pushing a result
This makes the evaluator significantly more useful past a few
results.

https://bugzilla.gnome.org/show_bug.cgi?id=597919
2009-10-13 13:10:43 -04:00
aa9c585562 Updated Arabic translation 2009-10-13 15:24:40 +02:00
8b813060f0 Update Catalan translation 2009-10-10 20:25:51 +02:00
ca263dade5 Updated Czech translation 2009-10-10 19:03:47 +02:00
b8ef9cdf4b Updated Italian translation 2009-10-10 12:39:44 +02:00
aa92c6fdf5 Add Russian translation
Based on the initial translation from Sergey V. Kovylov and additional
feedback from Andrey Korzinev.
2009-10-09 18:19:06 -04:00
3af8130fff Add places.js to POTFILES.in
places.js was missing.

Reordered files alphabetically.
2009-10-09 18:09:34 -04:00
ab0460ad59 Use clutter_actor_destroy in dispose, add _dispose where needed
ClutterGroup calls _destroy, but most of St was just calling _unparent.
This caused problems because the DESTROY signal was not emitted
for child elements after destroying a toplevel.  Also, in a GC'd
binding it would cause unpredictable lifetime of children.

Some St widgets simply didn't have _dispose at all; implement it.

Note because of the usage of the background_image in StButton,
we can't cleanly destroy it inside the StWidget.

https://bugzilla.gnome.org/show_bug.cgi?id=597845
2009-10-09 16:19:33 -04:00
a27c29f4fc Improve capitalization
"Add to Favorites" and "Remove from Favorites" menu options should be
capitalized throughout.
2009-10-09 00:33:33 -04:00
212d5c1954 Add missing files to POTFILES.in; add a translation hint
POTFILES.in was missing some files.

"Activities" is not easily translatable into some languages, e.g. Russian,
so suggest using the word for "Overview" instead.
2009-10-09 00:30:10 -04:00
8929f43ad9 [AppSwitcher] Fix hiding the arrow on application change.
The down arrow is shown when an application with more than one
window is selected, but the window list is not always displayed.

This patch fixes the fact that the arrow was not hidden when one
focus an app with a single window when coming from an app with
multiple windows, if the window list was not displayed.

https://bugzilla.gnome.org/show_bug.cgi?id=597791
2009-10-08 13:56:47 +02:00
a26b0b60d1 Fix srcdir != builddir build of St.gir
We need to use st_cflags which has -I$(srcdir) not ST_CFLAGS
when building St.gir.
2009-10-07 19:32:00 -04:00
60dbb19c2d Reference Meta-2.28.gir
Now that Mutter has been bumped to 2.28.0, we need to reference
Meta-2.28.gir not Meta-2.27.gir.
2009-10-07 19:27:17 -04:00
3703a86354 Add run-test.sh to CLEANFILES
Fix distcheck by adding run-test.sh to CLEANFILES
2009-10-07 19:18:43 -04:00
992b43f914 Bump version to 2.28.0 2009-10-07 19:07:05 -04:00
ff39edd1ee Deal with unknown flags from ClutterEvent.get_state()
When we get a ClutterModifierType from Clutter, it might contain
bits not in the enumeration. See bug 59771 for a similar problem
with GdkModifierType.

Add a wrapper Shell.get_event_state() around clutter_event_get_state()
to mask these bits out and only return approved bits.

https://bugzilla.gnome.org/show_bug.cgi?id=597735
2009-10-07 17:22:37 -04:00
a81a16801d Fix overview to show on the correct monitor
When tweening the overview in, tween it to appear on the correct
position of the primary monitor, not at (0,0); position
the 'backOver' actor to cover all monitors properly.

Reported by Rui Matos

https://bugzilla.gnome.org/show_bug.cgi?id=597721
2009-10-07 17:14:56 -04:00
4c6f770dea Fix positioning of the Calendar on multihead
Parens were in the wrong place, resulting in the calendar not
being properly centered on the primary monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=597078
2009-10-07 14:52:49 -04:00
c0b01c0210 Match on menu category during application search
Being able to display all applications in a category based on the search
string with a category name is generaly useful.

Prepare all the applications that match a search term based on their
category name up-front.

Remove unused this._appCategories and a call to non-existing
itemInfo.get_categories()
2009-10-07 14:28:49 -04:00
400326e549 Add docs and (transfer none) to st_widget_get_theme_node()
st_widget_get_theme_node() was missing the (transfer none)
GObject Introspection causing crashes. Add that and document the
function.
2009-10-07 14:26:14 -04:00
d7af6d40e3 [AppSwitcher] Use thumbnails instead of a window menu, and other UI changes
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-07 14:00:43 -04:00
90ebcd32e3 Fix exception when showing menu for not-running app
Need to check windows.length before checking first window.

https://bugzilla.gnome.org/show_bug.cgi?id=597466
2009-10-06 17:19:36 -04:00
53d0581377 Don't process the first click on Activities button for a timeout period after the hot corner was triggered
This avoids opening and closing the overview when the hot corner is triggered
and the activities button is clicked.
2009-10-06 16:58:30 -04:00
439daf828f [AppSwitcher] add a workaround for a gjs problem with GdkModifierType
gdk_display_get_pointer() sometimes returns values for the mask that
aren't part of the GdkModifierType enumeration, which gjs doesn't like
(bug 597292). Work around that by adding a C wrapper that strips out
the extra flags.

https://bugzilla.gnome.org/show_bug.cgi?id=597559
2009-10-06 16:07:37 -04:00
d120d03de9 Workaround being allocated 0x0
Because of a chain of bugs we could end up getting allocated 0x0,
and this would cause the WellGrid allocation code to be unhappy.

See http://bugzilla.openedhand.com/show_bug.cgi?id=1831

Simply treat 0 as "unlimited" i.e. equivalent to -1.

https://bugzilla.gnome.org/show_bug.cgi?id=597586
2009-10-06 15:12:20 -04:00
53fbabe2ca Use GtkIMContext instead of ClutterIMContext
Add StIMText, which is a drop-in replacement for ClutterIMText but
uses GtkIMContext instead of ClutterIMContext.

StIMText doesn't have preedit support (would need ClutterText
changes), so isn't going to be useful for complicated input methods,
but is good enough to get dead keys and similar working.

entry.js: Simple test case of StEntry
gnome-shell.modules: Remove clutter-imcontext module

https://bugzilla.gnome.org/show_bug.cgi?id=597471
2009-10-06 14:48:32 -04:00
4bdd40911f Disconnect from window user time notifications, only sort when mapped
Before we were badly leaking AppIcons by not disconnecting from the
window signal handlers when our actor got destroyed.  This caused
us to repeatedly re-sort the windows for each AppIcon that
had ever been displayed with obvious bad consequences.

Besides simply chaining the signals to the lifetime of the AppIcon
actor, we also only do the sorting if we're mapped.  This decreases
the amount of work to do in the not-mapped case.

https://bugzilla.gnome.org/show_bug.cgi?id=597120
2009-10-06 12:49:43 -04:00
ff4ac0d02e [AppIcon] Improve shell_draw_box_pointer()
Add a new enum type for the pointer direction, rather than abusing
ClutterGravity, and implement the missing directions.

https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-06 09:53:47 -04:00
45dd342cc0 [AppIcon] redo constructor to take a params object, add "size" param
Add a "size" parameter to allow changing the AppIcon size, and then
simplify the constructor by taking an object with parameters like
gobject-introspection constructors do, rather than taking a large
number of miscellaneous arguments.

https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-06 09:53:42 -04:00
e5efecd2bd [AppIcon] compute the sorted window list even if not doing the menu
https://bugzilla.gnome.org/show_bug.cgi?id=597498
2009-10-05 22:35:05 -04:00
3bf88b8988 Run dialog: Make error message translatable
Allow the error message to be translated.

https://bugzilla.gnome.org/show_bug.cgi?id=597422
2009-10-05 23:53:50 +02:00
4ddc1118bb Work around libcroco < 0.6.2 parsing bug for 'rgba'
To work around a problem where libcroco < 0.6.2 can't handle
functions starting with 'r' or 'u', preconvert 'rgba' to 'RGBA'
when parsing stylesheets and then check for rgba()
case-insensitively.

(libcroco is uniformly case-sensitive, though the CSS spec requires
that ASCII should be handled case-insensitively.)

https://bugzilla.gnome.org/show_bug.cgi?id=597054
2009-10-05 16:25:38 -04:00
fd1e7b2a0f Places: Add padding between "Connect to.." and devices section
Add padding after "Connect to.." to make the list look consistent when devices
are connected.

https://bugzilla.gnome.org/show_bug.cgi?id=597423
2009-10-05 22:24:04 +02:00
aed1e67add Check that no new term was introduced before doing a subsearch
We combine search terms with OR, so if a new search term is introduced,
the search results are no longer a subset of the previous search results.
2009-10-05 13:50:58 -04:00
dc99e8ffcd [AppSwitcher] Change separator color
https://bugzilla.gnome.org/show_bug.cgi?id=597362
2009-10-05 13:13:21 -04:00
6a8b50cb00 Don't create multiple copies of the (+) button
Currently we recreate it every time Main.overview.show() is called,
 so destroy it to avoid having multiple copies floating around.

https://bugzilla.gnome.org/show_bug.cgi?id=597309
2009-10-05 18:54:41 +02:00
edb50d5dc7 String formatting: Fix warning
Fix to not trigger a warning like:

JS ERROR: !!!   WARNING: 'anonymous function does not always return a value'

by adding a return ""; at the end of the anonymous function.

https://bugzilla.gnome.org/show_bug.cgi?id=595661
2009-10-05 17:59:33 +02:00
2f6c951997 Avoid doing expensive work when not mapped
For some unknown reason we were connecting to app-added and
app-removed on ShellAppMonitor in the AppDisplay class, which
never made any use of the data.  Simply don't connect to those
signals for now.  In the future we should have AppDisplay
be using the AppIcon class which will more correctly handle
dynamic changes.

In the AppWell, avoid doing the full relayout until we're
actually mapped.

https://bugzilla.gnome.org/show_bug.cgi?id=597169
2009-10-05 11:32:33 -04:00
64cd51667d Add String formatting
Add String formatting by extending the String object with a
format method.

Now we can do stuff like "Text: %s, %d".format(somevar, 5)

This is required for proper translation of some strings.

https://bugzilla.gnome.org/show_bug.cgi?id=595661
2009-10-04 23:37:33 +02:00
caa08f27fa Updated German translation 2009-10-04 18:52:10 +02:00
26015ef16d Select next window from the current app on alt+tab
This slightly changes the behaviour of the alt+tab window, this way:
when using alt-tab on a workspace that contains two or more windows from
the same window, the application selected when hitting alt+tab is the
currently selected application, but the highlighted window is the next
one.

Intended goal is to make it easier to cycle around windows of the same
application while not having to cycle through all the applications first.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-04 12:45:23 -04:00
4798ad5107 Consider workspace when sorting windows in menu.
By sorting the windows in the current workspace first, we ensure that
when using alt+tab to switch windows, we will pick a window on the
active workspace as the default focused window for the application if
the application has at least one window on the current workspace (that
is, if it is on the left of the app switcher separator).

This makes the behaviour of alt+tab more predictable for the user, as
an user will expect alt+tab to switch to the window he/she can see right
now rather than the one on the workspace he just left (presumably to do
something else on the workspace he's currently on).

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-04 12:45:19 -04:00
9b05304c2d Use better fitting color for non ARGB tray icons
Currently we use 0xefefefff as a background color for non ARGB tray icons,
which looks out of place (i.e does not fit the panel's background gradient).

Change it to 0x0b0b0bff to fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=597148
2009-10-04 10:02:37 +02:00
795feca393 Updated Arabic translation 2009-10-03 19:20:25 +02:00
31663dcd83 Updated Norwegian bokmål translation. 2009-10-03 10:48:19 +02:00
2f2df61093 Cache applications for a menu
Rather than recomputing this each time someone asks, have a
cache of the apps for a given menu.

https://bugzilla.gnome.org/show_bug.cgi?id=597167
2009-10-02 19:30:42 -04:00
3b8d53060d Immediately pop up menu on right click
We were actually showing a menu on button 3 before, but only
through a chain of coincidences.  This patch explicitly supports
it and makes sure we show it immediately rather than after
a timeout. Pass the activating button in so that we only pop
down on that button.

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
c5ce405859 Ignore releases of buttons other than the activating button
Before we hardcoded popdowns to only button 1 before. But we need
to actually pop down on the release of the activating button.
(Once the button is released, if the we don't pop-down the menu,
then subsequently we let the user use any button.)

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
b3a5fc72fb Add Add/Remove from favorites menu, unify lists more
Also have inactive applications pop up a menu.

Add/Remove from favorites is now in the menu.

Concatenate the favorites/not-favorites instead of having a gap only
if you happened to have a not-divisible-by-4 number of favorites.

https://bugzilla.gnome.org/show_bug.cgi?id=596371
2009-10-02 19:28:25 -04:00
8a2cc11cc0 Fix rundialog not closing for internal commands
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=597076
2009-10-02 14:18:51 -04:00
cbb3a3aec8 Fix make dist by including all the private files and the tests in the tarball 2009-10-02 17:02:25 +01:00
e382da9708 [AppSwitcher] Update colors/border
Switch from Big.Box to St.Bin and update styling per latest spec

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 09:04:04 -04:00
ab1fbbde92 add a missing (optional) ";" 2009-10-02 08:49:22 -04:00
5f5266ca60 [AppSwitcher] Display a separator between apps on this workspace and others.
This makes a visible distinction between the apps that only have minimized
windows on the current workspace and the ones that have no window on the
workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 14:17:00 +02:00
68e8b14b8b [AppSwitcher] Use GenericContainer instead of BigBox.
This allows defining some custom policy for size allocation.
Currently, the minimum width is always used, but it can be tweaked
afterwards when a sizing policy has been defined.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-02 14:15:01 +02:00
abdd8b330c Don't show all sections each time the search is updated
We shouldn't show all sections each time the search is updated because that
breaks viewing search results for a single section and flickers headers for
sections with no results.
2009-10-01 18:21:27 -04:00
eb8176deeb Fix regressions in the item displays
Fix displaying documents in the document browse and refreshing the selection
when the results have changed.

Make sure we are passing the appropriate flag to _redisplay() in GenericDisplay.

Make sure we set this._appsStale to true if there was a change in the
applications set.

Don't call _refreshCache() from the AppDisplay constructor.

Don't short-circuit the call to _refreshCache() from _redisplay() on initial load.

Rename _redisplayFull() to recreateDisplayItems() and remove adding an
actor to the actual result list in _addDisplayItem() because we redo adding the
actors to the list in _redisplayReordering() anyway to ensure that we add
them in the right order.

Based on a patch from Colin Walters.
2009-10-01 17:41:17 -04:00
956f89f377 Add dep of clutter on gir-repository to moduleset
Clutter requires Pango.gir. Until Pango is universally available
in a version that builds its own GIR, Pango.gir is built as part
of gir-repository.

(Found by Adel Gadllah)
2009-10-01 17:34:28 -04:00
1c69380923 [AppSwitcher] Put apps with no window on current workspace at the end.
Following the idea expressed in bug 590563 by mccann ("Minimized or
hidden applications should appear at the end of the list"), we should
also put applications that have no visible window in the active
workspace at the end of the alt-tab window list, after apps which have
minimized windows in the active workspace.
2009-10-01 23:25:15 +02:00
d2bc7b200e Update Catalan translation. 2009-10-01 23:23:54 +02:00
afb3b1e718 Fixes for Calendar widget
Miscellaneous fixes from review:

- Distribute calendar.js and the interactive test
- Make the pointless protection against leap seconds actually work
  by starting in the middle of the day so that forward/back always
  move a day.
- Use a variable instead of an inline '8' to know where to start
  when removing old day actors.
- Remove a stray comment from the test

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 16:48:24 -04:00
061a2cfbfb Add scroll-wheel support to the calendar
Make the calendar reactive and handle scroll events to change the month.
(GtkCalendar and hence the old gnome-panel calendar supported this and
it is apparently a handy way to flip through months.)

The padding is moved from the CalenderPopup to the Calendar so that the
scroll region extends all the way to the edge of the popup.

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 16:48:24 -04:00
243824ab80 Replace "round(x)" with "(int)(0.5 + x)"
round() is a C99 addition, so causes portability problems:
different C library versions require different #defines to
enable it. So simply avoid using it.
2009-10-01 22:39:04 +02:00
90ddad7ba1 Make Connect string translatable
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=597038
2009-10-01 16:11:33 -04:00
20b29ff48f Sync clone stacking order with MetaStackTracker
Previously, we initialized actor stacking order from the return
value of global.get_windows() once, which is defined to be in
stack order.  However it was not updated later.  Furthermore,
the way stackAbove was called from onAnimationComplete in
WindowClone was highly dubious, since there are lots of animations
which apply to the clones, and we want the stacking to be right
all of the time, not when some animation completes.

Fix this by connecting to 'restacked' on the screen and syncing
the clones.

I also snuck in another bugfix here; we weren't disconnecting
from the 'showing' signal handler, which had various bad
consequences.

https://bugzilla.gnome.org/show_bug.cgi?id=596263
2009-10-01 15:59:05 -04:00
96f4d318c5 Add libcroco to gnome-shell-build-setup.sh
Check for the new build dependency "libcroco" when running on any
of the distros supported by the script.
2009-10-01 21:57:53 +02:00
6f7da264ba Support LinuxMint in the build script
LinuxMint is based on Ubuntu, so can be handled with the
same package list as Debian and Ubuntu.

https://bugzilla.gnome.org/show_bug.cgi?id=596447
2009-10-01 15:40:04 -04:00
640e45c12a Make gnome-shell depend on clutter-imcontext
The gnome-shell module requires clutter-imcontext to build.
2009-10-01 15:05:18 -04:00
04e28cd7c4 Add a calendar pop-down to the clock
js/ui/calendar.js: Generic calendar widget
tests/interactive/calendar.js: Basic test of the calendar

js/ui/panel.js: Add a pop-down from the clock that shows a
  calendar widget. The pop-down is not menu-like to allow the user to
  interact with an application while looking at the calendar.
gnome-shell.css: Add theming for calendar, calendar popup, and for
  buttons on the panel

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 15:05:11 -04:00
2cc41c6726 StButton: Fix property enumeration names
Property enumeration names should correspond exactly to the property names;
in particular the ACTIVE vs :checked disparity was confusing reading the
code.

http://bugzilla.moblin.org/show_bug.cgi?id=6504
2009-10-01 14:46:33 -04:00
03a45b665c testcommon.css: Don't theme all buttons
StButton is used for many things - scrollbar steppers, etc. Theming
all buttons to look like push-buttons breaks that. So in testcommon.css
just theme a .push-button class to look vaguely button-like.

https://bugzilla.gnome.org/show_bug.cgi?id=596432
2009-10-01 14:46:33 -04:00
5a42179a96 Port StTable to StThemeNode
Convert the StTable code from StStylable to StThemeNode. The
:row-spacing and :col-spacing GObject properties are converted
into spacing-rows and spacing-columns style properties.

A new interactive test is added for StTable.

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
af3ec56ca1 Handle adding children to StTable from Javascript
Remove the StTable specific methods to add actors:

 st_table_add_actor()
 st_table_add_actor_with_properties()

Since they shadow the generic ClutterContainer add_actor() method,
and patch in our add() convenience function as we do for
StBoxLayout.

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
289b19aa31 Import MxTable as StTable
Import table code from Mx library

https://bugzilla.gnome.org/show_bug.cgi?id=596811
2009-10-01 14:46:33 -04:00
91eb613d69 Turn StBoxLayout:spacing into a style property
Remove the StBoxLayout:spacing GObject property, and instead make
BoxLayout look up the spacing from the CSS style. This makes it
consistent with padding and will allow the use of units. (The
removal of the GObject property entirely instead of making it an
override is consistent with how we handle color, font, padding, etc.)

https://bugzilla.gnome.org/show_bug.cgi?id=596803
2009-10-01 14:46:32 -04:00
1c7c53d19f 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.)

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:46:32 -04:00
d4304495c6 Port LookingGlass console to ST widgets
* Style aspects like colors and fonts are moved into gnome-shell.css.
* Scrolling is adding using StScrollView.

Based on a patch from Colin Walters
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:46:32 -04:00
b77b205d37 Add clutter-text properties to StEntry and StLabel
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 StEntry 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-10-01 14:41:20 -04:00
a15205e6c4 Fix interaction of borders/background and scrolling
StBoxLayout: 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 StScrollView 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.

https://bugzilla.gnome.org/show_bug.cgi?id=595997
2009-10-01 14:41:19 -04:00
28dbf7a06e 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
https://bugzilla.gnome.org/show_bug.cgi?id=595996
2009-10-01 14:41:19 -04:00
1ec8e9eb6b Allow StBoxLayout to shrink down to its minimum size
When a StBoxLayout 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
https://bugzilla.gnome.org/show_bug.cgi?id=595995
2009-10-01 14:41:19 -04:00
fa09f7a6da 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
https://bugzilla.gnome.org/show_bug.cgi?id=595995
2009-10-01 14:41:19 -04:00
d67e54d3ee 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
https://bugzilla.gnome.org/show_bug.cgi?id=595996
2009-10-01 14:41:19 -04:00
d263c12e2e 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 st-widget.c, since
prior to this transparent and translucent borders were handled
differently.)

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
4d55ccff39 Rename StThemeImage to StBorderImage
The current CSS3 border-image is close to a superset of what we were
doing for -hippo-background-image. Woot! rename StThemeImage to
StBorderImage and change parsing to look for:

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

Rather than

 -st-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.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:19 -04:00
2a0adc0fc8 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
StWidget's draw_background() method since they were not used
for StButton (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.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
076e902b2c Centralize computations of border and padding into StThemeNode
Rather than repeating the computation of borders in many different
widget subclasses, add helper functions:

 st_theme_node_adjust_for_height()
 st_theme_node_adjust_preferred_width()
 st_theme_node_adjust_for_width()
 st_theme_node_adjust_preferred_height()
 st_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 StPadding type.

Queueing a relayout when the borders/padding change is moved from
st_widget_real_style_changed() to the invoking code to allow access
to the old StThemeNode 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.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:19 -04:00
8c72623da3 StThemeNode: 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.

https://bugzilla.gnome.org/show_bug.cgi?id=595993
2009-10-01 14:41:18 -04:00
1fd25573e5 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.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
6527dbc8b7 Add support for inline styles
Add support for passing an inline-style string when creating a
StThemeNode.

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

Add a test case that demonstrates using this to update font sizes
on the fly.

https://bugzilla.gnome.org/show_bug.cgi?id=595991
2009-10-01 14:41:18 -04:00
3c646ec516 run-test.sh: support running tests under gdb
As with the 'gnome-shell' -g/--debug can be passed to run under
the debugger.

https://bugzilla.gnome.org/show_bug.cgi?id=595987
2009-10-01 14:41:18 -04:00
a9fd350396 Port our imported parts of Mx to ShellTheme
ShellTheme replaces both StStyle and ccss_stylesheet_t.

The interface StStylable 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 StStylable and ccss_node_t.

Some operations that were previously on StStylable (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.

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
e91e8e993d Add emacs mode-lines to ST sources
To each .c and .h file, add:

 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

'gnu' is the default anyways for Emacs, but indent-tabs-mode is not,
so this sets things up to correspond to the policy of no-tabs.

http://bugzilla.moblin.org/show_bug.cgi?id=6467
2009-10-01 14:41:18 -04:00
276d9a9302 Import stylesheet code from hippo-canvas
Import:

  HippoCanvasTheme      => StTheme
  HippoCanvasThemeImage => StThemeImage
  HippoCanvasStyle      => StThemeNode

StThemeContext 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

https://bugzilla.gnome.org/show_bug.cgi?id=595990
2009-10-01 14:41:18 -04:00
6b95864076 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.)

https://bugzilla.gnome.org/show_bug.cgi?id=595989
2009-10-01 14:41:18 -04:00
d4c577a299 Remove stale C files
Remove several stale C files that we are no longer using; now
that we have a distcheck hook to catch non-distributed files, these
would otherwise prevent distchecking.

https://bugzilla.gnome.org/show_bug.cgi?id=595988
2009-10-01 14:41:17 -04:00
b90fc1e194 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.

https://bugzilla.gnome.org/show_bug.cgi?id=595988
2009-10-01 14:41:17 -04:00
55497899dd Add some structure for interactive tests of UI components
js/ui/environment.js: Split out initial UI setup (Tweener initialization,
  ClutterContainer 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 StLayout

https://bugzilla.gnome.org/show_bug.cgi?id=595987
2009-10-01 14:41:17 -04:00
e37790fdf9 Monkey-patch in ClutterContainer methods for StBoxLayout
Setting options for children added to StBoxLayout 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 StBoxLayout 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-10-01 14:41:17 -04:00
83402957bb 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.

st_texture_cache_get_actor() and st_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-10-01 14:41:17 -04:00
58325fca76 Import MxEntry, MxLabel, MxClipboard
For now this commit introduces an external dependency on clutter-imcontext.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
8b6962f3bf Import MxBoxLayout, MxBoxLayoutChild
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
c1f91def74 Add css for scrolling
Port bits of Mx'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-10-01 14:41:17 -04:00
529f74c0e5 Load gnome-shell.css at startup
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:17 -04:00
459a3b18f2 Add a "datadir" property
Will be used to load stylesheets from main.js.

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
ac2be7f0d1 Remove hardcoded '28' from StScrollView
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
f6b80d5ed4 Import MxScrollView and dependencies
https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
d291e568fd Import Mx core as ST
Import the core MxWidget/MxBin and their dependencies; we use the
namespace "St" (Shell Toolkit) because it is the same length as Mx
so enabling easy sharing of code, but makes it clear that this is
a friendly fork and not a literal import.

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

https://bugzilla.gnome.org/show_bug.cgi?id=591245
2009-10-01 14:41:16 -04:00
2b78d5bd5d Improve support for multihead setups
Fix panel, app switcher, and looking glass to limit themselves to the
primary monitor, and run dialog to limit itself to the monitor
containing the currently-focused window.

The overview is also limited to the primary monitor now (with the
other monitors being blacked out), although the workspaces within the
overview are shaped like the full "screen" (the bounding box of all
monitors). To be fixed later.

https://bugzilla.gnome.org/show_bug.cgi?id=593060
2009-10-01 13:46:03 -04:00
c9d9846759 Add Desktop in Places
Updated by Colin Walters <walters@verbum.org to monitor gconf
and use g_get_user_special_dir.

Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
Signed-off-by: Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=596933
2009-10-01 11:53:30 -04:00
6baafaa530 [places] Fix double spacing between actions and devices
https://bugzilla.gnome.org/show_bug.cgi?id=596991
2009-10-01 10:43:57 -04:00
c2af05f753 [AppSwitcher] Allow use of arrow keys in the popup
https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-10-01 10:35:40 -04:00
97df305a6d [AppSwitcher] Drop the line wrapping code.
Also rename _grid into _appsBox as grid is not an appropriate word
anymore for what this box is.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-30 23:32:36 +02:00
fee385ba35 [AppSwitcher] Do not show the glow for icons in alt+tab dialog.
Unlike icons in the application well, do not show the glow used to
indicate running apps.  It is somewhat redundant here.  These are all
running apps and it is fairly clear from the window list if there are
multiple instances available, according to mccann.

https://bugzilla.gnome.org/show_bug.cgi?id=590563
2009-09-29 18:43:35 +02:00
332 changed files with 74381 additions and 19511 deletions

15
.gitignore vendored
View File

@ -18,12 +18,21 @@ config
configure
data/gnome-shell.desktop
data/gnome-shell.desktop.in
data/gnome-shell-clock-preferences.desktop
data/gnome-shell-clock-preferences.desktop.in
data/gschemas.compiled
data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid
data/org.gnome.accessibility.magnifier.gschema.xml
data/org.gnome.accessibility.magnifier.gschema.valid
intltool-extract.in
intltool-merge.in
intltool-update.in
libtool
m4/
omf.make
po/*.gmo
po/gnome-shell.pot
po/Makefile.in.in
po/POTFILES
po/stamp-it
@ -36,7 +45,13 @@ src/Makefile
src/Makefile.in
src/gnomeshell-taskpanel
src/gnome-shell
src/gnome-shell-clock-preferences
src/test-recorder
src/test-recorder.ogg
src/test-theme
src/st.h
stamp-h1
tests/run-test.sh
xmldocs.make
*~
*.patch

View File

@ -1,18 +1,21 @@
SUBDIRS = data js src po
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src tests po man
EXTRA_DIST = \
.project \
.settings
.settings \
autogen.sh \
tools/check-for-missing.py
# 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"
@failed=false; \
for f in `cd $(srcdir) && git ls-files js` ; do \
if ! test -e $(distdir)/$$f ; then \
echo File missing from distribution: $$f ; \
failed=true ; \
fi \
done ; \
if $$failed ; then \
exit 1 ; \
fi
@echo "Checking disted files against files in git"
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)

View File

@ -5,7 +5,6 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="gnome-shell"
REQUIRED_AUTOMAKE_VERSION=1.10
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {
@ -15,7 +14,7 @@ REQUIRED_AUTOMAKE_VERSION=1.10
}
which gnome-autogen.sh || {
echo "You need to install gnome-common from GNOME Subversion (or from"
echo "You need to install gnome-common from GNOME Git (or from"
echo "your OS vendor's package manager)."
exit 1
}

View File

@ -1,33 +1,40 @@
AC_INIT(gnome-shell, 2.27.3)
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[2.91.0],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([config])
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip foreign])
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS(config.h)
AC_DISABLE_STATIC
# Checks for programs.
AC_PROG_CC
# Needed for per-target cflags, like in gnomeshell-taskpanel
AM_PROG_CC_C_O
AM_PROG_LIBTOOL
# Initialize libtool
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
GETTEXT_PACKAGE=gnome-shell
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
[The prefix for our gettext translation domains.])
PKG_PROG_PKG_CONFIG(0.16)
IT_PROG_INTLTOOL(0.26)
AM_GLIB_GNU_GETTEXT
PKG_PROG_PKG_CONFIG([0.22])
# GConf stuff
AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
AM_GCONF_SOURCE_2
GLIB_GSETTINGS
# Get a value to substitute into gnome-shell.in
AM_PATH_PYTHON([2.5])
AC_SUBST(PYTHON)
@ -50,16 +57,39 @@ fi
AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.3.14
GOBJECT_INTROSPECTION_MIN_VERSION=0.6.11
GJS_MIN_VERSION=0.7
MUTTER_MIN_VERSION=2.91.0
GTK_MIN_VERSION=2.90.7
GIO_MIN_VERSION=2.25.9
# 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(MUTTER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION
gio-unix-2.0 dbus-glib-1
gtk+-3.0 >= $GTK_MIN_VERSION
mutter-plugins >= $MUTTER_MIN_VERSION
gjs-gi-1.0 >= $GJS_MIN_VERSION
libgnome-menu $recorder_modules gconf-2.0
gdk-x11-3.0
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
libstartup-notification-1.0
gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION)
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS
CFLAGS=$MUTTER_PLUGIN_CFLAGS
LIBS=$MUTTER_PLUGIN_LIBS
# sn_startup_sequence_get_application_id, we can replace with a version check later
AC_CHECK_FUNCS(JS_NewGlobalObject sn_startup_sequence_get_application_id)
CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
PKG_CHECK_MODULES(TIDY, clutter-1.0)
PKG_CHECK_MODULES(BIG, clutter-1.0 gtk+-2.0 librsvg-2.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-2.0)
PKG_CHECK_MODULES(TRAY, gtk+-2.0)
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 gnome-desktop-3.0 >= 2.90.0)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
MUTTER_BIN_DIR=`$PKG_CONFIG --variable=exec_prefix mutter-plugins`/bin
# FIXME: metacity-plugins.pc should point directly to its .gir file
@ -71,10 +101,13 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
GJS_JS_DIR=`$PKG_CONFIG --variable=jsdir gjs-1.0`
GJS_JS_NATIVE_DIR=`$PKG_CONFIG --variable=jsnativedir gjs-1.0`
GJS_CONSOLE=`$PKG_CONFIG --variable=gjs_console gjs-1.0`
AC_SUBST(GJS_JS_DIR)
AC_SUBST(GJS_JS_NATIVE_DIR)
AC_SUBST(GJS_CONSOLE)
AC_CHECK_FUNCS(fdwalk)
AC_CHECK_FUNCS(mallinfo)
AC_CHECK_HEADERS([sys/resource.h])
# Sets GLIB_GENMARSHAL and GLIB_MKENUMS
@ -93,8 +126,7 @@ AC_SUBST(TYPELIBDIR)
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
[Turn on compiler warnings]),,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
changequote(,)dnl
@ -121,12 +153,21 @@ changequote([,])dnl
AC_PATH_PROG(mutter, [mutter])
AC_SUBST(mutter)
AC_OUTPUT([
AC_MSG_CHECKING([if mutter was compiled with GTK+-3.0])
if $PKG_CONFIG --libs libmutter-private | grep gtk-x11-3 >/dev/null; then
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
AC_MSG_ERROR([GNOME Shell requires Mutter to be compiled against GTK+-3.0])
fi
AC_CONFIG_FILES([
Makefile
data/Makefile
js/Makefile
js/misc/Makefile
js/ui/Makefile
src/Makefile
tests/Makefile
po/Makefile.in
man/Makefile
])
AC_OUTPUT

View File

@ -1,40 +1,101 @@
desktopdir=$(datadir)/applications
desktop_DATA = gnome-shell.desktop
desktop_DATA = gnome-shell.desktop gnome-shell-clock-preferences.desktop
# We substitute in bindir so it works as an autostart
# file when built in a non-system prefix
gnome-shell.desktop.in: gnome-shell.desktop.in.in
%.desktop.in:%.desktop.in.in
$(AM_V_GEN) sed -e "s|@bindir[@]|$(bindir)|" \
-e "s|@VERSION[@]|$(VERSION)|" \
$< > $@ || rm $@
# Placeholder until we add intltool
gnome-shell.desktop: gnome-shell.desktop.in
%.desktop:%.desktop.in
$(AM_V_GEN) sed s/^_// < $< > $@ || rm $@
imagedir = $(pkgdatadir)/images
dist_pkgdata_DATA = clock-preferences.ui
dist_image_DATA = \
add-workspace.svg \
app-well-glow.png \
back.svg \
close.svg \
close-black.svg \
info.svg \
magnifier.svg \
remove-workspace.svg
imagesdir = $(pkgdatadir)/images
dist_images_DATA = \
close-black.svg \
magnifier.svg
schemadir = @GCONF_SCHEMA_FILE_DIR@
schema_DATA = gnome-shell.schemas
themedir = $(pkgdatadir)/theme
dist_theme_DATA = \
theme/add-workspace.svg \
theme/close-window.svg \
theme/close.svg \
theme/corner-ripple.png \
theme/dialog-error.svg \
theme/gnome-shell.css \
theme/mosaic-view-active.svg \
theme/mosaic-view.svg \
theme/move-window-on-new.svg \
theme/process-working.png \
theme/remove-workspace.svg \
theme/scroll-button-down-hover.png \
theme/scroll-button-down.png \
theme/scroll-button-up-hover.png \
theme/scroll-button-up.png \
theme/scroll-hhandle.svg \
theme/scroll-vhandle.svg \
theme/section-more.svg \
theme/section-more-open.svg \
theme/separator-white.png \
theme/single-view-active.svg \
theme/single-view.svg \
theme/toggle-off-us.svg \
theme/toggle-off-intl.svg \
theme/toggle-on-us.svg \
theme/toggle-on-intl.svg \
theme/ws-switch-arrow-left.svg \
theme/ws-switch-arrow-right.svg
gsettings_SCHEMAS = \
org.gnome.accessibility.magnifier.gschema.xml \
org.gnome.shell.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
# We need to compile schemas at make time
# to run from source tree
gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
$(AM_V_GEN) $(GLIB_COMPILE_SCHEMAS) --targetdir=. .
all-local: gschemas.compiled
# GConf schemas: provide defaults for keys from Metacity we are overriding
gconfschemadir = @GCONF_SCHEMA_FILE_DIR@
gconfschema_DATA = gnome-shell.schemas
menudir = $(sysconfdir)/xdg/menus
menu_DATA = \
gs-applications.menu
shadersdir = $(pkgdatadir)/shaders
shaders_DATA = \
shaders/dim-window.glsl
install-data-local:
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(schema_DATA)
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(gconfschema_DATA)
EXTRA_DIST = \
gnome-shell.desktop.in.in \
$(schema_DATA)
CLEANFILES = \
gnome-shell.desktop.in \
$(desktop_DATA)
EXTRA_DIST = \
gnome-shell.desktop.in.in \
gnome-shell-clock-preferences.desktop.in.in \
$(menu_DATA) \
$(gconfschema_DATA) \
$(shaders_DATA) \
org.gnome.accessibility.magnifier.gschema.xml.in \
org.gnome.shell.gschema.xml.in
CLEANFILES = \
gnome-shell.desktop.in \
gnome-shell-clock-preferences.desktop.in \
$(desktop_DATA) \
$(gsettings_SCHEMAS) \
gschemas.compiled

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="59.995201"
height="59.995102"
id="svg3113"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="add-workspace.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3115">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3121" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="375"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="641"
inkscape:window-height="683"
inkscape:window-x="4"
inkscape:window-y="54" />
<metadata
id="metadata3118">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-498.57383,-439.50749)">
<path
id="path3269"
d="M 528.57143,439.91129 C 512.23433,439.91129 498.97763,453.16795 498.97763,469.50504 C 498.97763,485.84214 512.23433,499.09881 528.57143,499.09879 C 544.90853,499.09879 558.16513,485.84215 558.16523,469.50504 C 558.16523,453.16794 544.90853,439.9113 528.57143,439.91129 z M 525.29023,451.16129 L 531.88393,451.16129 C 533.75363,451.16129 535.25893,452.66659 535.25893,454.53629 L 535.25893,462.84879 L 543.54023,462.84879 C 545.40973,462.84879 546.91523,464.35409 546.91523,466.22379 L 546.91523,472.81754 C 546.91523,474.68728 545.40993,476.19255 543.54023,476.19254 L 535.25893,476.19254 L 535.25893,484.47379 C 535.25893,486.34353 533.75363,487.8488 531.88393,487.84879 L 525.29023,487.84879 C 523.42053,487.84881 521.91523,486.34351 521.91523,484.47379 L 521.91523,476.19254 L 513.60263,476.19254 C 511.73313,476.19257 510.22773,474.68726 510.22763,472.81754 L 510.22763,466.22379 C 510.22763,464.35407 511.73303,462.8488 513.60263,462.84879 L 521.91523,462.84879 L 521.91523,454.53629 C 521.91523,452.66657 523.42043,451.1613 525.29023,451.16129 z"
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,7 +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.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>

Before

Width:  |  Height:  |  Size: 1.9 KiB

188
data/clock-preferences.ui Normal file
View File

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

View File

@ -62,5 +62,5 @@
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>
style="fill-opacity:1;fill:#545454" />
</svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

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

View File

@ -1,93 +1,66 @@
<gconfschemafile>
<schemalist>
<!-- Metacity overrides -->
<schema>
<key>/schemas/desktop/gnome/shell/development_tools</key>
<applyto>/desktop/gnome/shell/development_tools</applyto>
<key>/schemas/desktop/gnome/shell/windows/attach_modal_dialogs</key>
<applyto>/desktop/gnome/shell/windows/attach_modal_dialogs</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>
<short>Attach modal dialog to the parent window</short>
<long>
This key overrides /apps/mutter/general/attach_modal_dialogs when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/app_monitor/enable_monitoring</key>
<applyto>/desktop/gnome/shell/app_monitor/enable_monitoring</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Whether to collect stats about applications usage</short>
<long>
The shell normally monitors active applications in order to present the most used ones (e.g. in launchers). While this data will be kept private, you may want to disable this for privacy reasons. Please note that doing so won't remove already saved data.
</long>
</locale>
<key>/schemas/desktop/gnome/shell/windows/button_layout</key>
<applyto>/desktop/gnome/shell/windows/button_layout</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>:minimize,maximize,close</default>
<locale name="C">
<short>Arrangement of buttons on the titlebar</short>
<long>
Arrangement of buttons on the titlebar. The
value should be a string, such as
"menu:minimize,maximize,spacer,close"; the colon separates the
left corner of the window from the right corner, and
the button names are comma-separated. Duplicate buttons
are not allowed. Unknown button names are silently ignored
so that buttons can be added in future gnome-shell versions
without breaking older versions.
A special spacer tag can be used to insert some space between
two adjacent buttons.
This key overrides /apps/metacity/general/button_layout when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/favorite_apps</key>
<applyto>/desktop/gnome/shell/favorite_apps</applyto>
<owner>gnome-shell</owner>
<type>list</type>
<list_type>string</list_type>
<default>[mozilla-firefox.desktop,evolution.desktop,openoffice.org-writer.desktop]</default>
<locale name="C">
<short>List of desktop file IDs for favorite applications</short>
<long>
The applications corresponding to these identifiers will be displayed in the favorites area.
</long>
</locale>
</schema>
<key>/schemas/desktop/gnome/shell/windows/side_by_side_tiling</key>
<applyto>/desktop/gnome/shell/windows/side_by_side_tiling</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>enable side-by-side tiling when dropping windows on screen edges</short>
<long>
If enabled, dropping windows on screen edges maximizes them
vertically and resizes them horizontally to cover half of the
available area.
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/visible</key>
<applyto>/desktop/gnome/shell/sidebar/visible</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>false</default>
<locale name="C">
<short>Whether or not to display the sidebar</short>
<long>
Determines whether or not the sidebar is visible.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/expanded</key>
<applyto>/desktop/gnome/shell/sidebar/expanded</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Whether the sidebar should be in the expanded (wide) mode</short>
<long>
Controls the expanded/collapsed state of the sidebar.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/sidebar/widgets</key>
<applyto>/desktop/gnome/shell/sidebar/widgets</applyto>
<owner>gnome-shell</owner>
<type>list</type>
<list_type>string</list_type>
<default>[imports.ui.widget.ClockWidget,imports.ui.widget.AppsWidget,imports.ui.widget.RecentDocsWidget]</default>
<locale name="C">
<short>The widgets to display in the sidebar</short>
<long>
The widgets to display in the sidebar, in order from top to bottom. Each widget "name" is actually a JavaScript expression referring to a widget constructor object.
</long>
</locale>
This key overrides /apps/metacity/general/side_by_side_tiling when
running GNOME Shell.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

44
data/gs-applications.menu Normal file
View File

@ -0,0 +1,44 @@
<Menu>
<DefaultLayout>
<Menuname>Apps</Menuname>
<Menuname>Games</Menuname>
<Menuname>Tools</Menuname>
</DefaultLayout>
<Name>Applications</Name>
<DefaultAppDirs/>
<Menu>
<Name>Games</Name>
<Include>
<And>
<Category>Game</Category>
</And>
</Include>
</Menu>
<Menu>
<Name>Tools</Name>
<Include>
<Category>Development</Category>
<And>
<Category>System</Category>
<Not>
<Category>Settings</Category>
</Not>
</And>
<Category>Utility</Category>
</Include>
</Menu>
<Menu>
<Name>Apps</Name>
<OnlyUnallocated/>
<Include>
<And>
<Or>
<Category>Documentation</Category>
<Not><Category>Core</Category></Not>
</Or>
<Not><Category>Settings</Category></Not>
<Not><Category>Screensaver</Category></Not>
</And>
</Include>
</Menu>
</Menu>

View File

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

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,133 @@
<schemalist>
<enum id="MouseTrackingMode">
<value nick="none" value="0"/>
<value nick="centered" value="1"/>
<value nick="proportional" value="2"/>
<value nick="push" value="3"/>
</enum>
<enum id="ScreenPosition">
<value nick="none" value="0"/>
<value nick="full-screen" value="1"/>
<value nick="top-half" value="2"/>
<value nick="bottom-half" value="3"/>
<value nick="left-half" value="4"/>
<value nick="right-half" value="5"/>
</enum>
<schema id="org.gnome.accessibility.magnifier"
path="/desktop/gnome/accessibility/magnifier/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="show-magnifier" type="b">
<default>false</default>
<_summary>Show or hide the magnifier</_summary>
<_description>
Show or hide the magnifier and all of its zoom regions.
</_description>
</key>
<key name="mouse-tracking" enum="MouseTrackingMode">
<default>'centered'</default>
<_summary>Mouse Tracking Mode</_summary>
<_description>
Determines the position of the magnified mouse image within the
magnified view and how it reacts to system mouse movement. The values
are
- none: no mouse tracking;
- centered: the mouse image is
displayed at the center of the zoom region (which also represents
the point under the system mouse) and the magnified contents are
scrolled as the system mouse moves;
- proportional: the position of the magnified mouse in the zoom region
is proportionally the same as the position of the system mouse on screen;
- push: when the magnified mouse intersects a boundary of the zoom
region, the contents are scrolled into view.
</_description>
</key>
<key name="screen-position" enum="ScreenPosition">
<default>'bottom-half'</default>
<_summary>Screen position</_summary>
<_description>
The magnified view either fills the entire screen, or occupies the
top-half, bottom-half, left-half, or right-half of the screen.
</_description>
</key>
<key name="mag-factor" type="d">
<default>2.0</default>
<_summary>Magnification factor</_summary>
<_description>
The power of the magnification. A value of 1.0 means no magnification.
A value of 2.0 doubles the size.
</_description>
</key>
<key name="lens-mode" type="b">
<default>false</default>
<_summary>Enable lens mode</_summary>
<_description>
Whether the magnified view should be centered over the location of
the system mouse and move with it.
</_description>
</key>
<key name="scroll-at-edges" type="b">
<default>false</default>
<_summary>
Scroll magnified contents beyond the edges of the desktop
</_summary>
<_description>
For centered mouse tracking, when the system pointer is at or near the
edge of the screen, the magnified contents continue to scroll such that
the screen edge moves into the magnified view.
</_description>
</key>
<!-- Cross-hairs -->
<key name="show-cross-hairs" type="b">
<default>false</default>
<_summary>Show or hide crosshairs</_summary>
<_description>
Enables/disables display of crosshairs centered on the magnified
mouse sprite.
</_description>
</key>
<key name="cross-hairs-thickness" type="i">
<default>8</default>
<_summary>Thickness of the crosshairs</_summary>
<_description>
Width of the vertical and horizontal lines that make up the crosshairs.
</_description>
</key>
<key name="cross-hairs-color" type="s">
<default>'#ff0000'</default>
<_summary>Color of the crosshairs</_summary>
<_description>
The color of the the vertical and horizontal lines that make up
the crosshairs.
</_description>
</key>
<key name="cross-hairs-opacity" type="i">
<default>169</default>
<_summary>Opacity of the crosshairs</_summary>
<_description>
Determines the transparency of the crosshairs, from fully opaque
to fully transparent.
</_description>
</key>
<key name="cross-hairs-length" type="i">
<default>4096</default>
<_summary>Length of the crosshairs</_summary>
<_description>
Determines the length of the vertical and horizontal lines that
make up the crosshairs.
</_description>
</key>
<key name="cross-hairs-clip" type="b">
<default>false</default>
<_summary>Clip the crosshairs at the center</_summary>
<_description>
Determines whether the crosshairs intersect the magnified mouse sprite,
or are clipped such that the ends of the horizontal and vertical lines
surround the mouse image.
</_description>
</key>
</schema>
</schemalist>

View File

@ -0,0 +1,158 @@
<schemalist>
<schema id="org.gnome.shell" path="/apps/gnome-shell/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="development-tools" type="b">
<default>true</default>
<_summary>
Enable internal tools useful for developers and testers from Alt-F2
</_summary>
<_description>
Allows access to internal debugging and monitoring tools
using the Alt-F2 dialog.
</_description>
</key>
<key name="disabled-extensions" type="as">
<default>[]</default>
<_summary>Uuids of extensions to disable</_summary>
<_description>
GNOME Shell extensions have a uuid property;
this key lists extensions which should not be loaded.
</_description>
</key>
<key name="enable-app-monitoring" type="b">
<default>true</default>
<_summary>Whether to collect stats about applications usage</_summary>
<_description>
The shell normally monitors active applications in order to present
the most used ones (e.g. in launchers). While this data will be
kept private, you may want to disable this for privacy reasons.
Please note that doing so won't remove already saved data.
</_description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'mozilla-firefox.desktop', 'evolution.desktop', 'openoffice.org-writer.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary>
<_description>
The applications corresponding to these identifiers
will be displayed in the favorites area.
</_description>
</key>
<key name="command-history" type="as">
<default>[]</default>
<_summary>History for command (Alt-F2) dialog</_summary>
</key>
<key name="workspaces-view" type="s">
<default>'single'</default>
<_summary>Overview workspace view mode</_summary>
<_description>
The selected workspace view mode in the overview.
Supported values are "single" and "grid".
</_description>
<choices>
<choice value="single"/>
<choice value="grid"/>
</choices>
</key>
<child name="clock" schema="org.gnome.shell.clock"/>
<child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="recorder" schema="org.gnome.shell.recorder"/>
</schema>
<schema id="org.gnome.shell.calendar" path="/apps/gnome-shell/calendar/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="show-weekdate" type="b">
<default>false</default>
<_summary>Show the week date in the calendar</_summary>
<_description>
If true, display the ISO week date in the calendar.
</_description>
</key>
</schema>
<schema id="org.gnome.shell.clock" path="/apps/gnome-shell/clock/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="format" type="s">
<default l10n="messages" context="hour_format">
<!-- TRANSLATORS: This is the default hour format, choose ONLY '12-hour' or '24-hour'. -->
"12-hour"
</default>
<_summary>Hour format</_summary>
<_description>
This key specifies the hour format used by the panel clock.
Possible values are "12-hour", "24-hour", "unix" and "custom". If set
to "unix", the clock will display time in seconds since Epoch,
i.e. 1970-01-01. If set to "custom", the clock will display time
according to the format specified in the custom_format key. Note that
if set to either "unix" or "custom", the show_date and show_seconds
keys are ignored.
</_description>
<choices>
<choice value="12-hour"/>
<choice value="24-hour"/>
<choice value="unix"/>
<choice value="custom"/>
</choices>
</key>
<key name="custom-format" type="s">
<default>''</default>
<_summary>Custom format of the clock</_summary>
<_description>
This key specifies the format used by the panel clock when the format
key is set to "custom". You can use conversion specifiers understood
by strftime() to obtain a specific format. See the strftime() manual
for more information.
</_description>
</key>
<key name="show-seconds" type="b">
<default>false</default>
<_summary>Show time with seconds</_summary>
<_description>
If true and format is either "12-hour" or "24-hour", display seconds in time.
</_description>
</key>
<key name="show-date" type="b">
<default>false</default>
<_summary>Show date in clock</_summary>
<_description>
If true and format is either "12-hour" or "24-hour",
display date in the clock, in addition to time.
</_description>
</key>
</schema>
<schema id="org.gnome.shell.recorder" path="/apps/gnome-shell/recorder/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="framerate" type="i">
<default>15</default>
<_summary>Framerate used for recording screencasts.</_summary>
<_description>
The framerate of the resulting screencast recordered
by GNOME Shell's screencast recorder in frames-per-second.
</_description>
</key>
<key name="pipeline" type="s">
<default>''</default>
<_summary>The gstreamer pipeline used to encode the screencast</_summary>
<_description>
Sets the GStreamer pipeline used to encode recordings.
It follows the syntax used for gst-launch. The pipeline should have
an unconnected sink pad where the recorded video is recorded. It will
normally have a unconnected source pad; output from that pad
will be written into the output file. However the pipeline can also
take care of its own output - this might be used to send the output
to an icecast server via shout2send or similar. When unset or set
to an empty value, the default pipeline will be used. This is currently
'videorate ! theoraenc ! oggmux' and records to Ogg Theora.
</_description>
</key>
<key name="file-extension" type="s">
<default>'ogv'</default>
<_summary>File extension used for storing the screencast</_summary>
<_description>
The filename for recorded screencasts will be a unique filename
based on the current date, and use this extension. It should be
changed when recording to a different container format.
</_description>
</key>
</schema>
</schemalist>

View File

@ -1,71 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="59.995201"
height="59.995102"
id="svg3113"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="remove-workspace.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs3115">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3121" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4.5"
inkscape:cx="-8.1974244"
inkscape:cy="38.948933"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1400"
inkscape:window-height="971"
inkscape:window-x="454"
inkscape:window-y="105" />
<metadata
id="metadata3118">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-498.57383,-439.50749)">
<path
style="opacity:0.30701785;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.807603px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="M 30 0.40625 C 13.662899 0.40624999 0.40625 13.66291 0.40625 30 C 0.40624999 46.337101 13.6629 59.59377 30 59.59375 C 46.337099 59.593749 59.59365 46.33711 59.59375 30 C 59.59375 13.662901 46.3371 0.40626 30 0.40625 z M 15.03125 23.34375 L 44.96875 23.34375 C 46.83825 23.343751 48.34375 24.84905 48.34375 26.71875 L 48.34375 33.3125 C 48.34375 35.182239 46.83845 36.68751 44.96875 36.6875 L 15.03125 36.6875 C 13.16175 36.687529 11.65635 35.18222 11.65625 33.3125 L 11.65625 26.71875 C 11.65625 24.849031 13.16165 23.34376 15.03125 23.34375 z "
transform="translate(498.57383,439.50749)"
id="path2382" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,26 @@
#version 110
uniform sampler2D sampler0;
uniform float fraction;
uniform float height;
const float c = -0.2;
const float border_max_height = 60.0;
mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
0.0, 1.0 + c, 0.0, 0.0,
0.0, 0.0, 1.0 + c, 0.0,
0.0, 0.0, 0.0, 1.0);
vec4 off = vec4(0.633, 0.633, 0.633, 0);
void main()
{
vec4 color = texture2D(sampler0, gl_TexCoord[0].st);
float y = height * gl_TexCoord[0][1];
// To reduce contrast, blend with a mid gray
gl_FragColor = color * contrast - off * c;
// We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
// when the fraction is 1.0. For other locations and fractions we linearly
// interpolate back to the original undimmed color.
gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0);
gl_FragColor = color + (gl_FragColor - color) * fraction;
}

View File

@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="23"
height="15"
id="svg6375"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="New document 13">
<defs
id="defs6377">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6383" />
<inkscape:perspective
id="perspective6366"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6380">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<g
style="display:inline"
id="g6243"
transform="translate(-986.28859,-658.2796)">
<rect
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="rect5318"
width="22"
height="14"
x="986.89801"
y="675.86743"
rx="0.49999979"
ry="0.5" />
<g
id="g5320"
transform="translate(402.77304,-12.882544)">
<path
id="path5322"
d="m 595.125,692.53048 0,6.43903"
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
id="path5324"
d="m 598.34451,695.75 -6.43902,0"
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,76 @@
<?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="22"
height="22"
viewBox="0 0 16 16"
enable-background="new 0 0 16 16"
xml:space="preserve"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="close-window.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 /></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="999"
inkscape:window-width="1680"
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="false"
inkscape:zoom="25.648691"
inkscape:cx="8.8097603"
inkscape:cy="9.0472789"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:current-layer="Foreground"
showguides="true"
inkscape:guide-bbox="true" />
<g
id="g3175"><path
sodipodi:nodetypes="csssc"
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.59217799;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path2394"
d="M 0.83987936,8.0425327 C 0.83987936,4.0805265 4.0712155,0.86823453 8.0567103,0.86823453 C 12.042205,0.86823453 15.273542,4.0805265 15.273542,8.0425327 C 15.273542,12.004539 12.042205,15.216831 8.0567103,15.216831 C 4.0712155,15.216831 0.83987936,12.004539 0.83987936,8.0425327 z"
clip-rule="evenodd" /><g
id="g3172"><path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.4242673,5.3313047 L 10.515414,10.421272 L 10.714004,10.646491"
id="path3152" /></g></g><path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.67127273;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5.4402527,10.650392 L 10.688082,5.3573033"
id="path3154"
sodipodi:nodetypes="cc" /></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

222
data/theme/dialog-error.svg Normal file
View File

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

After

Width:  |  Height:  |  Size: 8.0 KiB

1160
data/theme/gnome-shell.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6503"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="mosaic-view-active.svg">
<defs
id="defs6505">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6511" />
<inkscape:perspective
id="perspective6494"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="-15.97056"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6508">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-16)">
<g
style="display:inline;fill:#cbcbcb;fill-opacity:1"
transform="translate(-449.85476,-685.85869)"
id="g5306">
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none"
id="rect5308"
width="11"
height="7"
x="450.5"
y="710.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5310"
width="11"
height="7"
x="462.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999976000000002;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5312"
width="11"
height="7"
x="450.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#cbcbcb;fill-opacity:1;stroke:#000000;stroke-width:0.99999970000000005;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.44262299999999999;stroke-dasharray:none;display:inline"
id="rect5314"
width="11"
height="7"
x="462.5"
y="710.5"
rx="0.99999958"
ry="1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

113
data/theme/mosaic-view.svg Normal file
View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6503"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="New document 19">
<defs
id="defs6505">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6511" />
<inkscape:perspective
id="perspective6494"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="16"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6508">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-16)">
<g
style="display:inline"
transform="translate(-449.85476,-685.85869)"
id="g5306">
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none"
id="rect5308"
width="11"
height="7"
x="450.5"
y="710.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5310"
width="11"
height="7"
x="462.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.99999976;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5312"
width="11"
height="7"
x="450.5"
y="702.5"
rx="0.99999958"
ry="1" />
<rect
style="fill:#666666;fill-opacity:1;stroke:#000000;stroke-width:0.9999997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.442623;stroke-dasharray:none;display:inline"
id="rect5314"
width="11"
height="7"
x="462.5"
y="710.5"
rx="0.99999958"
ry="1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="98"
height="98"
id="svg6375"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="add-workspace.svg">
<defs
id="defs6377">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6383" />
<inkscape:perspective
id="perspective6366"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.9590209"
inkscape:cx="56.650687"
inkscape:cy="20.635343"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6380">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,66)">
<g
id="g2824"
transform="matrix(11.568551,0,0,11.698271,-78.828159,-304.81518)">
<path
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 11.07363,21.36834 0,6.43903"
id="path5322" />
<path
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
d="m 14.29314,24.58786 -6.43902,0"
id="path5324" />
</g>
<path
style="fill:#000000;fill-opacity:0.98823529"
d="m 48.239516,97.908047 c -0.41677,-0.05102 -1.269253,-0.222408 -1.894408,-0.380859 -4.088493,-1.036262 -7.520781,-4.753234 -8.330163,-9.021094 -0.154947,-0.817026 -0.257819,-6.68112 -0.257819,-14.696556 l 0,-13.337088 -13.829177,-0.08909 C 10.802042,60.298796 10.026884,60.268266 8.6851548,59.783022 3.6288503,57.954375 0.62673331,53.828648 0.62673331,48.708554 c 0,-5.625522 4.25936019,-10.425065 9.97721469,-11.242548 0.987903,-0.141242 7.368912,-0.254994 14.460646,-0.257791 l 12.692532,-0.005 0,-13.586668 c 0,-14.6441583 0.03287,-15.0698926 1.364686,-17.6753047 2.185477,-4.2754229 6.938193,-6.75739913 11.687647,-6.10355607 3.382776,0.46569661 6.737962,2.72496967 8.414081,5.66577137 1.480816,2.5981315 1.519067,3.0522448 1.519067,18.0333334 l 0,13.666424 12.692533,0.005 c 7.091733,0.0028 13.472742,0.116549 14.460646,0.257791 6.395303,0.914337 10.804785,6.623716 9.941157,12.871766 -0.698243,5.051565 -4.792685,9.104635 -9.941157,9.840713 -0.987904,0.141242 -7.368913,0.254995 -14.460646,0.257791 l -12.692533,0.005 0,13.801945 c 0,13.031417 -0.02798,13.895893 -0.501177,15.484801 -1.526902,5.127058 -6.919246,8.802262 -12.001914,8.18002 z"
id="path2828"
transform="translate(0,-66)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="23"
height="15"
id="svg5501"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="add-workspace.svg">
<defs
id="defs5503">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective5509" />
<inkscape:perspective
id="perspective5314"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="-0.074583208"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1"
inkscape:snap-grids="true"
inkscape:snap-bbox="true" />
<metadata
id="metadata5506">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<g
style="display:inline"
id="g6239"
transform="translate(-953.97989,-657.32287)">
<rect
style="fill:#000000;fill-opacity:0.98770495;stroke:#666666;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
id="rect5318-6"
width="22"
height="14"
x="954.5"
y="675"
rx="0.49999979"
ry="0.5" />
<path
style="fill:none;stroke:#666666;stroke-width:1.99999952;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
d="m 968.71951,682 -6.43902,0"
id="path5324-5" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

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

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="10"
height="4"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="scroll-hhandle.svg">
<defs
id="defs4">
</defs>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="rect3592"
width="2"
height="4"
x="0"
y="0"
rx="0"
ry="0" />
<use
x="0"
y="0"
xlink:href="#rect3592"
id="use2825"
transform="translate(8,0)"
width="10"
height="4" />
<use
x="0"
y="0"
xlink:href="#use2825"
id="use2827"
transform="translate(-4,0)"
width="10"
height="4" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="4"
height="10"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="scroll-hhandle.svg">
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:#323232;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="rect3592"
width="2"
height="4"
x="0"
y="-4"
rx="0"
ry="0"
transform="matrix(0,1,-1,0,0,0)" />
<use
x="0"
y="0"
xlink:href="#rect3592"
id="use3705"
transform="translate(0,4)"
width="4"
height="10" />
<use
x="0"
y="0"
xlink:href="#use3705"
id="use3707"
transform="translate(0,4)"
width="4"
height="10" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5.8600588"
height="9"
id="svg3647"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="section-more.svg">
<defs
id="defs3649">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3655" />
<inkscape:perspective
id="perspective3603"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="82.777778"
inkscape:cx="2.9300294"
inkscape:cy="5.466443"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata3652">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-262.78425,-490.71933)">
<path
transform="matrix(0,-0.98149546,0.71467449,0,25.404986,578.15569)"
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="1.5707963"
sodipodi:arg1="0.52359878"
sodipodi:r2="2.5"
sodipodi:r1="5"
sodipodi:cy="337.5"
sodipodi:cx="84.5"
sodipodi:sides="3"
id="path5497-5"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
sodipodi:type="star" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

87
data/theme/section-more.svg Executable file
View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5.8600588"
height="9"
id="svg3647"
version="1.1"
inkscape:version="0.46+devel"
sodipodi:docname="New document 6">
<defs
id="defs3649">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3655" />
<inkscape:perspective
id="perspective3603"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="112.21575"
inkscape:cy="-32.642856"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="164"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata3652">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-262.78425,-490.71933)">
<path
transform="matrix(0,0.98149546,-0.71467449,0,506.02358,412.28296)"
d="M 88.830127,340 80.169873,340 84.5,332.5 88.830127,340 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="1.5707963"
sodipodi:arg1="0.52359878"
sodipodi:r2="2.5"
sodipodi:r1="5"
sodipodi:cy="337.5"
sodipodi:cx="84.5"
sodipodi:sides="3"
id="path5497-5"
style="fill:#5f5f5f;fill-opacity:1;stroke:#5f5f5f;stroke-width:0.59699643;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
sodipodi:type="star" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6446"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="single-view-active.svg">
<defs
id="defs6448">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6454" />
<inkscape:perspective
id="perspective6441"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="0.014720032"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6451">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<rect
ry="0.5"
rx="0.49999979"
y="17.483809"
x="0.53483802"
height="15"
width="23"
id="rect5304"
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="16"
id="svg6446"
version="1.1"
inkscape:version="0.47pre4 r22446"
sodipodi:docname="single-view.svg">
<defs
id="defs6448">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 16 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="32 : 16 : 1"
inkscape:persp3d-origin="16 : 10.666667 : 1"
id="perspective6454" />
<inkscape:perspective
id="perspective6441"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.197802"
inkscape:cx="0.014720032"
inkscape:cy="16"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="1680"
inkscape:window-height="997"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="1" />
<metadata
id="metadata6451">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer"
transform="translate(0,-17)">
<rect
ry="0.5"
rx="0.49999979"
y="17.483809"
x="0.53483802"
height="15"
width="23"
id="rect5304"
style="fill:#626262;fill-opacity:1;stroke:#cccccc;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="22"
id="svg3273"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="New document 14">
<defs
id="defs3275">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3281" />
<inkscape:perspective
id="perspective3261"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="32.000004"
inkscape:cy="10.999997"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata3278">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-343,-521.36218)">
<g
id="g17454"
transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g
transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
id="g17460"
style="display:inline">
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 803.6322,115.48629 0,4.29495"
id="path17462"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 806.62805,115.48629 0,4.29495"
id="path17464"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 809.6239,115.48629 0,4.29495"
id="path17466"
inkscape:connector-curvature="0" />
</g>
<path
sodipodi:type="arc"
style="color:#000000;fill:none;stroke:#ffffff;stroke-width:1.96875012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="path18722"
sodipodi:cx="47.6875"
sodipodi:cy="11.5625"
sodipodi:rx="3.9375"
sodipodi:ry="3.9375"
d="m 51.625,11.5625 c 0,2.174621 -1.762879,3.9375 -3.9375,3.9375 -2.174621,0 -3.9375,-1.762879 -3.9375,-3.9375 0,-2.1746212 1.762879,-3.9375 3.9375,-3.9375 2.174621,0 3.9375,1.7628788 3.9375,3.9375 z"
transform="matrix(1.0158729,0,0,1.0158729,795.55556,72.25399)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="22"
id="svg3012"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="New document 6">
<defs
id="defs3014">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3020" />
<inkscape:perspective
id="perspective2997"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="32.000004"
inkscape:cy="10.999997"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata3017">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-343,-521.36218)">
<g
id="g17454"
transform="translate(-453,448.36218)"
style="display:inline">
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74.5"
x="-859.5"
height="19"
width="63.000004"
id="rect17456"
style="color:#000000;fill:none;stroke:#2e3436;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
<rect
transform="scale(-1,1)"
ry="4"
rx="4"
y="74"
x="-828"
height="20"
width="31"
id="rect17458"
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline" />
<g
transform="matrix(-1,0,0,1,1619.1239,-33.986291)"
id="g17460"
style="display:inline">
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1"
d="m 803.6322,115.48629 0,4.29495"
id="path17462"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 806.62805,115.48629 0,4.29495"
id="path17464"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline"
d="m 809.6239,115.48629 0,4.29495"
id="path17466"
inkscape:connector-curvature="0" />
</g>
<g
style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="text17468"
transform="translate(0.34375,0)">
<path
d="m 837.28518,80.750726 c 0.63282,6e-6 1.19566,0.123947 1.68852,0.371824 0.49284,0.247888 0.8807,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42431,1.649149 0,0.635748 -0.13853,1.200045 -0.41556,1.692892 -0.27706,0.489934 -0.66638,0.870507 -1.16797,1.141719 -0.5016,0.271213 -1.07756,0.406819 -1.72789,0.406819 -0.42869,0 -0.83551,-0.06562 -1.22045,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03674,-0.581795 -0.30329,-0.256631 -0.54534,-0.589085 -0.72615,-0.997363 -0.17789,-0.408276 -0.26684,-0.869045 -0.26683,-1.382311 -10e-6,-0.638658 0.13997,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06297,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40683,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41412,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38933,0.129779 -0.57305,0.240592 -0.18081,0.107907 -0.33974,0.242055 -0.47681,0.402445 -0.13706,0.160399 -0.24642,0.358705 -0.32808,0.594918 -0.0816,0.233306 -0.12248,0.491395 -0.12248,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622903 0.41702,0.408278 0.93758,0.612416 1.56166,0.612416 0.25954,0 0.51034,-0.04229 0.7524,-0.126858 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376198 0.20705,-0.166226 0.37328,-0.392236 0.49868,-0.678032 0.12539,-0.285792 0.18809,-0.610956 0.1881,-0.975492 -10e-6,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20415,-0.453475 -0.34995,-0.61679 -0.14291,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18599"
inkscape:connector-curvature="0" />
<path
d="m 843.5362,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10673,0 0,-6.216022 4.31754,0 0,1.014861 -3.21081,0"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18601"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
<path
d="m 849.71285,81.831203 0,1.17917 2.94834,0 0,1.014861 -2.94834,0 0,3.00713 -1.10672,0 0,-6.216022 4.31753,0 0,1.014861 -3.21081,0"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18603"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg3199"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="New document 11">
<defs
id="defs3201">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3207" />
<inkscape:perspective
id="perspective3187"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="32.500004"
inkscape:cy="10.999997"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata3204">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-342.5,-521.36218)">
<g
style="display:inline"
transform="translate(-453.5,448.36218)"
id="g16453">
<rect
style="color:#000000;fill:#204a87;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect16256-9-4"
width="63.000004"
height="19"
x="-859.5"
y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g
style="display:inline"
id="g16298-3-6"
transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
<path
inkscape:connector-curvature="0"
id="path16265-3-5"
d="m 803.6322,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path16265-0-2-0"
d="m 806.62805,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
id="path16265-8-7-1"
d="m 809.6239,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
<path
style="color:#000000;fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
d="m 16,27.9375 0,10.125"
id="path19232"
inkscape:connector-curvature="0"
transform="translate(796,51.00002)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

128
data/theme/toggle-on-us.svg Normal file
View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="22"
id="svg2857"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="New document 2">
<defs
id="defs2859">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective2865" />
<inkscape:perspective
id="perspective2843"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-69.642856"
inkscape:cy="42.428569"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="609"
inkscape:window-height="501"
inkscape:window-x="0"
inkscape:window-y="26"
inkscape:window-maximized="0" />
<metadata
id="metadata2862">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-444.64286,-781.36218)">
<g
style="display:inline"
transform="translate(-351.35714,708.36218)"
id="g16453">
<rect
style="color:#000000;fill:#204a87;fill-opacity:1;fill-rule:nonzero;stroke:#3465a4;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
id="rect16256-9-4"
width="63.000004"
height="19"
x="-859.5"
y="74.5"
rx="4"
ry="4"
transform="scale(-1,1)" />
<rect
style="fill:#000000;fill-opacity:1;stroke:#5f5f5f;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;display:inline"
id="rect16258-5-4"
width="31"
height="20"
x="-860"
y="74"
rx="4"
ry="4"
transform="scale(-1,1)" />
<g
style="display:inline"
id="g16298-3-6"
transform="matrix(-1,0,0,1,1651.1322,-33.986291)">
<path
inkscape:connector-curvature="0"
id="path16265-3-5"
d="m 803.6322,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path16265-0-2-0"
d="m 806.62805,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
<path
inkscape:connector-curvature="0"
id="path16265-8-7-1"
d="m 809.6239,115.48629 0,4.29495"
style="fill:none;stroke:#5f5f5f;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
</g>
<g
style="font-size:8.95877075px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:125%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="text42229-3-0">
<path
d="m 808.01473,80.573953 c 0.63283,6e-6 1.19567,0.123947 1.68852,0.371824 0.49284,0.247888 0.88071,0.609505 1.16359,1.084851 0.28287,0.472439 0.42431,1.022155 0.42432,1.649149 -10e-6,0.635748 -0.13853,1.200045 -0.41557,1.692892 -0.27705,0.489934 -0.66637,0.870506 -1.16796,1.141719 -0.50161,0.271212 -1.07757,0.406819 -1.72789,0.406819 -0.4287,0 -0.83552,-0.06562 -1.22046,-0.196848 -0.38495,-0.134148 -0.73053,-0.32808 -1.03673,-0.581795 -0.3033,-0.256631 -0.54535,-0.589085 -0.72615,-0.997363 -0.1779,-0.408276 -0.26684,-0.869045 -0.26684,-1.382311 0,-0.638658 0.13998,-1.200039 0.41994,-1.684144 0.27996,-0.487011 0.66782,-0.858835 1.16359,-1.115472 0.49576,-0.259541 1.06298,-0.389315 1.70164,-0.389321 m 0.57305,1.089225 c -0.20123,-0.05249 -0.40682,-0.07873 -0.61679,-0.07874 -0.20998,5e-6 -0.41411,0.02625 -0.61242,0.07874 -0.19831,0.04958 -0.38932,0.129779 -0.57304,0.240592 -0.18081,0.107907 -0.33975,0.242055 -0.47681,0.402445 -0.13707,0.160399 -0.24643,0.358705 -0.32808,0.594918 -0.0817,0.233305 -0.12249,0.491395 -0.12249,0.774269 0,0.67366 0.20851,1.214627 0.62554,1.622902 0.41703,0.408279 0.93758,0.612417 1.56166,0.612416 0.25955,10e-7 0.51035,-0.04228 0.7524,-0.126857 0.24496,-0.08457 0.47097,-0.20997 0.67803,-0.376199 0.20705,-0.166225 0.37328,-0.392236 0.49868,-0.678031 0.1254,-0.285792 0.1881,-0.610956 0.1881,-0.975492 0,-0.297455 -0.0437,-0.568668 -0.13123,-0.813638 -0.0875,-0.247878 -0.20414,-0.453475 -0.34995,-0.61679 -0.1429,-0.163307 -0.31059,-0.301829 -0.50306,-0.415568 -0.18956,-0.11373 -0.38641,-0.195385 -0.59054,-0.244967"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18606" />
<path
d="m 813.15903,80.639569 1.21608,0 3.4689,4.776844 0,-4.776844 1.10235,0 0,6.216022 -1.22921,0 -3.45577,-4.785594 0,4.785594 -1.10235,0 0,-6.216022"
style="line-height:125%;fill:#ffffff;fill-opacity:1;marker:none;font-family:Cantarell;-inkscape-font-specification:Cantarell Bold"
id="path18608" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="96" height="96" id="svg25070" version="1.1" inkscape:version="0.47 r22583" sodipodi:docname="dark-arrow-larger.svg">
<defs id="defs25072">
<inkscape:perspective sodipodi:type="inkscape:persp3d" inkscape:vp_x="0 : 24 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="48 : 24 : 1" inkscape:persp3d-origin="24 : 16 : 1" id="perspective25078"/>
<inkscape:perspective id="perspective24985" inkscape:persp3d-origin="0.5 : 0.33333333 : 1" inkscape:vp_z="1 : 0.5 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_x="0 : 0.5 : 1" sodipodi:type="inkscape:persp3d"/>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4034-0-4" id="linearGradient24957" gradientUnits="userSpaceOnUse" gradientTransform="translate(6)" x1="-86.552246" y1="185.439" x2="-83.37072" y2="197.31261"/>
<linearGradient inkscape:collect="always" id="linearGradient4034-0-4">
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4036-5-7"/>
<stop style="stop-color: rgb(186, 189, 182); stop-opacity: 1;" offset="1" id="stop4038-9-6"/>
</linearGradient>
<filter id="filter24765" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix24767" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix24769" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4632-1-3-9-3-2" id="linearGradient24955" gradientUnits="userSpaceOnUse" gradientTransform="translate(-5)" x1="-74.520325" y1="169.06032" x2="-74.520325" y2="205.94189"/>
<linearGradient id="linearGradient4632-1-3-9-3-2">
<stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="0" id="stop4634-1-8-3-9-0"/>
<stop id="stop4636-1-9-9-8-8" offset="0.0274937" style="stop-color: rgb(255, 255, 255); stop-opacity: 1;"/>
<stop id="stop4638-8-3-9-6-6" offset="0.274937" style="stop-color: rgb(242, 242, 242); stop-opacity: 1;"/>
<stop id="stop4640-8-5-7-8-9" offset="0.38707438" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4642-5-41-9-6-9" offset="0.66528589" style="stop-color: rgb(217, 218, 216); stop-opacity: 1;"/>
<stop id="stop4644-5-2-7-9-2" offset="0.76745707" style="stop-color: rgb(223, 224, 221); stop-opacity: 1;"/>
<stop style="stop-color: rgb(240, 240, 240); stop-opacity: 1;" offset="1" id="stop4646-3-2-3-7-3"/>
</linearGradient>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-1" id="radialGradient24959" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
<linearGradient id="linearGradient4869-4-1">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-2"/>
<stop id="stop4879-7-4" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4877-6-1" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-0"/>
</linearGradient>
<filter id="filter25011" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25013" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25015" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<radialGradient inkscape:collect="always" xlink:href="#linearGradient4869-4-0" id="radialGradient24961" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0075, 0, 0, 1.0075, -5.4544, -1.25141)" cx="-33.412369" cy="185.74171" fx="-33.412369" fy="185.74171" r="2.3554697"/>
<linearGradient id="linearGradient4869-4-0">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4871-6-8"/>
<stop id="stop4879-7-5" offset="0.31807542" style="stop-color: rgb(238, 238, 236); stop-opacity: 1;"/>
<stop id="stop4877-6-5" offset="0.74691135" style="stop-color: rgb(200, 201, 198); stop-opacity: 1;"/>
<stop style="stop-color: rgb(211, 215, 207); stop-opacity: 1;" offset="1" id="stop4873-1-4"/>
</linearGradient>
<filter id="filter25023" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25025" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25027" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941" id="linearGradient24963" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
<linearGradient inkscape:collect="always" id="linearGradient4941">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943"/>
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945"/>
</linearGradient>
<filter id="filter25033" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25035" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25037" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<linearGradient inkscape:collect="always" xlink:href="#linearGradient4941-7" id="linearGradient24965" gradientUnits="userSpaceOnUse" x1="-39.858727" y1="184.61784" x2="-38.244785" y2="188.84898"/>
<linearGradient inkscape:collect="always" id="linearGradient4941-7">
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop4943-2"/>
<stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop4945-5"/>
</linearGradient>
<filter id="filter25043" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25045" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25047" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<filter id="filter25049" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25051" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25053" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
<filter id="filter25055" inkscape:label="Invert" x="0" y="0" width="1" height="1" inkscape:menu="Color" inkscape:menu-tooltip="Invert colors" color-interpolation-filters="sRGB">
<feColorMatrix id="feColorMatrix25057" type="saturate" values="1" result="fbSourceGraphic"/>
<feColorMatrix id="feColorMatrix25059" in="fbSourceGraphic" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"/>
</filter>
</defs>
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="2.8284271" inkscape:cx="48.631638" inkscape:cy="57.536221" inkscape:current-layer="layer1" showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" inkscape:window-width="1200" inkscape:window-height="851" inkscape:window-x="0" inkscape:window-y="52" inkscape:window-maximized="0"/>
<metadata id="metadata25075">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer" transform="translate(0, 48)">
<g id="g4030-1-8" transform="matrix(2, 0, 0, 2, 193.25, -374.967)" style="stroke: rgb(0, 0, 0); display: inline; stroke-opacity: 1;">
<path sodipodi:nodetypes="ccc" id="path3165-7-3" d="m -72.5,173.5 -14,14 14,14" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 7; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;"/>
</g>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 185.28, -623.176)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 0.523439; visibility: visible; display: inline;" id="path4050-2-7-9-4-8" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(3.34328, 0, 0, 3.34328, 207.28, -623.176)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 166.846, -534.143)"/>
<path sodipodi:type="arc" style="overflow: visible; marker: none; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 0.697921; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-opacity: 1; stroke-dasharray: none; stroke-dashoffset: 0pt; visibility: visible; display: inline;" id="path4050-2-7-9-4-0-9" sodipodi:cx="-38.59375" sodipodi:cy="186.40625" sodipodi:rx="2.09375" sodipodi:ry="2.09375" d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z" transform="matrix(2.86565, 0, 0, 2.86565, 188.846, -534.143)"/>
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; opacity: 0.35; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 317.06251,365.96875 c -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 l -16.125,16.125 16.125,16.125 c 1.11265,1.11265 3.13735,1.11265 4.25,0 1.11265,-1.11264 1.11265,-3.13735 0,-4.25 l -11.875,-11.875 11.875,-11.875 c 0.86584,-0.83655 1.1475,-2.22114 0.6773,-3.32947 -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 z" id="path3165-7-3-1" sodipodi:nodetypes="ccccscccsc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
<path style="overflow: visible; marker: none; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; text-indent: 0pt; text-align: start; text-decoration: none; line-height: normal; letter-spacing: normal; word-spacing: normal; text-transform: none; direction: ltr; text-anchor: start; color: rgb(0, 0, 0); fill: none; stroke: rgb(0, 0, 0); stroke-width: 1; stroke-linecap: round; stroke-miterlimit: 4; stroke-dasharray: none; visibility: visible; display: inline; font-family: Bitstream Vera Sans; stroke-opacity: 1;" d="m 320.08435,397.03059 c 0.007,-0.79449 -0.27079,-1.59203 -0.83434,-2.15559 L 307.37501,383 m 12.5523,-15.20447 c -0.47021,-1.10834 -1.66156,-1.86802 -2.8648,-1.82678 -0.76948,0.0224 -1.52555,0.35464 -2.0625,0.90625 L 298.87501,383" id="path3165-7-3-1-9" sodipodi:nodetypes="ccccccc" transform="matrix(2, 0, 0, 2, -586, -765.967)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,331 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="96"
height="96"
id="svg25070">
<defs
id="defs25072">
<linearGradient
x1="-86.552246"
y1="185.439"
x2="-83.37072"
y2="197.31261"
id="linearGradient24957"
xlink:href="#linearGradient4034-0-4"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6,0)" />
<linearGradient
id="linearGradient4034-0-4">
<stop
id="stop4036-5-7"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4038-9-6"
style="stop-color:#babdb6;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter24765">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix24767" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix24769" />
</filter>
<linearGradient
x1="-74.520325"
y1="169.06032"
x2="-74.520325"
y2="205.94189"
id="linearGradient24955"
xlink:href="#linearGradient4632-1-3-9-3-2"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-5,0)" />
<linearGradient
id="linearGradient4632-1-3-9-3-2">
<stop
id="stop4634-1-8-3-9-0"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0" />
<stop
id="stop4636-1-9-9-8-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0.0274937" />
<stop
id="stop4638-8-3-9-6-6"
style="stop-color:#f2f2f2;stop-opacity:1"
offset="0.274937" />
<stop
id="stop4640-8-5-7-8-9"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.38707438" />
<stop
id="stop4642-5-41-9-6-9"
style="stop-color:#d9dad8;stop-opacity:1"
offset="0.66528589" />
<stop
id="stop4644-5-2-7-9-2"
style="stop-color:#dfe0dd;stop-opacity:1"
offset="0.76745707" />
<stop
id="stop4646-3-2-3-7-3"
style="stop-color:#f0f0f0;stop-opacity:1"
offset="1" />
</linearGradient>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24959"
xlink:href="#linearGradient4869-4-1"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-1">
<stop
id="stop4871-6-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-4"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-1"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-0"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25011">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25013" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25015" />
</filter>
<radialGradient
cx="-33.412369"
cy="185.74171"
r="2.3554697"
fx="-33.412369"
fy="185.74171"
id="radialGradient24961"
xlink:href="#linearGradient4869-4-0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0075,0,0,1.0075,-5.4544,-1.25141)" />
<linearGradient
id="linearGradient4869-4-0">
<stop
id="stop4871-6-8"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4879-7-5"
style="stop-color:#eeeeec;stop-opacity:1"
offset="0.31807542" />
<stop
id="stop4877-6-5"
style="stop-color:#c8c9c6;stop-opacity:1"
offset="0.74691135" />
<stop
id="stop4873-1-4"
style="stop-color:#d3d7cf;stop-opacity:1"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25023">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25025" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25027" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24963"
xlink:href="#linearGradient4941"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941">
<stop
id="stop4943"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25033">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25035" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25037" />
</filter>
<linearGradient
x1="-39.858727"
y1="184.61784"
x2="-38.244785"
y2="188.84898"
id="linearGradient24965"
xlink:href="#linearGradient4941-7"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient4941-7">
<stop
id="stop4943-2"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop4945-5"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25043">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25045" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25047" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25049">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25051" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25053" />
</filter>
<filter
x="0"
y="0"
width="1"
height="1"
color-interpolation-filters="sRGB"
id="filter25055">
<feColorMatrix
result="fbSourceGraphic"
values="1"
type="saturate"
id="feColorMatrix25057" />
<feColorMatrix
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
in="fbSourceGraphic"
id="feColorMatrix25059" />
</filter>
</defs>
<g
transform="translate(0,48)"
id="layer1">
<g
transform="matrix(-2,0,0,2,-97.2497,-374.967)"
id="g4030-1-8"
style="stroke:#000000;stroke-opacity:1;display:inline">
<path
d="m -72.5,173.5 -14,14 14,14"
id="path3165-7-3"
style="color:#000000;fill:none;stroke:#000000;stroke-width:7;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
</g>
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-89.2797,-623.176)"
id="path4050-2-7-9-4"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-3.34328,0,0,3.34328,-111.2797,-623.176)"
id="path4050-2-7-9-4-8"
style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52343899;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-70.8457,-534.143)"
id="path4050-2-7-9-4-0"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m -36.5,186.40625 a 2.09375,2.09375 0 1 1 -4.1875,0 2.09375,2.09375 0 1 1 4.1875,0 z"
transform="matrix(-2.86565,0,0,2.86565,-92.8457,-534.143)"
id="path4050-2-7-9-4-0-9"
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.69792098;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" />
<path
d="m 47.87528,-34.0295 c 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25 -32.25,32.25 c -2.2253,2.2253 -6.2747,2.2253 -8.5,0 -2.2253,-2.22528 -2.2253,-6.2747 0,-8.5 l 23.75,-23.75 -23.75,-23.75 c -1.73168,-1.6731 -2.295,-4.44228 -1.3546,-6.65894 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 z"
id="path3165-7-3-1"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;opacity:0.35;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
<path
d="m 41.8316,28.09418 c -0.014,-1.58898 0.54158,-3.18406 1.66868,-4.31118 l 23.75,-23.75 m -25.1046,-30.40894 c 0.94042,-2.21668 3.32312,-3.73604 5.7296,-3.65356 1.53896,0.0448 3.0511,0.70928 4.125,1.8125 l 32.25,32.25"
id="path3165-7-3-1-9"
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0pt;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;text-anchor:start;color:#000000;fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;font-family:Bitstream Vera Sans" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1 +1,52 @@
SUBDIRS = misc ui
jsdir = $(pkgdatadir)/js
nobase_dist_js_DATA = \
misc/docInfo.js \
misc/fileUtils.js \
misc/format.js \
misc/gnomeSession.js \
misc/params.js \
misc/telepathy.js \
perf/core.js \
prefs/clockPreferences.js \
ui/altTab.js \
ui/appDisplay.js \
ui/appFavorites.js \
ui/boxpointer.js \
ui/calendar.js \
ui/chrome.js \
ui/dash.js \
ui/dnd.js \
ui/docDisplay.js \
ui/environment.js \
ui/extensionSystem.js \
ui/genericDisplay.js \
ui/iconGrid.js \
ui/lightbox.js \
ui/link.js \
ui/lookingGlass.js \
ui/magnifier.js \
ui/magnifierDBus.js \
ui/main.js \
ui/messageTray.js \
ui/notificationDaemon.js \
ui/overview.js \
ui/panel.js \
ui/panelMenu.js \
ui/placeDisplay.js \
ui/popupMenu.js \
ui/runDialog.js \
ui/scripting.js \
ui/search.js \
ui/shellDBus.js \
ui/statusIconDispatcher.js \
ui/statusMenu.js \
ui/status/accessibility.js \
ui/telepathyClient.js \
ui/tweener.js \
ui/windowAttentionHandler.js \
ui/windowManager.js \
ui/workspace.js \
ui/workspacesView.js \
ui/workspaceSwitcherPopup.js

View File

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

View File

@ -1,13 +1,10 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Main = imports.ui.main;
const Search = imports.ui.search;
const THUMBNAIL_ICON_MARGIN = 2;
@ -17,69 +14,40 @@ function DocInfo(recentInfo) {
DocInfo.prototype = {
_init : function(recentInfo) {
this._recentInfo = recentInfo;
this.recentInfo = recentInfo;
// We actually used get_modified() instead of get_visited()
// here, as GtkRecentInfo doesn't updated get_visited()
// correctly. See http://bugzilla.gnome.org/show_bug.cgi?id=567094
this.timestamp = recentInfo.get_modified().getTime() / 1000;
this.timestamp = recentInfo.get_modified();
this.name = recentInfo.get_display_name();
this._lowerName = this.name.toLowerCase();
this.uri = recentInfo.get_uri();
this.mimeType = recentInfo.get_mime_type();
},
createIcon : function(size) {
return Shell.TextureCache.get_default().load_recent_thumbnail(size, this._recentInfo);
return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo);
},
launch : function() {
// While using Gio.app_info_launch_default_for_uri() would be
// shorter in terms of lines of code, we are not doing so
// because that would duplicate the work of retrieving the
// mime type.
let appInfo = Gio.app_info_get_default_for_type(this.mimeType, true);
if (appInfo != null) {
appInfo.launch_uris([this.uri], Main.createAppLaunchContext());
} else {
log("Failed to get default application info for mime type " + this.mimeType +
". Will try to use the last application that registered the document.");
let appName = this._recentInfo.last_application();
let [success, appExec, count, time] = this._recentInfo.get_application_info(appName);
if (success) {
log("Will open a document with the following command: " + appExec);
// TODO: Change this once better support for creating
// GAppInfo is added to GtkRecentInfo, as right now
// this relies on the fact that the file uri is
// already a part of appExec, so we don't supply any
// files to appInfo.launch().
// The 'command line' passed to
// create_from_command_line is allowed to contain
// '%<something>' macros that are expanded to file
// name / icon name, etc, so we need to escape % as %%
appExec = appExec.replace(/%/g, "%%");
let appInfo = Gio.app_info_create_from_commandline(appExec, null, 0, null);
// The point of passing an app launch context to
// launch() is mostly to get startup notification and
// associated benefits like the app appearing on the
// right desktop; but it doesn't really work for now
// because with the way we create the appInfo we
// aren't reading the application's desktop file, and
// thus don't find the StartupNotify=true in it. So,
// despite passing the app launch context, no startup
// notification occurs.
appInfo.launch([], Main.createAppLaunchContext());
} else {
log("Failed to get application info for " + this.uri);
}
}
Shell.DocSystem.get_default().open(this.recentInfo);
},
exists : function() {
return this._recentInfo.exists();
matchTerms: function(terms) {
let mtype = Search.MatchType.NONE;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
let idx = this._lowerName.indexOf(term);
if (idx == 0) {
mtype = Search.MatchType.PREFIX;
} else if (idx > 0) {
if (mtype == Search.MatchType.NONE)
mtype = Search.MatchType.SUBSTRING;
} else {
return Search.MatchType.NONE;
}
}
return mtype;
}
};
@ -91,51 +59,83 @@ function getDocManager() {
return docManagerInstance;
}
/**
* DocManager wraps the DocSystem, primarily to expose DocInfo objects
* which conform to the GenericDisplay item API.
*/
function DocManager() {
this._init();
}
DocManager.prototype = {
_init: function() {
this._recentManager = Gtk.RecentManager.get_default();
this._items = {};
this._recentManager.connect('changed', Lang.bind(this, function(recentManager) {
this._reload();
this.emit('changed');
}));
this._docSystem = Shell.DocSystem.get_default();
this._infosByTimestamp = [];
this._infosByUri = {};
this._docSystem.connect('changed', Lang.bind(this, this._reload));
this._reload();
},
_reload: function() {
let docs = this._recentManager.get_items();
let newItems = {};
let docs = this._docSystem.get_all();
this._infosByTimestamp = [];
this._infosByUri = {};
for (let i = 0; i < docs.length; i++) {
let recentInfo = docs[i];
if (!recentInfo.exists())
continue;
let docInfo = new DocInfo(recentInfo);
// we use GtkRecentInfo URI as an item Id
newItems[docInfo.uri] = docInfo;
this._infosByTimestamp.push(docInfo);
this._infosByUri[docInfo.uri] = docInfo;
}
let deleted = {};
for (var uri in this._items) {
if (!(uri in newItems))
deleted[uri] = this._items[uri];
}
/* If we'd cached any thumbnail references that no longer exist,
dump them here */
let texCache = Shell.TextureCache.get_default();
for (var uri in deleted) {
texCache.evict_recent_thumbnail(this._items[uri]);
}
this._items = newItems;
this.emit('changed');
},
getItems: function() {
return this._items;
getTimestampOrderedInfos: function() {
return this._infosByTimestamp;
},
getInfosByUri: function() {
return this._infosByUri;
},
lookupByUri: function(uri) {
return this._infosByUri[uri];
},
queueExistenceCheck: function(count) {
return this._docSystem.queue_existence_check(count);
},
_searchDocs: function(items, terms) {
let multiplePrefixMatches = [];
let prefixMatches = [];
let multipleSubtringMatches = [];
let substringMatches = [];
for (let i = 0; i < items.length; i++) {
let item = items[i];
let mtype = item.matchTerms(terms);
if (mtype == Search.MatchType.MULTIPLE_PREFIX)
multiplePrefixMatches.push(item.uri);
else if (mtype == Search.MatchType.PREFIX)
prefixMatches.push(item.uri);
else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING)
multipleSubtringMatches.push(item.uri);
else if (mtype == Search.MatchType.SUBSTRING)
substringMatches.push(item.uri);
}
return multiplePrefixMatches.concat(prefixMatches.concat(multipleSubtringMatches.concat(substringMatches)));
},
initialSearch: function(terms) {
return this._searchDocs(this._infosByTimestamp, terms);
},
subsearch: function(previousResults, terms) {
return this._searchDocs(previousResults.map(Lang.bind(this,
function(url) {
return this._infosByUri[url];
})), terms);
}
}
};
Signals.addSignalMethods(DocManager.prototype);

22
js/misc/fileUtils.js Normal file
View File

@ -0,0 +1,22 @@
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
function listDirAsync(file, callback) {
let allFiles = [];
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME,
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_LOW, null, function (obj, res) {
let enumerator = obj.enumerate_children_finish(res);
function onNextFileComplete(obj, res) {
let files = obj.next_files_finish(res);
if (files.length) {
allFiles = allFiles.concat(files);
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
} else {
enumerator.close(null);
callback(allFiles);
}
}
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
});
}

60
js/misc/format.js Normal file
View File

@ -0,0 +1,60 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* This function is intended to extend the String object and provide
* an String.format API for string formatting.
* It has to be set up using String.prototype.format = Format.format;
* Usage:
* "somestring %s %d".format('hello', 5);
* It supports %s, %d, %x and %f, for %f it also support precisions like
* "%.2f".format(1.526). All specifiers can be prefixed with a minimum
* field width, e.g. "%5s".format("foo"). Unless the width is prefixed
* with '0', the formatted string will be padded with spaces.
*/
function format() {
let str = this;
let i = 0;
let args = arguments;
return str.replace(/%([0-9]+)?(?:\.([0-9]+))?(.)/g, function (str, widthGroup, precisionGroup, genericGroup) {
if (precisionGroup != '' && genericGroup != 'f')
throw new Error("Precision can only be specified for 'f'");
let fillChar = (widthGroup[0] == '0') ? '0' : ' ';
let width = parseInt(widthGroup, 10) || 0;
function fillWidth(s, c, w) {
let fill = '';
for (let i = 0; i < w; i++)
fill += c;
return fill.substr(s.length) + s;
}
let s = '';
switch (genericGroup) {
case '%':
return '%';
break;
case 's':
s = args[i++].toString();
break;
case 'd':
s = parseInt(args[i++]).toString();
break;
case 'x':
s = parseInt(args[i++]).toString(16);
break;
case 'f':
if (precisionGroup == '')
s = parseFloat(args[i++]).toString();
else
s = parseFloat(args[i++]).toFixed(parseInt(precisionGroup));
break;
default:
throw new Error('Unsupported conversion character %' + genericGroup);
}
return fillWidth(s, fillChar, width);
});
}

45
js/misc/gnomeSession.js Normal file
View File

@ -0,0 +1,45 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const Lang = imports.lang;
const PresenceIface = {
name: 'org.gnome.SessionManager.Presence',
methods: [{ name: 'SetStatus',
inSignature: 'u' }],
properties: [{ name: 'status',
signature: 'u',
access: 'readwrite' }],
signals: [{ name: 'StatusChanged',
inSignature: 'u' }]
};
const PresenceStatus = {
AVAILABLE: 0,
INVISIBLE: 1,
BUSY: 2,
IDLE: 3
};
function Presence() {
this._init();
}
Presence.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
},
getStatus: function(callback) {
this.GetRemote('status', Lang.bind(this,
function(status, ex) {
if (!ex)
callback(this, status);
}));
},
setStatus: function(status) {
this.SetStatusRemote(status);
}
};
DBus.proxifyPrototype(Presence.prototype, PresenceIface);

35
js/misc/params.js Normal file
View File

@ -0,0 +1,35 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// parse:
// @params: caller-provided parameter object, or %null
// @defaults: function-provided defaults object
// @allowExtras: whether or not to allow properties not in @default
//
// Examines @params and fills in default values from @defaults for
// any properties in @defaults that don't appear in @params. If
// @allowExtras is not %true, it will throw an error if @params
// contains any properties that aren't in @defaults.
//
// If @params is %null, this returns the values from @defaults.
//
// Return value: a new object, containing the merged parameters from
// @params and @defaults
function parse(params, defaults, allowExtras) {
let ret = {}, prop;
if (!params)
params = {};
for (prop in params) {
if (!(prop in defaults) && !allowExtras)
throw new Error('Unrecognized parameter "' + prop + '"');
ret[prop] = params[prop];
}
for (prop in defaults) {
if (!(prop in params))
ret[prop] = defaults[prop];
}
return ret;
}

372
js/misc/telepathy.js Normal file
View File

@ -0,0 +1,372 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
// D-Bus utils; should eventually move to gjs.
// https://bugzilla.gnome.org/show_bug.cgi?id=610859
function makeProxyClass(iface) {
let constructor = function() { this._init.apply(this, arguments); };
constructor.prototype._init = function(bus, name, path) {
bus.proxifyObject(this, name, path);
};
DBus.proxifyPrototype(constructor.prototype, iface);
return constructor;
}
function nameToPath(name) {
return '/' + name.replace(/\./g, '/');
};
function pathToName(path) {
if (path[0] != '/')
throw new Error('not a D-Bus path: ' + path);
return path.substr(1).replace(/\//g, '.');
};
// This is tp_escape_as_identifier() from telepathy-glib
function escapeAsIdentifier(name) {
if (!name)
return '_';
// first char is replaced with _XX if it's non-alpha,
// later chars are replaced with _XX if they're non-alphanumeric
if (name.length == 1) {
return name.replace(/[^a-zA-Z]/, _hexEscape);
} else {
return (name[0].replace(/[^a-zA-Z]/, _hexEscape) +
name.substring(1).replace(/[^a-zA-Z0-9]/g, _hexEscape));
}
}
function _hexEscape(ch) {
return '_' + ch.charCodeAt(0).toString(16);
}
// Telepathy D-Bus interface definitions. Note that most of these are
// incomplete, and only cover the methods/properties/signals that
// we're currently using.
const TELEPATHY = 'org.freedesktop.Telepathy';
const CLIENT_NAME = TELEPATHY + '.Client';
const ClientIface = {
name: CLIENT_NAME,
properties: [
{ name: 'Interfaces',
signature: 'as',
access: 'read' }
]
};
const CLIENT_APPROVER_NAME = TELEPATHY + '.Client.Approver';
const ClientApproverIface = {
name: CLIENT_APPROVER_NAME,
methods: [
{ name: 'AddDispatchOperation',
inSignature: 'a(oa{sv})oa{sv}',
outSignature: '' }
],
properties: [
{ name: 'ApproverChannelFilter',
signature: 'aa{sv}',
access: 'read' }
]
};
const CLIENT_HANDLER_NAME = TELEPATHY + '.Client.Handler';
const ClientHandlerIface = {
name: CLIENT_HANDLER_NAME,
methods: [
{ name: 'HandleChannels',
inSignature: 'ooa(oa{sv})aota{sv}',
outSignature: '' }
],
properties: [
{ name: 'HandlerChannelFilter',
signature: 'aa{sv}',
access: 'read' }
]
};
const CLIENT_OBSERVER_NAME = TELEPATHY + '.Client.Observer';
const ClientObserverIface = {
name: CLIENT_OBSERVER_NAME,
methods: [
{ name: 'ObserveChannels',
inSignature: 'ooa(oa{sv})oaoa{sv}',
outSignature: '' }
],
properties: [
{ name: 'ObserverChannelFilter',
signature: 'aa{sv}',
access: 'read' }
]
};
const CHANNEL_DISPATCH_OPERATION_NAME = TELEPATHY + '.ChannelDispatchOperation';
const ChannelDispatchOperationIface = {
name: CHANNEL_DISPATCH_OPERATION_NAME,
methods: [
{ name: 'HandleWith',
inSignature: 's',
outSignature: '' },
{ name: 'Claim',
inSignature: '',
outSignature: '' }
]
};
let ChannelDispatchOperation = makeProxyClass(ChannelDispatchOperationIface);
const CONNECTION_NAME = TELEPATHY + '.Connection';
const ConnectionIface = {
name: CONNECTION_NAME,
signals: [
{ name: 'StatusChanged',
inSignature: 'uu' }
]
};
let Connection = makeProxyClass(ConnectionIface);
const ConnectionStatus = {
CONNECTED: 0,
CONNECTING: 1,
DISCONNECTED: 2
};
const CONNECTION_ALIASING_NAME = CONNECTION_NAME + '.Interface.Aliasing';
const ConnectionAliasingIface = {
name: CONNECTION_ALIASING_NAME,
methods: [
{ name: 'RequestAliases',
inSignature: 'au',
outSignature: 'as'
}
],
signals: [
{ name: 'AliasesChanged',
inSignature: 'a(us)' }
]
};
let ConnectionAliasing = makeProxyClass(ConnectionAliasingIface);
const CONNECTION_AVATARS_NAME = CONNECTION_NAME + '.Interface.Avatars';
const ConnectionAvatarsIface = {
name: CONNECTION_AVATARS_NAME,
methods: [
{ name: 'GetKnownAvatarTokens',
inSignature: 'au',
outSignature: 'a{us}'
},
{ name: 'RequestAvatars',
inSignature: 'au',
outSignature: ''
}
],
signals: [
{ name: 'AvatarRetrieved',
inSignature: 'usays'
},
{ name: 'AvatarUpdated',
inSignature: 'us'
}
]
};
let ConnectionAvatars = makeProxyClass(ConnectionAvatarsIface);
const CONNECTION_CONTACTS_NAME = CONNECTION_NAME + '.Interface.Contacts';
const ConnectionContactsIface = {
name: CONNECTION_CONTACTS_NAME,
methods: [
{ name: 'GetContactAttributes',
inSignature: 'auasb',
outSignature: 'a{ua{sv}}'
}
]
};
let ConnectionContacts = makeProxyClass(ConnectionContactsIface);
const CONNECTION_REQUESTS_NAME = CONNECTION_NAME + '.Interface.Requests';
const ConnectionRequestsIface = {
name: CONNECTION_REQUESTS_NAME,
methods: [
{ name: 'CreateChannel',
inSignature: 'a{sv}',
outSignature: 'oa{sv}'
},
{ name: 'EnsureChannel',
inSignature: 'a{sv}',
outSignature: 'boa{sv}'
}
],
properties: [
{ name: 'Channels',
signature: 'a(oa{sv})',
access: 'read' }
],
signals: [
{ name: 'NewChannels',
inSignature: 'a(oa{sv})'
},
{ name: 'ChannelClosed',
inSignature: 'o'
}
]
};
let ConnectionRequests = makeProxyClass(ConnectionRequestsIface);
const CONNECTION_SIMPLE_PRESENCE_NAME = CONNECTION_NAME + '.Interface.SimplePresence';
const ConnectionSimplePresenceIface = {
name: CONNECTION_SIMPLE_PRESENCE_NAME,
methods: [
{ name: 'SetPresence',
inSignature: 'ss'
},
{ name: 'GetPresences',
inSignature: 'au',
outSignature: 'a{u(uss)}'
}
],
signals: [
{ name: 'PresencesChanged',
inSignature: 'a{u(uss)}' }
]
};
let ConnectionSimplePresence = makeProxyClass(ConnectionSimplePresenceIface);
const ConnectionPresenceType = {
UNSET: 0,
OFFLINE: 1,
AVAILABLE: 2,
AWAY: 3,
EXTENDED_AWAY: 4,
HIDDEN: 5,
BUSY: 6,
UNKNOWN: 7,
ERROR: 8
};
const HandleType = {
NONE: 0,
CONTACT: 1,
ROOM: 2,
LIST: 3,
GROUP: 4
};
const CHANNEL_NAME = TELEPATHY + '.Channel';
const ChannelIface = {
name: CHANNEL_NAME,
signals: [
{ name: 'Closed',
inSignature: '' }
]
};
let Channel = makeProxyClass(ChannelIface);
const CHANNEL_TEXT_NAME = CHANNEL_NAME + '.Type.Text';
const ChannelTextIface = {
name: CHANNEL_TEXT_NAME,
methods: [
{ name: 'ListPendingMessages',
inSignature: 'b',
outSignature: 'a(uuuuus)'
},
{ name: 'AcknowledgePendingMessages',
inSignature: 'au',
outSignature: ''
},
{ name: 'Send',
inSignature: 'us',
outSignature: ''
}
],
signals: [
{ name: 'Received',
inSignature: 'uuuuus' }
]
};
let ChannelText = makeProxyClass(ChannelTextIface);
const ChannelTextMessageType = {
NORMAL: 0,
ACTION: 1,
NOTICE: 2,
AUTO_REPLY: 3,
DELIVERY_REPORT: 4
};
const CHANNEL_CONTACT_LIST_NAME = CHANNEL_NAME + '.Type.ContactList';
// There is no interface associated with ContactList; it's just a
// special kind of Channel.Interface.Group
const CHANNEL_GROUP_NAME = CHANNEL_NAME + '.Interface.Group';
const ChannelGroupIface = {
name: CHANNEL_GROUP_NAME,
properties: [
{ name: 'Members',
signature: 'au',
access: 'read' }
],
signals: [
{ name: 'MembersChanged',
inSignature: 'sauauauauuu' }
]
};
let ChannelGroup = makeProxyClass(ChannelGroupIface);
const ACCOUNT_MANAGER_NAME = TELEPATHY + '.AccountManager';
const AccountManagerIface = {
name: ACCOUNT_MANAGER_NAME,
properties: [
{ name: 'ValidAccounts',
signature: 'ao',
access: 'read' }
],
signals: [
{ name: 'AccountValidityChanged',
inSignature: 'ob' }
]
};
let AccountManager = makeProxyClass(AccountManagerIface);
const ACCOUNT_NAME = TELEPATHY + '.Account';
const AccountIface = {
name: ACCOUNT_NAME,
properties: [
{ name: 'Connection',
signature: 'o',
access: 'read' }
]
};
let Account = makeProxyClass(AccountIface);
const CHANNEL_DISPATCHER_NAME = TELEPATHY + '.ChannelDispatcher';
const ChannelDispatcherIface = {
name: CHANNEL_DISPATCHER_NAME,
methods: [
{ name: 'EnsureChannel',
inSignature: 'oa{sv}xs',
outSignature: 'o' }
]
};
let ChannelDispatcher = makeProxyClass(ChannelDispatcherIface);
const CHANNEL_REQUEST_NAME = TELEPATHY + '.ChannelRequest';
const ChannelRequestIface = {
name: CHANNEL_REQUEST_NAME,
methods: [
{ name: 'Proceed',
inSignature: '',
outSignature: '' }
],
signals: [
{ name: 'Failed',
signature: 'ss' },
{ name: 'Succeeded',
signature: '' }
]
};
let ChannelRequest = makeProxyClass(ChannelRequestIface);

140
js/perf/core.js Normal file
View File

@ -0,0 +1,140 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
// This performance script measure the most important (core) performance
// metrics for the shell. By looking at the output metrics of this script
// someone should be able to get an idea of how well the shell is performing
// on a particular system.
let METRICS = {
overviewLatencyFirst:
{ description: "Time to first frame after triggering overview, first time",
units: "us" },
overviewFpsFirst:
{ description: "Frame rate when going to the overview, first time",
units: "frames / s" },
overviewLatencySubsequent:
{ description: "Time to first frame after triggering overview, second time",
units: "us"},
overviewFpsSubsequent:
{ description: "Frames rate when going to the overview, second time",
units: "frames / s" },
usedAfterOverview:
{ description: "Malloc'ed bytes after the overview is shown once",
units: "B" },
leakedAfterOverview:
{ description: "Additional malloc'ed bytes the second time the overview is shown",
units: "B" }
};
function run() {
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
Main.overview.connect('shown', function() {
Scripting.scriptEvent('overviewShowDone');
});
yield Scripting.sleep(1000);
yield Scripting.waitLeisure();
for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
yield Scripting.waitLeisure();
Main.overview.hide();
yield Scripting.waitLeisure();
global.gc();
yield Scripting.sleep(1000);
Scripting.collectStatistics();
Scripting.scriptEvent('afterShowHide');
}
}
let showingOverview = false;
let finishedShowingOverview = false;
let overviewShowStart;
let overviewFrames;
let overviewLatency;
let mallocUsedSize = 0;
let overviewShowCount = 0;
let firstOverviewUsedSize;
let haveSwapComplete = false;
function script_overviewShowStart(time) {
showingOverview = true;
finishedShowingOverview = false;
overviewShowStart = time;
overviewFrames = 0;
}
function script_overviewShowDone(time) {
// We've set up the state at the end of the zoom out, but we
// need to wait for one more frame to paint before we count
// ourselves as done.
finishedShowingOverview = true;
}
function script_afterShowHide(time) {
if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize;
} else {
METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
}
}
function malloc_usedSize(time, bytes) {
mallocUsedSize = bytes;
}
function _frameDone(time) {
if (showingOverview) {
if (overviewFrames == 0)
overviewLatency = time - overviewShowStart;
overviewFrames++;
}
if (finishedShowingOverview) {
showingOverview = false;
finishedShowingOverview = false;
overviewShowCount++;
let dt = (time - (overviewShowStart + overviewLatency)) / 1000000;
// If we see a start frame and an end frame, that would
// be 1 frame for a FPS computation, hence the '- 1'
let fps = (overviewFrames - 1) / dt;
if (overviewShowCount == 1) {
METRICS.overviewLatencyFirst.value = overviewLatency;
METRICS.overviewFpsFirst.value = fps;
} else {
METRICS.overviewLatencySubsequent.value = overviewLatency;
METRICS.overviewFpsSubsequent.value = fps;
}
}
}
function glx_swapComplete(time, swapTime) {
haveSwapComplete = true;
_frameDone(swapTime);
}
function clutter_stagePaintDone(time) {
// If we aren't receiving GLXBufferSwapComplete events, then we approximate
// the time the user sees a frame with the time we finished doing drawing
// commands for the frame. This doesn't take into account the time for
// the GPU to finish painting, and the time for waiting for the buffer
// swap, but if this are uniform - every frame takes the same time to draw -
// then it won't upset our FPS calculation, though the latency value
// will be slightly too low.
if (!haveSwapComplete)
_frameDone(time);
}

View File

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

View File

@ -1,27 +0,0 @@
jsuidir = $(pkgdatadir)/js/ui
dist_jsui_DATA = \
altTab.js \
appDisplay.js \
appIcon.js \
button.js \
chrome.js \
dash.js \
dnd.js \
docDisplay.js \
genericDisplay.js \
lightbox.js \
link.js \
lookingGlass.js \
main.js \
overview.js \
panel.js \
places.js \
runDialog.js \
shellDBus.js \
sidebar.js \
tweener.js \
widget.js \
widgetBox.js \
windowManager.js \
workspaces.js

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

120
js/ui/appFavorites.js Normal file
View File

@ -0,0 +1,120 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
function AppFavorites() {
this._init();
}
AppFavorites.prototype = {
FAVORITE_APPS_KEY: 'favorite-apps',
_init: function() {
this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, Lang.bind(this, this._onFavsChanged));
this._reload();
},
_onFavsChanged: function() {
this._reload();
this.emit('changed');
},
_reload: function() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) {
return appSys.get_app(id);
}).filter(function (app) {
return app != null;
});
this._favorites = {};
for (let i = 0; i < apps.length; i++) {
let app = apps[i];
this._favorites[app.get_id()] = app;
}
},
_getIds: function() {
let ret = [];
for (let id in this._favorites)
ret.push(id);
return ret;
},
getFavoriteMap: function() {
return this._favorites;
},
getFavorites: function() {
let ret = [];
for (let id in this._favorites)
ret.push(this._favorites[id]);
return ret;
},
isFavorite: function(appId) {
return appId in this._favorites;
},
_addFavorite: function(appId) {
if (appId in this._favorites)
return false;
let app = Shell.AppSystem.get_default().get_app(appId);
if (!app)
return false;
let ids = this._getIds();
ids.push(appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
this._favorites[appId] = app;
return true;
},
addFavorite: function(appId) {
if (!this._addFavorite(appId))
return;
let app = Shell.AppSystem.get_default().get_app(appId);
Main.overview.infoBar.setMessage(_("%s has been added to your favorites.").format(app.get_name()), Lang.bind(this, function () {
this._removeFavorite(appId);
}));
},
_removeFavorite: function(appId) {
if (!appId in this._favorites)
return false;
let ids = this._getIds().filter(function (id) { return id != appId; });
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
return true;
},
removeFavorite: function(appId) {
let app = this._favorites[appId];
if (!this._removeFavorite(appId))
return;
Main.overview.infoBar.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
Lang.bind(this, function () {
this._addFavorite(appId);
}));
}
};
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;
function getAppFavorites() {
if (appFavoritesInstance == null)
appFavoritesInstance = new AppFavorites();
return appFavoritesInstance;
}

View File

@ -1,572 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Workspaces = imports.ui.workspaces;
const GLOW_COLOR = new Clutter.Color();
GLOW_COLOR.from_pixel(0x4f6ba4ff);
const GLOW_PADDING_HORIZONTAL = 3;
const GLOW_PADDING_VERTICAL = 3;
const APPICON_ICON_SIZE = 48;
const APPICON_PADDING = 1;
const APPICON_BORDER_WIDTH = 1;
const APPICON_CORNER_RADIUS = 4;
const APPICON_MENU_POPUP_TIMEOUT_MS = 600;
const APPICON_DEFAULT_BORDER_COLOR = new Clutter.Color();
APPICON_DEFAULT_BORDER_COLOR.from_pixel(0x787878ff);
const APPICON_MENU_BACKGROUND_COLOR = new Clutter.Color();
APPICON_MENU_BACKGROUND_COLOR.from_pixel(0x292929ff);
const APPICON_MENU_FONT = 'Sans 14px';
const APPICON_MENU_COLOR = new Clutter.Color();
APPICON_MENU_COLOR.from_pixel(0xffffffff);
const APPICON_MENU_SELECTED_COLOR = new Clutter.Color();
APPICON_MENU_SELECTED_COLOR.from_pixel(0x005b97ff);
const APPICON_MENU_SEPARATOR_COLOR = new Clutter.Color();
APPICON_MENU_SEPARATOR_COLOR.from_pixel(0x787878ff);
const APPICON_MENU_BORDER_WIDTH = 1;
const APPICON_MENU_ARROW_SIZE = 12;
const APPICON_MENU_CORNER_RADIUS = 4;
const APPICON_MENU_PADDING = 4;
const TRANSPARENT_COLOR = new Clutter.Color();
TRANSPARENT_COLOR.from_pixel(0x00000000);
const MenuType = { NONE: 0, ON_RIGHT: 1, BELOW: 2 };
function AppIcon(appInfo, menuType) {
this._init(appInfo, menuType || MenuType.NONE);
}
AppIcon.prototype = {
_init : function(appInfo, menuType) {
this.appInfo = appInfo;
this._menuType = menuType;
this.actor = new Shell.ButtonBox({ orientation: Big.BoxOrientation.VERTICAL,
border: APPICON_BORDER_WIDTH,
corner_radius: APPICON_CORNER_RADIUS,
padding: APPICON_PADDING,
reactive: true });
this.actor._delegate = this;
this.highlight_border_color = APPICON_DEFAULT_BORDER_COLOR;
if (menuType != MenuType.NONE) {
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.connect('button-press-event', Lang.bind(this, this._updateMenuOnButtonPress));
this.actor.connect('notify::hover', Lang.bind(this, this._updateMenuOnHoverChanged));
this.actor.connect('activate', Lang.bind(this, this._updateMenuOnActivate));
this._menuTimeoutId = 0;
this._menu = null;
} else
this.windows = [];
let iconBox = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
x_align: Big.BoxAlignment.CENTER,
y_align: Big.BoxAlignment.CENTER,
width: APPICON_ICON_SIZE,
height: APPICON_ICON_SIZE });
this.icon = appInfo.create_icon_texture(APPICON_ICON_SIZE);
iconBox.append(this.icon, Big.BoxPackFlags.NONE);
this.actor.append(iconBox, Big.BoxPackFlags.EXPAND);
let nameBox = new Shell.GenericContainer();
nameBox.connect('get-preferred-width', Lang.bind(this, this._nameBoxGetPreferredWidth));
nameBox.connect('get-preferred-height', Lang.bind(this, this._nameBoxGetPreferredHeight));
nameBox.connect('allocate', Lang.bind(this, this._nameBoxAllocate));
this._nameBox = nameBox;
this._name = new 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 visA = a.showing_on_its_workspace();
let visB = b.showing_on_its_workspace();
if (visA && !visB)
return -1;
else if (visB && !visA)
return 1;
else
return b.get_user_time() - a.get_user_time();
});
},
// AppIcon itself is not a draggable, but if you want to make
// a subclass of it draggable, you can use this method to create
// a drag actor
createDragActor: function() {
return this.appInfo.create_icon_texture(APPICON_ICON_SIZE);
},
setHighlight: function(highlight) {
if (highlight) {
this.actor.border_color = this.highlight_border_color;
} else {
this.actor.border_color = TRANSPARENT_COLOR;
}
},
_updateMenuOnActivate: function(actor, event) {
if (this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
this.emit('activate');
return false;
},
_updateMenuOnHoverChanged: function() {
if (!this.actor.hover && this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
return false;
},
_updateMenuOnButtonPress: function(actor, event) {
if (this._menuTimeoutId != 0)
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = Mainloop.timeout_add(APPICON_MENU_POPUP_TIMEOUT_MS,
Lang.bind(this, this.popupMenu));
return false;
},
popupMenu: function() {
if (this._menuTimeoutId != 0) {
Mainloop.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
this.actor.fake_release();
if (!this._menu) {
this._menu = new AppIconMenu(this, this._menuType);
this._menu.connect('highlight-window', Lang.bind(this, function (menu, window) {
this.highlightWindow(window);
}));
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
this.activateWindow(window);
}));
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
if (isPoppedUp)
this.menuPoppedUp();
else
this.menuPoppedDown();
}));
}
this._menu.popup();
return false;
},
// Default implementations; AppDisplay.RunningWellItem overrides these
highlightWindow: function(window) {
this.emit('highlight-window', window);
},
activateWindow: function(window) {
this.emit('activate-window', window);
},
menuPoppedUp: function() {
this.emit('menu-popped-up', this._menu);
},
menuPoppedDown: function() {
this.emit('menu-popped-down', this._menu);
}
};
Signals.addSignalMethods(AppIcon.prototype);
function AppIconMenu(source, type) {
this._init(source, type);
}
AppIconMenu.prototype = {
_init: function(source, type) {
this._source = source;
this._type = type;
this.actor = new Shell.GenericContainer({ reactive: true });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._windowContainer = new Shell.Menu({ orientation: Big.BoxOrientation.VERTICAL,
border_color: source.highlight_border_color,
border: APPICON_MENU_BORDER_WIDTH,
background_color: APPICON_MENU_BACKGROUND_COLOR,
padding: 4,
corner_radius: APPICON_MENU_CORNER_RADIUS,
width: Main.overview._dash.actor.width * 0.75 });
this._windowContainer.connect('unselected', Lang.bind(this, this._onItemUnselected));
this._windowContainer.connect('selected', Lang.bind(this, this._onItemSelected));
this._windowContainer.connect('cancelled', Lang.bind(this, this._onWindowSelectionCancelled));
this._windowContainer.connect('activate', Lang.bind(this, this._onItemActivate));
this.actor.add_actor(this._windowContainer);
// Stay popped up on release over application icon
this._windowContainer.set_persistent_source(this._source.actor);
// Intercept events while the menu has the pointer grab to do window-related effects
this._windowContainer.connect('enter-event', Lang.bind(this, this._onMenuEnter));
this._windowContainer.connect('leave-event', Lang.bind(this, this._onMenuLeave));
this._windowContainer.connect('button-release-event', Lang.bind(this, this._onMenuButtonRelease));
this._arrow = new Shell.DrawingArea();
this._arrow.connect('redraw', Lang.bind(this, function (area, texture) {
Shell.draw_box_pointer(texture,
this._type == MenuType.ON_RIGHT ? Clutter.Gravity.WEST : Clutter.Gravity.NORTH,
source.highlight_border_color,
APPICON_MENU_BACKGROUND_COLOR);
}));
this.actor.add_actor(this._arrow);
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
if (!source.actor.mapped)
this._windowContainer.popdown();
}));
source.actor.connect('destroy', Lang.bind(this, function () { this.actor.destroy(); }));
global.stage.add_actor(this.actor);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [min, natural] = this._windowContainer.get_preferred_width(forHeight);
if (this._type == MenuType.ON_RIGHT) {
min += APPICON_MENU_ARROW_SIZE;
natural += APPICON_MENU_ARROW_SIZE;
}
alloc.min_size = min;
alloc.natural_size = natural;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [min, natural] = this._windowContainer.get_preferred_height(forWidth);
if (this._type == MenuType.BELOW) {
min += APPICON_MENU_ARROW_SIZE;
natural += APPICON_MENU_ARROW_SIZE;
}
alloc.min_size = min;
alloc.natural_size = natural;
},
_allocate: function(actor, box, flags) {
let childBox = new Clutter.ActorBox();
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
if (this._type == MenuType.ON_RIGHT) {
childBox.x1 = 0;
childBox.x2 = APPICON_MENU_ARROW_SIZE;
childBox.y1 = Math.floor((height / 2) - (APPICON_MENU_ARROW_SIZE / 2));
childBox.y2 = childBox.y1 + APPICON_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
childBox.x1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
childBox.x2 = width;
childBox.y1 = 0;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
} else /* MenuType.BELOW */ {
childBox.x1 = Math.floor((width / 2) - (APPICON_MENU_ARROW_SIZE / 2));
childBox.x2 = childBox.x1 + APPICON_MENU_ARROW_SIZE;
childBox.y1 = 0;
childBox.y2 = APPICON_MENU_ARROW_SIZE;
this._arrow.allocate(childBox, flags);
childBox.x1 = 0;
childBox.x2 = width;
childBox.y1 = APPICON_MENU_ARROW_SIZE - APPICON_MENU_BORDER_WIDTH;
childBox.y2 = height;
this._windowContainer.allocate(childBox, flags);
}
},
_redisplay: function() {
this._windowContainer.remove_all();
let windows = this._source.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) {
this._appendSeparator();
}
this._appendWindows(otherWorkspaceWindows, iconsDiffer);
this._appendSeparator();
this._newWindowMenuItem = this._appendMenuItem(null, _("New Window"));
this._highlightedItem = null;
},
_appendSeparator: function () {
let box = new Big.Box({ padding_top: 2, padding_bottom: 2 });
box.append(new Clutter.Rectangle({ height: 1,
color: APPICON_MENU_SEPARATOR_COLOR }),
Big.BoxPackFlags.EXPAND);
this._windowContainer.append_separator(box, Big.BoxPackFlags.NONE);
},
_appendMenuItem: function(iconTexture, labelText) {
/* Use padding here rather than spacing in the box above so that
* we have a larger reactive area.
*/
let box = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
padding_top: 4,
padding_bottom: 4,
spacing: 4,
reactive: true });
let vCenter;
if (iconTexture != null) {
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
vCenter.append(iconTexture, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
}
vCenter = new Big.Box({ y_align: Big.BoxAlignment.CENTER });
let label = new Clutter.Text({ text: labelText,
font_name: APPICON_MENU_FONT,
ellipsize: Pango.EllipsizeMode.END,
color: APPICON_MENU_COLOR });
vCenter.append(label, Big.BoxPackFlags.NONE);
box.append(vCenter, Big.BoxPackFlags.NONE);
this._windowContainer.append(box, Big.BoxPackFlags.NONE);
return box;
},
_appendWindows: function (windows, iconsDiffer) {
for (let i = 0; i < windows.length; i++) {
let metaWindow = windows[i];
let icon = null;
if (iconsDiffer) {
icon = Shell.TextureCache.get_default().bind_pixbuf_property(metaWindow, "mini-icon");
}
let box = this._appendMenuItem(icon, metaWindow.title);
box._window = metaWindow;
}
},
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, Main.currentTime());
this.emit('popup', true);
let x, y;
if (this._type == MenuType.ON_RIGHT) {
x = Math.floor(stageX + stageWidth);
y = Math.floor(stageY + (stageHeight / 2) - (this.actor.height / 2));
} else {
x = Math.floor(stageX + (stageWidth / 2) - (this.actor.width / 2));
y = Math.floor(stageY + stageHeight);
}
this.actor.set_position(x, y);
this.actor.show();
},
popdown: function() {
this._windowContainer.popdown();
this.emit('popup', false);
this.actor.hide();
},
selectWindow: function(metaWindow) {
this._selectMenuItemForWindow(metaWindow);
},
_findMetaWindowForActor: function (actor) {
if (actor._delegate instanceof Workspaces.WindowClone)
return actor._delegate.metaWindow;
else if (actor.get_meta_window)
return actor.get_meta_window();
return null;
},
// This function is called while the menu has a pointer grab; what we want
// to do is see if the mouse was released over a window representation
_onMenuButtonRelease: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this.emit('activate-window', metaWindow);
}
},
_updateHighlight: function (item) {
if (this._highlightedItem) {
this._highlightedItem.background_color = TRANSPARENT_COLOR;
this.emit('highlight-window', null);
}
this._highlightedItem = item;
if (this._highlightedItem) {
this._highlightedItem.background_color = APPICON_MENU_SELECTED_COLOR;
let window = this._highlightedItem._window;
if (window)
this.emit('highlight-window', window);
}
},
_selectMenuItemForWindow: function (metaWindow) {
let children = this._windowContainer.get_children();
for (let i = 0; i < children.length; i++) {
let child = children[i];
let menuMetaWindow = child._window;
if (menuMetaWindow == metaWindow)
this._updateHighlight(child);
}
},
// Called while menu has a pointer grab
_onMenuEnter: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this._selectMenuItemForWindow(metaWindow);
}
},
// Called while menu has a pointer grab
_onMenuLeave: function (actor, event) {
let metaWindow = this._findMetaWindowForActor(event.get_source());
if (metaWindow) {
this._updateHighlight(null);
}
},
_onItemUnselected: function (actor, child) {
this._updateHighlight(null);
},
_onItemSelected: function (actor, child) {
this._updateHighlight(child);
},
_onItemActivate: function (actor, child) {
if (child._window) {
let metaWindow = child._window;
this.emit('activate-window', metaWindow);
} else if (child == this._newWindowMenuItem) {
this._source.appInfo.launch();
this.emit('activate-window', null);
}
this.popdown();
},
_onWindowSelectionCancelled: function () {
this.emit('highlight-window', null);
this.popdown();
}
};
Signals.addSignalMethods(AppIconMenu.prototype);

198
js/ui/boxpointer.js Normal file
View File

@ -0,0 +1,198 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
/**
* BoxPointer:
* @side: A St.Side type; currently only St.Side.TOP is implemented
* @binProperties: Properties to set on contained bin
*
* An actor which displays a triangle "arrow" pointing to a given
* side. The .bin property is a container in which content can be
* placed. The arrow position may be controlled via setArrowOrigin().
*
*/
function BoxPointer(side, binProperties) {
this._init(side, binProperties);
}
BoxPointer.prototype = {
_init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide;
this._arrowOrigin = 0;
this.actor = new St.Bin({ x_fill: true,
y_fill: true });
this._container = new Shell.GenericContainer();
this.actor.set_child(this._container);
this._container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._container.connect('allocate', Lang.bind(this, this._allocate));
this.bin = new St.Bin(binProperties);
this._container.add_actor(this.bin);
this._border = new St.DrawingArea();
this._border.connect('repaint', Lang.bind(this, this._drawBorder));
this._container.add_actor(this._border);
this.bin.raise(this._border);
},
_adjustAllocationForArrow: function(isWidth, alloc) {
let themeNode = this.actor.get_theme_node();
let found, borderWidth, base, rise;
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
alloc.min_size += borderWidth * 2;
alloc.natural_size += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
|| (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let [found, rise] = themeNode.get_length('-arrow-rise', false);
alloc.min_size += rise;
alloc.natural_size += rise;
}
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let [minInternalSize, natInternalSize] = this.bin.get_preferred_width(forHeight);
alloc.min_size = minInternalSize;
alloc.natural_size = natInternalSize;
this._adjustAllocationForArrow(true, alloc);
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [minSize, naturalSize] = this.bin.get_preferred_height(forWidth);
alloc.min_size = minSize;
alloc.natural_size = naturalSize;
this._adjustAllocationForArrow(false, alloc);
},
_allocate: function(actor, box, flags) {
let themeNode = this.actor.get_theme_node();
let found, borderWidth, borderRadius, rise, base;
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
[found, rise] = themeNode.get_length('-arrow-rise', false);
let childBox = new Clutter.ActorBox();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
childBox.x1 = 0;
childBox.y1 = 0;
childBox.x2 = availWidth;
childBox.y2 = availHeight;
this._border.allocate(childBox, flags);
childBox.x1 = borderWidth;
childBox.y1 = borderWidth;
childBox.x2 = availWidth - borderWidth;
childBox.y2 = availHeight - borderWidth;
switch (this._arrowSide) {
case St.Side.TOP:
childBox.y1 += rise;
break;
case St.Side.BOTTOM:
childBox.y2 -= rise;
break;
case St.Side.LEFT:
childBox.x1 += rise;
break;
case St.Side.RIGHT:
childBox.x2 -= rise;
break;
}
this.bin.allocate(childBox, flags);
},
_drawBorder: function(area) {
let themeNode = this.actor.get_theme_node();
let found, borderWidth, borderRadius, rise, base;
[found, borderWidth] = themeNode.get_length('-arrow-border-width', false);
[found, base] = themeNode.get_length('-arrow-base', false);
[found, rise] = themeNode.get_length('-arrow-rise', false);
[found, borderRadius] = themeNode.get_length('-arrow-border-radius', false);
let halfBorder = borderWidth / 2;
let halfBase = Math.floor(base/2);
let borderColor = new Clutter.Color();
themeNode.get_color('-arrow-border-color', false, borderColor);
let backgroundColor = new Clutter.Color();
themeNode.get_color('-arrow-background-color', false, backgroundColor);
let [width, height] = area.get_surface_size();
let [boxWidth, boxHeight] = [width, height];
if (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM) {
boxHeight -= rise;
} else {
boxWidth -= rise;
}
let cr = area.get_context();
Clutter.cairo_set_source_color(cr, borderColor);
// Translate so that box goes from 0,0 to boxWidth,boxHeight,
// with the arrow poking out of that
if (this._arrowSide == St.Side.TOP) {
cr.translate(0, rise);
} else if (this._arrowSide == St.Side.LEFT) {
cr.translate(rise, 0);
}
cr.moveTo(borderRadius, halfBorder);
if (this._arrowSide == St.Side.TOP) {
cr.lineTo(this._arrowOrigin - halfBase, halfBorder);
cr.lineTo(this._arrowOrigin, halfBorder - rise);
cr.lineTo(this._arrowOrigin + halfBase, halfBorder);
}
cr.lineTo(boxWidth - borderRadius, halfBorder);
cr.arc(boxWidth - borderRadius - halfBorder, borderRadius + halfBorder, borderRadius,
3*Math.PI/2, Math.PI*2);
if (this._arrowSide == St.Side.RIGHT) {
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin - halfBase);
cr.lineTo(boxWidth - halfBorder + rise, this._arrowOrigin);
cr.lineTo(boxWidth - halfBorder, this._arrowOrigin + halfBase);
}
cr.lineTo(boxWidth - halfBorder, boxHeight - borderRadius);
cr.arc(boxWidth - borderRadius - halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
0, Math.PI/2);
if (this._arrowSide == St.Side.BOTTOM) {
cr.lineTo(this._arrowOrigin + halfBase, boxHeight - halfBorder);
cr.lineTo(this._arrowOrigin, boxHeight - halfBorder + rise);
cr.lineTo(this._arrowOrigin - halfBase, boxHeight - halfBorder);
}
cr.lineTo(borderRadius, boxHeight - halfBorder);
cr.arc(borderRadius + halfBorder, boxHeight - borderRadius - halfBorder, borderRadius,
Math.PI/2, Math.PI);
if (this._arrowSide == St.Side.LEFT) {
cr.lineTo(halfBorder, this._arrowOrigin + halfBase);
cr.lineTo(halfBorder - rise, this._arrowOrigin);
cr.lineTo(halfBorder, this._arrowOrigin - halfBase);
}
cr.lineTo(halfBorder, borderRadius);
cr.arc(borderRadius + halfBorder, borderRadius + halfBorder, borderRadius,
Math.PI, 3*Math.PI/2);
Clutter.cairo_set_source_color(cr, backgroundColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, borderColor);
cr.setLineWidth(borderWidth);
cr.stroke();
},
// @origin: Coordinate specifying middle of the arrow, along
// the Y axis for St.Side.LEFT, St.Side.RIGHT from the top and X axis from
// the left for St.Side.TOP and St.Side.BOTTOM.
setArrowOrigin: function(origin) {
if (this._arrowOrigin != origin) {
this._arrowOrigin = origin;
this._border.queue_repaint();
}
}
};

View File

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

266
js/ui/calendar.js Normal file
View File

@ -0,0 +1,266 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const Gettext_gtk20 = imports.gettext.domain('gtk20');
const MSECS_IN_DAY = 24 * 60 * 60 * 1000;
const WEEKDATE_HEADER_WIDTH_DIGITS = 3;
const SHOW_WEEKDATE_KEY = 'show-weekdate';
function _sameDay(dateA, dateB) {
return (dateA.getDate() == dateB.getDate() &&
dateA.getMonth() == dateB.getMonth() &&
dateA.getYear() == dateB.getYear());
}
function _getCalendarWeekForDate(date) {
// Based on the algorithms found here:
// http://en.wikipedia.org/wiki/Talk:ISO_week_date
let midnightDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
// Need to get Monday to be 1 ... Sunday to be 7
let dayOfWeek = 1 + ((midnightDate.getDay() + 6) % 7);
let nearestThursday = new Date(midnightDate.getFullYear(), midnightDate.getMonth(),
midnightDate.getDate() + (4 - dayOfWeek));
let jan1st = new Date(nearestThursday.getFullYear(), 0, 1);
let diffDate = nearestThursday - jan1st;
let dayNumber = Math.floor(Math.abs(diffDate) / MSECS_IN_DAY);
let weekNumber = Math.floor(dayNumber / 7) + 1;
return weekNumber;
}
function _getDigitWidth(actor){
let context = actor.get_pango_context();
let themeNode = actor.get_theme_node();
let font = themeNode.get_font();
let metrics = context.get_metrics(font, context.get_language());
let width = metrics.get_approximate_digit_width();
return width;
}
function Calendar() {
this._init();
}
Calendar.prototype = {
_init: function() {
// FIXME: This is actually the fallback method for GTK+ for the week start;
// GTK+ by preference uses nl_langinfo (NL_TIME_FIRST_WEEKDAY). We probably
// should add a C function so we can do the full handling.
this._weekStart = NaN;
this._weekdate = NaN;
this._digitWidth = NaN;
this._settings = new Gio.Settings({ schema: 'org.gnome.shell.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
let weekStartString = Gettext_gtk20.gettext('calendar:week_start:0');
if (weekStartString.indexOf('calendar:week_start:') == 0) {
this._weekStart = parseInt(weekStartString.substring(20));
}
if (isNaN(this._weekStart) || this._weekStart < 0 || this._weekStart > 6) {
log('Translation of "calendar:week_start:0" in GTK+ is not correct');
this._weekStart = 0;
}
// Find the ordering for month/year in the calendar heading
switch (Gettext_gtk20.gettext('calendar:MY')) {
case 'calendar:MY':
this._headerFormat = '%B %Y';
break;
case 'calendar:YM':
this._headerFormat = '%Y %B';
break;
default:
log('Translation of "calendar:MY" in GTK+ is not correct');
this._headerFormat = '%B %Y';
break;
}
// Start off with the current date
this.date = new Date();
this.actor = new St.Table({ homogeneous: false,
style_class: 'calendar',
reactive: true });
this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll));
this._buildHeader ();
this._update();
},
// Sets the calendar to show a specific date
setDate: function(date) {
if (!_sameDay(date, this.date)) {
this.date = date;
this._update();
}
},
_buildHeader: function() {
let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.destroy_children();
// Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout();
this.actor.add(this._topBox,
{ row: 0, col: 0, col_span: offsetCols + 7 });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChange));
let [backlabel, forwardlabel] = ['&lt;', '&gt;'];
if (St.Widget.get_default_direction () == St.TextDirection.RTL) {
[backlabel, forwardlabel] = [forwardlabel, backlabel];
}
let back = new St.Button({ label: backlabel, style_class: 'calendar-change-month' });
this._topBox.add(back);
back.connect('clicked', Lang.bind(this, this._prevMonth));
this._dateLabel = new St.Label();
this._topBox.add(this._dateLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
let forward = new St.Button({ label: forwardlabel, style_class: 'calendar-change-month' });
this._topBox.add(forward);
forward.connect('clicked', Lang.bind(this, this._nextMonth));
// We need to figure out the abbreviated localized names for the days of the week;
// we do this by just getting the next 7 days starting from right now and then putting
// them in the right cell in the table. It doesn't matter if we add them in order
let iter = new Date(this.date);
iter.setSeconds(0); // Leap second protection. Hah!
iter.setHours(12);
if (this._useWeekdate) {
this._weekdateHeader = new St.Label();
this.actor.add(this._weekdateHeader,
{ row: 1,
col: 0,
x_fill: false, x_align: St.Align.MIDDLE });
this._setWeekdateHeaderWidth();
} else {
this._weekdateHeader = null;
}
for (let i = 0; i < 7; i++) {
this.actor.add(new St.Label({ text: iter.toLocaleFormat('%a') }),
{ row: 1,
col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: St.Align.END });
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
// All the children after this are days, and get removed when we update the calendar
this._firstDayIndex = this.actor.get_children().length;
},
_onStyleChange: function(actor, event) {
// width of a digit in pango units
this._digitWidth = _getDigitWidth(this.actor) / Pango.SCALE;
this._setWeekdateHeaderWidth();
},
_setWeekdateHeaderWidth: function() {
if (this.digitWidth != NaN && this._useWeekdate && this._weekdateHeader) {
this._weekdateHeader.set_width (this._digitWidth * WEEKDATE_HEADER_WIDTH_DIGITS);
}
},
_onScroll : function(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.LEFT:
this._prevMonth();
break;
case Clutter.ScrollDirection.DOWN:
case Clutter.ScrollDirection.RIGHT:
this._nextMonth();
break;
}
},
_prevMonth: function() {
if (this.date.getMonth() == 0) {
this.date.setMonth(11);
this.date.setFullYear(this.date.getFullYear() - 1);
} else {
this.date.setMonth(this.date.getMonth() - 1);
}
this._update();
},
_nextMonth: function() {
if (this.date.getMonth() == 11) {
this.date.setMonth(0);
this.date.setFullYear(this.date.getFullYear() + 1);
} else {
this.date.setMonth(this.date.getMonth() + 1);
}
this._update();
},
_onSettingsChange: function() {
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
this._buildHeader();
this._update();
},
_update: function() {
this._dateLabel.text = this.date.toLocaleFormat(this._headerFormat);
// Remove everything but the topBox and the weekday labels
let children = this.actor.get_children();
for (let i = this._firstDayIndex; i < children.length; i++)
children[i].destroy();
// Start at the beginning of the week before the start of the month
let iter = new Date(this.date);
iter.setDate(1);
iter.setSeconds(0);
iter.setHours(12);
let daysToWeekStart = (7 + iter.getDay() - this._weekStart) % 7;
iter.setTime(iter.getTime() - daysToWeekStart * MSECS_IN_DAY);
let now = new Date();
let row = 2;
while (true) {
let label = new St.Label({ text: iter.getDate().toString() });
if (_sameDay(now, iter))
label.style_class = 'calendar-day calendar-today';
else if (iter.getMonth() != this.date.getMonth())
label.style_class = 'calendar-day calendar-other-month-day';
else
label.style_class = 'calendar-day';
let offsetCols = this._useWeekdate ? 1 : 0;
this.actor.add(label,
{ row: row, col: offsetCols + (7 + iter.getDay() - this._weekStart) % 7,
x_fill: false, x_align: St.Align.END });
if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
style_class: 'calendar-day calendar-calendarweek'});
this.actor.add(label,
{ row: row, col: 0,
x_fill: false, x_align: St.Align.MIDDLE });
}
iter.setTime(iter.getTime() + MSECS_IN_DAY);
if (iter.getDay() == this._weekStart) {
// We stop on the first "first day of the week" after the month we are displaying
if (iter.getMonth() > this.date.getMonth() || iter.getYear() > this.date.getYear())
break;
row++;
}
}
}
};

View File

@ -1,17 +1,31 @@
/* -*- 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 Signals = imports.signals;
const Main = imports.ui.main;
const Params = imports.misc.params;
// This manages the shell "chrome"; the UI that's visible in the
// normal mode (ie, outside the Overview), that surrounds the main
// workspace content.
const Visibility = {
FULL: 1,
FULLSCREEN: 2,
OVERVIEW: 3
};
const defaultParams = {
visibleInOverview: false,
visibleInFullscreen: false,
affectsStruts: true,
affectsInputRegion: true
};
function Chrome() {
this._init();
}
@ -19,12 +33,13 @@ function Chrome() {
Chrome.prototype = {
_init: function() {
// 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.nonOverviewActor = new Clutter.Group();
this.actor.add_actor(this.nonOverviewActor);
this.actor = new Shell.GenericContainer({ width: 0, height: 0 });
Main.uiGroup.add_actor(this.actor);
this.actor.connect('allocate', Lang.bind(this, this._allocated));
this._obscuredByFullscreen = false;
this._inFullscreen = false;
this._inOverview = false;
this.visibility = Visibility.FULL;
this._trackedActors = [];
@ -43,18 +58,15 @@ Chrome.prototype = {
this._queueUpdateRegions();
},
_verifyAncestry: function(actor, ancestor) {
while (actor) {
if (actor == ancestor)
return true;
actor = actor.get_parent();
}
return false;
_allocated: function(actor, box, flags) {
let children = this.actor.get_children();
for (let i = 0; i < children.length; i++)
children[i].allocate_preferred_size(flags);
},
// addActor:
// @actor: an actor to add to the chrome layer
// @shapeActor: optional "shape actor".
// @params: (optional) additional params
//
// Adds @actor to the chrome layer and extends the input region
// and window manager struts to include it. (Window manager struts
@ -64,59 +76,60 @@ Chrome.prototype = {
// in its visibility will affect the input region, but NOT the
// struts.
//
// If @shapeActor is provided, it will be used instead of @actor
// for the input region/strut shape. (This lets you have things like
// drop shadows in @actor that don't affect the struts.) It must
// be a child of @actor. Alternatively, you can pass %null for
// @shapeActor to indicate that @actor should not affect the input
// region or struts at all.
addActor: function(actor, shapeActor) {
if (shapeActor === undefined)
shapeActor = actor;
else if (shapeActor && !this._verifyAncestry(shapeActor, actor))
throw new Error('shapeActor is not a descendent of actor');
this.nonOverviewActor.add_actor(actor);
if (shapeActor)
this._trackActor(shapeActor, true, true);
// If %visibleInOverview is %true in @params, @actor will remain
// visible when the overview is brought up. Otherwise it will
// automatically be hidden. Likewise, if %visibleInFullscreen is
// %true, the actor will be visible even when a fullscreen window
// should be covering it.
//
// If %affectsStruts or %affectsInputRegion is %false, the actor
// will not have the indicated effect.
addActor: function(actor, params) {
this.actor.add_actor(actor);
this._trackActor(actor, params);
},
// setVisibleInOverview:
// @actor: an actor in the chrome layer
// @visible: Overview visibility
// trackActor:
// @actor: a descendant of the chrome to begin tracking
// @params: parameters describing how to track @actor
//
// By default, actors in the chrome layer are automatically hidden
// when the Overview is shown. This can be used to override that
// behavior
setVisibleInOverview: function(actor, visible) {
if (!this._verifyAncestry(actor, this.actor))
// Tells the chrome to track @actor, which must be a descendant
// of an actor added via addActor(). This can be used to extend the
// struts or input region to cover specific children.
//
// @params can have any of the same values as in addActor(), though
// some possibilities don't make sense (eg, trying to have a
// %visibleInOverview child of a non-%visibleInOverview parent).
// By default, @actor has the same params as its chrome ancestor.
trackActor: function(actor, params) {
let ancestor = actor.get_parent();
let index = this._findActor(ancestor);
while (ancestor && index == -1) {
ancestor = ancestor.get_parent();
index = this._findActor(ancestor);
}
if (!ancestor)
throw new Error('actor is not a descendent of the chrome layer');
if (visible)
actor.reparent(this.actor);
else
actor.reparent(this.nonOverviewActor);
let ancestorData = this._trackedActors[index];
if (!params)
params = {};
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
if (!params[prop])
params[prop] = ancestorData[prop];
}
this._trackActor(actor, params);
},
// addInputRegionActor:
// @actor: an actor to add to the stage input region
// untrackActor:
// @actor: an actor previously tracked via trackActor()
//
// Adds @actor to the stage input region, as with addActor(), but
// for actors that are already descendants of the chrome layer.
addInputRegionActor: function(actor) {
if (!this._verifyAncestry(actor, this.actor))
throw new Error('actor is not a descendent of the chrome layer');
this._trackActor(actor, true, false);
},
// removeInputRegionActor:
// @actor: an actor previously added to the stage input region
//
// Undoes the effect of addInputRegionActor()
removeInputRegionActor: function(actor) {
this._untrackActor(actor, true, false);
// Undoes the effect of trackActor()
untrackActor: function(actor) {
this._untrackActor(actor);
},
// removeActor:
@ -124,11 +137,8 @@ Chrome.prototype = {
//
// Removes @actor from the chrome layer
removeActor: function(actor) {
if (actor.get_parent() == this.nonOverviewActor)
this.nonOverviewActor.remove_actor(actor);
else
this.actor.remove_actor(actor);
this._untrackActor(actor, true, true);
this.actor.remove_actor(actor);
this._untrackActor(actor);
},
_findActor: function(actor) {
@ -140,92 +150,79 @@ Chrome.prototype = {
return -1;
},
_trackActor: function(actor, inputRegion, strut) {
let actorData;
let i = this._findActor(actor);
if (i != -1) {
actorData = this._trackedActors[i];
if (inputRegion)
actorData.inputRegion++;
if (strut)
actorData.strut++;
if (!inputRegion && !strut)
actorData.children++;
return;
}
actorData = { actor: actor,
inputRegion: inputRegion ? 1 : 0,
strut: strut ? 1 : 0,
children: 0 };
_trackActor: function(actor, params) {
if (this._findActor(actor) != -1)
throw new Error('trying to re-track existing chrome actor');
let actorData = Params.parse(params, defaultParams);
actorData.actor = actor;
actorData.visibleId = actor.connect('notify::visible',
Lang.bind(this, this._queueUpdateRegions));
actorData.allocationId = actor.connect('notify::allocation',
Lang.bind(this, this._queueUpdateRegions));
actorData.parentSetId = actor.connect('parent-set',
Lang.bind(this, this._actorReparented));
// Note that destroying actor will unset its parent, so we don't
// need to connect to 'destroy' too.
this._trackedActors.push(actorData);
actor = actor.get_parent();
if (actor != this.actor && actor != this.nonOverviewActor)
this._trackActor(actor, false, false);
if (inputRegion || strut)
this._queueUpdateRegions();
this._queueUpdateRegions();
},
_untrackActor: function(actor, inputRegion, strut) {
_untrackActor: function(actor) {
let i = this._findActor(actor);
if (i == -1)
return;
let actorData = this._trackedActors[i];
if (inputRegion)
actorData.inputRegion--;
if (strut)
actorData.strut--;
if (!inputRegion && !strut)
actorData.children--;
this._trackedActors.splice(i, 1);
actor.disconnect(actorData.visibleId);
actor.disconnect(actorData.allocationId);
actor.disconnect(actorData.parentSetId);
if (actorData.inputRegion <= 0 && actorData.strut <= 0 && actorData.children <= 0) {
this._trackedActors.splice(i, 1);
actor.disconnect(actorData.visibleId);
actor.disconnect(actorData.allocationId);
actor.disconnect(actorData.parentSetId);
actor = actor.get_parent();
if (actor && actor != this.actor && actor != this.nonOverviewActor)
this._untrackActor(actor, false, false);
}
if (inputRegion || strut)
this._queueUpdateRegions();
this._queueUpdateRegions();
},
_actorReparented: function(actor, oldParent) {
if (this._verifyAncestry(actor, this.actor)) {
let newParent = actor.get_parent();
if (newParent != this.actor && newParent != this.nonOverviewActor)
this._trackActor(newParent, false, false);
if (!this.actor.contains(actor))
this._untrackActor(actor);
},
_updateVisibility: function() {
for (let i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i];
if (this._inOverview && !actorData.visibleInOverview)
this.actor.set_skip_paint(actorData.actor, true);
else if (!this._inOverview && this._inFullscreen && !actorData.visibleInFullscreen)
this.actor.set_skip_paint(actorData.actor, true);
else
this.actor.set_skip_paint(actorData.actor, false);
}
let newVisibility;
if (this._inOverview)
newVisibility = Visibility.OVERVIEW;
else if (this._inFullscreen)
newVisibility = Visibility.FULLSCREEN;
else
newVisibility = Visibility.FULL;
if (newVisibility != this.visibility) {
this.visibility = newVisibility;
this.emit('visibility-changed', this.visibility);
}
if (oldParent != this.actor && oldParent != this.nonOverviewActor)
this._untrackActor(oldParent, false, false);
},
_overviewShowing: function() {
this.actor.show();
this.nonOverviewActor.hide();
this._inOverview = true;
this._updateVisibility();
this._queueUpdateRegions();
},
_overviewHidden: function() {
if (this._obscuredByFullscreen)
this.actor.hide();
this.nonOverviewActor.show();
this._inOverview = false;
this._updateVisibility();
this._queueUpdateRegions();
},
@ -237,11 +234,12 @@ Chrome.prototype = {
_windowsRestacked: function() {
let windows = global.get_windows();
let primary = global.get_primary_monitor();
// The chrome layer should be visible unless there is a window
// with layer FULLSCREEN, or a window with layer
// OVERRIDE_REDIRECT that covers the whole screen.
// ("override_redirect" is not actually a layer above all
// ('override_redirect' is not actually a layer above all
// other windows, but this seems to be how mutter treats it
// currently...) If we wanted to be extra clever, we could
// figure out when an OVERRIDE_REDIRECT window was trying to
@ -250,28 +248,40 @@ Chrome.prototype = {
// @windows is sorted bottom to top.
this._obscuredByFullscreen = false;
let wasInFullscreen = this._inFullscreen;
this._inFullscreen = false;
for (let i = windows.length - 1; i > -1; i--) {
let layer = windows[i].get_meta_window().get_layer();
// There are 3 cases we check here for:
// 1.) Monitor sized window
// 2.) Window with a position somewhere on the primary screen having the _NET_WM_FULLSCREEN flag set
// 3.) Window that is partly off screen (tries to hide its decorations) which might have negative coords
// We check for 1.) and 2.) by checking if the upper right corner is on the primary monitor, but avoid the case
// where it overlaps with the secondary screen (like window.x + window.width == primary.x + primary.width)
// For 3.) we just ignore negative values as they don't really make sense
if (layer == Meta.StackLayer.FULLSCREEN) {
if (Math.max(windows[i].x, 0) >= primary.x && Math.max(windows[i].x, 0) < primary.x + primary.width &&
Math.max(windows[i].y, 0) >= primary.y && Math.max(windows[i].y, 0) < primary.y + primary.height) {
this._inFullscreen = true;
break;
}
}
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
if (windows[i].x <= 0 &&
windows[i].x + windows[i].width >= global.screen_width &&
windows[i].y <= 0 &&
windows[i].y + windows[i].height >= global.screen_height) {
this._obscuredByFullscreen = true;
if (windows[i].x <= primary.x &&
windows[i].x + windows[i].width >= primary.x + primary.width &&
windows[i].y <= primary.y &&
windows[i].y + windows[i].height >= primary.y + primary.height) {
this._inFullscreen = true;
break;
}
} else if (layer == Meta.StackLayer.FULLSCREEN) {
this._obscuredByFullscreen = true;
break;
} else
break;
}
let shouldBeVisible = !this._obscuredByFullscreen || Main.overview.visible;
if (this.actor.visible != shouldBeVisible) {
this.actor.visible = shouldBeVisible;
if (this._inFullscreen != wasInFullscreen) {
this._updateVisibility();
this._queueUpdateRegions();
}
},
@ -283,7 +293,7 @@ Chrome.prototype = {
for (i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i];
if (!actorData.inputRegion && !actorData.strut)
if (!actorData.affectsInputRegion && !actorData.affectsStruts)
continue;
let [x, y] = actorData.actor.get_transformed_position();
@ -294,10 +304,12 @@ Chrome.prototype = {
h = Math.round(h);
let rect = new Meta.Rectangle({ x: x, y: y, width: w, height: h});
if (actorData.inputRegion && actorData.actor.get_paint_visibility())
if (actorData.affectsInputRegion &&
actorData.actor.get_paint_visibility() &&
!this.actor.get_skip_paint(actorData.actor))
rects.push(rect);
if (!actorData.strut)
if (!actorData.affectsStruts)
continue;
// Metacity wants to know what side of the screen the
@ -349,3 +361,4 @@ Chrome.prototype = {
return false;
}
};
Signals.addSignalMethods(Chrome.prototype);

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,52 @@
/* -*- mode: js2; js2-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- */
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const St = imports.gi.St;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const Params = imports.misc.params;
// Time to scale down to maxDragActorSize
const SCALE_ANIMATION_TIME = 0.25;
// Time to animate to original position on cancel
const SNAP_BACK_ANIMATION_TIME = 0.25;
// Time to animate to original position on success
const REVERT_ANIMATION_TIME = 0.75;
const DragMotionResult = {
NO_DROP: 0,
COPY_DROP: 1,
MOVE_DROP: 2,
CONTINUE: 3
};
const DRAG_CURSOR_MAP = {
0: Shell.Cursor.UNSUPPORTED_TARGET,
1: Shell.Cursor.COPY,
2: Shell.Cursor.MOVE
};
const DragDropResult = {
FAILURE: 0,
SUCCESS: 1,
CONTINUE: 2
};
let eventHandlerActor = null;
let currentDraggable = null;
let dragMonitors = [];
function _getEventHandlerActor() {
if (!eventHandlerActor) {
eventHandlerActor = new Clutter.Rectangle();
eventHandlerActor.width = 0;
eventHandlerActor.height = 0;
global.stage.add_actor(eventHandlerActor);
Main.uiGroup.add_actor(eventHandlerActor);
// We connect to 'event' rather than 'captured-event' because the capturing phase doesn't happen
// when you've grabbed the pointer.
eventHandlerActor.connect('event',
@ -27,31 +57,63 @@ function _getEventHandlerActor() {
return eventHandlerActor;
}
function _Draggable(actor, manualMode) {
this._init(actor, manualMode);
function addDragMonitor(monitor) {
dragMonitors.push(monitor);
}
function removeMonitor(monitor) {
for (let i = 0; i < dragMonitors.length; i++)
if (dragMonitors[i] == monitor) {
dragMonitors.splice(i, 1);
return;
}
}
function _Draggable(actor, params) {
this._init(actor, params);
}
_Draggable.prototype = {
_init : function(actor, manualMode) {
_init : function(actor, params) {
params = Params.parse(params, { manualMode: false,
restoreOnSuccess: false,
dragActorMaxSize: undefined,
dragActorOpacity: undefined });
this.actor = actor;
if (!manualMode)
if (!params.manualMode)
this.actor.connect('button-press-event',
Lang.bind(this, this._onButtonPress));
this.actor.connect('destroy', Lang.bind(this, function() {
this.disconnectAll();
}));
this._onEventId = null;
this._restoreOnSuccess = params.restoreOnSuccess;
this._dragActorMaxSize = params.dragActorMaxSize;
this._dragActorOpacity = params.dragActorOpacity;
this._buttonDown = false; // The mouse button has been pressed and has not yet been released.
this._dragInProgress = false; // The drag has been started, and has not been dropped or cancelled yet.
this._snapBackInProgress = false; // The drag has been cancelled and the item is in the process of snapping back.
this._animationInProgress = false; // The drag is over and the item is in the process of animating to its original position (snapping back or reverting).
},
_onButtonPress : function (actor, event) {
// FIXME: we should make sure it's button 1, but we can't currently
// check that from JavaScript
if (event.get_button() != 1)
return false;
if (Tweener.getTweenCount(actor))
return false;
this._buttonDown = true;
this._grabActor();
// special case St.Clickable: grabbing the pointer would mess up the
// internal state, so we start the drag manually on hover change
if (this.actor instanceof St.Clickable)
this.actor.connect('notify::hover',
Lang.bind(this, this._onClickableHoverChanged));
else
this._grabActor();
let [stageX, stageY] = event.get_coords();
this._dragStartX = stageX;
@ -59,7 +121,16 @@ _Draggable.prototype = {
return false;
},
_onClickableHoverChanged: function(button) {
if (button.hover || !button.held)
return;
button.fake_release();
this.startDrag(this._dragStartX, this._dragStartY,
global.get_current_time());
},
_grabActor: function() {
Clutter.grab_pointer(this.actor);
this._onEventId = this.actor.connect('event',
@ -91,7 +162,7 @@ _Draggable.prototype = {
this._buttonDown = false;
if (this._dragInProgress) {
return this._dragActorDropped(event);
} else if (this._dragActor != null && !this._snapBackInProgress) {
} else if (this._dragActor != null && !this._animationInProgress) {
// Drag must have been cancelled with Esc.
this._dragComplete();
return true;
@ -139,9 +210,10 @@ _Draggable.prototype = {
if (this._onEventId)
this._ungrabActor();
this._grabEvents();
global.set_cursor(Shell.Cursor.IN_DRAG);
this._dragStartX = stageX;
this._dragStartY = stageY;
this._dragX = this._dragStartX = stageX;
this._dragY = this._dragStartY = stageY;
if (this.actor._delegate && this.actor._delegate.getDragActor) {
this._dragActor = this.actor._delegate.getDragActor(this._dragStartX, this._dragStartY);
@ -154,10 +226,9 @@ _Draggable.prototype = {
// 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) {
if (stageX > sourceX && stageX <= sourceX + this._dragActor.width &&
stageY > sourceY && stageY <= sourceY + this._dragActor.height) {
x = sourceX;
y = sourceY;
} else {
@ -193,6 +264,45 @@ _Draggable.prototype = {
this._dragActor.reparent(this.actor.get_stage());
this._dragActor.raise_top();
this._dragOrigOpacity = this._dragActor.opacity;
if (this._dragActorOpacity != undefined)
this._dragActor.opacity = this._dragActorOpacity;
this._snapBackX = this._dragStartX + this._dragOffsetX;
this._snapBackY = this._dragStartY + this._dragOffsetY;
this._snapBackScale = this._dragActor.scale_x;
if (this._dragActorMaxSize != undefined) {
let [scaledWidth, scaledHeight] = this._dragActor.get_transformed_size();
let currentSize = Math.max(scaledWidth, scaledHeight);
if (currentSize > this._dragActorMaxSize) {
let scale = this._dragActorMaxSize / currentSize;
let origScale = this._dragActor.scale_x;
let origDragOffsetX = this._dragOffsetX;
let origDragOffsetY = this._dragOffsetY;
// The position of the actor changes as we scale
// around the drag position, but we can't just tween
// to the final position because that tween would
// fight with updates as the user continues dragging
// the mouse; instead we do the position computations in
// an onUpdate() function.
Tweener.addTween(this._dragActor,
{ scale_x: scale * origScale,
scale_y: scale * origScale,
time: SCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate: function() {
let currentScale = this._dragActor.scale_x / origScale;
this._dragOffsetX = currentScale * origDragOffsetX;
this._dragOffsetY = currentScale * origDragOffsetY;
this._dragActor.set_position(this._dragX + this._dragOffsetX,
this._dragY + this._dragOffsetY);
},
onUpdateScope: this });
}
}
},
_maybeStartDrag: function(event) {
@ -211,31 +321,60 @@ _Draggable.prototype = {
_updateDragPosition : function (event) {
let [stageX, stageY] = event.get_coords();
this._dragX = stageX;
this._dragY = stageY;
// If we are dragging, update the position
if (this._dragActor) {
this._dragActor.set_position(stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
// Because we want to find out what other actor is located at the current position of this._dragActor,
// we have to temporarily hide this._dragActor.
this._dragActor.hide();
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
stageX + this._dragOffsetX,
stageY + this._dragOffsetY);
stageX, stageY);
this._dragActor.show();
// We call observers only once per motion with the innermost
// target actor. If necessary, the observer can walk the
// parent itself.
let dragEvent = {
x: stageX,
y: stageY,
dragActor: this._dragActor,
source: this.actor._delegate,
targetActor: target
};
for (let i = 0; i < dragMonitors.length; i++) {
let motionFunc = dragMonitors[i].dragMotion;
if (motionFunc) {
let result = motionFunc(dragEvent);
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
return true;
}
}
}
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
let [targX, targY] = target.get_transformed_position();
let [r, targX, targY] = target.transform_stage_point(stageX, stageY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
target._delegate.handleDragOver(this.actor._delegate, this._dragActor,
(stageX + this._dragOffsetX - targX) / target.scale_x,
(stageY + this._dragOffsetY - targY) / target.scale_y,
event.get_time());
let result = target._delegate.handleDragOver(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time());
if (result != DragMotionResult.CONTINUE) {
global.set_cursor(DRAG_CURSOR_MAP[result]);
return true;
}
}
target = target.get_parent();
}
global.set_cursor(Shell.Cursor.IN_DRAG);
}
return true;
@ -249,19 +388,47 @@ _Draggable.prototype = {
let target = this._dragActor.get_stage().get_actor_at_pos(Clutter.PickMode.ALL,
dropX, dropY);
this._dragActor.show();
// We call observers only once per motion with the innermost
// target actor. If necessary, the observer can walk the
// parent itself.
let dropEvent = {
dropActor: this._dragActor,
targetActor: target,
clutterEvent: event
};
for (let i = 0; i < dragMonitors.length; i++) {
let dropFunc = dragMonitors[i].dragDrop;
if (dropFunc)
switch (dropFunc(dropEvent)) {
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
}
}
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [targX, targY] = target.get_transformed_position();
if (target._delegate.acceptDrop(this.actor._delegate, this._dragActor,
(dropX - targX) / target.scale_x,
(dropY - targY) / target.scale_y,
let [r, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time())) {
// If it accepted the drop without taking the actor,
// destroy it.
if (this._dragActor.get_parent() == this._dragActor.get_stage())
this._dragActor.destroy();
// handle it ourselves.
if (this._dragActor.get_parent() == this._dragActor.get_stage()) {
if (this._restoreOnSuccess) {
this._restoreDragActor(event.get_time());
return true;
} else
this._dragActor.destroy();
}
this._dragInProgress = false;
global.unset_cursor();
this.emit('drag-end', event.get_time(), true);
this._dragComplete();
return true;
@ -275,31 +442,59 @@ _Draggable.prototype = {
return true;
},
// Get position of the drag actor's source if the source is still around,
// or return the original location if the actor itself was being dragged
// or the source is no longer around.
_getRestoreLocation: function() {
let locX = this._snapBackX;
let locY = this._snapBackY;
if (this._dragActorSource && this._dragActorSource.visible)
[locX, locY] = this._dragActorSource.get_transformed_position();
return [locX, locY];
},
_cancelDrag: function(eventTime) {
this._dragInProgress = false;
// Snap back to the actor source if the source is still around, snap back
// to the original location if the actor itself was being dragged or the
// source is no longer around.
let snapBackX = this._dragStartX + this._dragOffsetX;
let snapBackY = this._dragStartY + this._dragOffsetY;
if (this._dragActorSource && this._dragActorSource.visible) {
[snapBackX, snapBackY] = this._dragActorSource.get_transformed_position();
}
let [snapBackX, snapBackY] = this._getRestoreLocation();
this._snapBackInProgress = true;
this._animationInProgress = true;
// No target, so snap back
Tweener.addTween(this._dragActor,
{ x: snapBackX,
y: snapBackY,
scale_x: this._snapBackScale,
scale_y: this._snapBackScale,
opacity: this._dragOrigOpacity,
time: SNAP_BACK_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._onSnapBackComplete,
transition: 'easeOutQuad',
onComplete: this._onAnimationComplete,
onCompleteScope: this,
onCompleteParams: [this._dragActor, eventTime]
});
},
_onSnapBackComplete : function (dragActor, eventTime) {
_restoreDragActor: function(eventTime) {
this._dragInProgress = false;
[restoreX, restoreY] = this._getRestoreLocation();
// fade the actor back in at its original location
this._dragActor.set_position(restoreX, restoreY);
this._dragActor.set_scale(this._snapBackScale, this._snapBackScale);
this._dragActor.opacity = 0;
this._animationInProgress = true;
Tweener.addTween(this._dragActor,
{ opacity: this._dragOrigOpacity,
time: REVERT_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._onAnimationComplete,
onCompleteScope: this,
onCompleteParams: [this._dragActor, eventTime]
});
},
_onAnimationComplete : function (dragActor, eventTime) {
if (this._dragOrigParent) {
dragActor.reparent(this._dragOrigParent);
dragActor.set_scale(this._dragOrigScale, this._dragOrigScale);
@ -307,9 +502,10 @@ _Draggable.prototype = {
} else {
dragActor.destroy();
}
global.unset_cursor();
this.emit('drag-end', eventTime, false);
this._snapBackInProgress = false;
this._animationInProgress = false;
if (!this._buttonDown)
this._dragComplete();
},
@ -326,10 +522,24 @@ Signals.addSignalMethods(_Draggable.prototype);
/**
* makeDraggable:
* @actor: Source actor
* @manualMode: If given, do not automatically start drag and drop on click
* @params: (optional) Additional parameters
*
* Create an object which controls drag and drop for the given actor.
*
* If %manualMode is %true in @params, do not automatically start
* drag and drop on click
*
* If %dragActorMaxSize is present in @params, the drag actor will
* be scaled down to be no larger than that size in pixels.
*
* If %dragActorOpacity is present in @params, the drag actor will
* will be set to have that opacity during the drag.
*
* Note that when the drag actor is the source actor and the drop
* succeeds, the actor scale and opacity aren't reset; if the drop
* target wants to reuse the actor, it's up to the drop target to
* reset these values.
*/
function makeDraggable(actor, manualMode) {
return new _Draggable(actor, manualMode);
function makeDraggable(actor, params) {
return new _Draggable(actor, params);
}

View File

@ -1,20 +1,21 @@
/* -*- 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 St = imports.gi.St;
const Mainloop = imports.mainloop;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const DocInfo = imports.misc.docInfo;
const DND = imports.ui.dnd;
const GenericDisplay = imports.ui.genericDisplay;
const Main = imports.ui.main;
const Search = imports.ui.search;
const MAX_DASH_DOCS = 50;
const DASH_DOCS_ICON_SIZE = 16;
const DEFAULT_SPACING = 4;
@ -37,7 +38,7 @@ DocDisplayItem.prototype = {
GenericDisplay.GenericDisplayItem.prototype._init.call(this);
this._docInfo = docInfo;
this._setItemInfo(docInfo.name, "");
this._setItemInfo(docInfo.name, '');
this._timeoutTime = -1;
this._resetTimeDisplay(currentSecs);
@ -76,12 +77,12 @@ 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() {
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf("image/") != 0)
if (this._docInfo.mimeType == null || this._docInfo.mimeType.indexOf('image/') != 0)
return null;
try {
return Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.NONE,
this._docInfo.uri, -1, -1);
return St.TextureCache.get_default().load_uri_sync(St.TextureCachePolicy.NONE,
this._docInfo.uri, -1, -1);
} catch (e) {
// An exception will be raised when the image format isn't know
/* FIXME: http://bugzilla.gnome.org/show_bug.cgi?id=591480: should
@ -123,7 +124,7 @@ DocDisplay.prototype = {
// We keep a single timeout callback for updating last visited times
// for all the items in the display. This avoids creating individual
// callbacks for each item in the display. So proper time updates
// for individual items and item details depend on the item being
// for individual items and item details depend on the item being
// associated with one of the displays.
this._updateTimeoutTargetTime = -1;
this._updateTimeoutId = 0;
@ -136,7 +137,7 @@ DocDisplay.prototype = {
// but redisplaying right away is cool when we use Zephyr.
// Also, we might be displaying remote documents, like Google Docs, in the future
// which might be edited by someone else.
this._redisplay(false);
this._redisplay(GenericDisplay.RedisplayFlags.NONE);
}));
this.connect('destroy', Lang.bind(this, function (o) {
@ -151,7 +152,8 @@ DocDisplay.prototype = {
_refreshCache : function() {
if (!this._docsStale)
return true;
this._allItems = this._docManager.getItems();
this._allItems = {};
Lang.copyProperties(this._docManager.getInfosByUri(), this._allItems);
this._docsStale = false;
return false;
},
@ -176,13 +178,8 @@ DocDisplay.prototype = {
this._matchedItemKeys = [];
let docIdsToRemove = [];
for (docId in this._allItems) {
// this._allItems[docId].exists() checks if the resource still exists
if (this._allItems[docId].exists()) {
this._matchedItems[docId] = 1;
this._matchedItemKeys.push(docId);
} else {
docIdsToRemove.push(docId);
}
this._matchedItems[docId] = 1;
this._matchedItemKeys.push(docId);
}
for (docId in docIdsToRemove) {
@ -266,26 +263,39 @@ function DashDocDisplayItem(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 () {
this._icon = docInfo.createIcon(DASH_DOCS_ICON_SIZE);
this.actor = new St.Clickable({ style_class: 'recent-docs-item',
reactive: true,
x_align: St.Align.START });
let box = new St.BoxLayout({ style_class: 'recent-docs-item-box' });
this.actor.set_child(box);
box.add(this._icon);
let text = new St.Label({ text: docInfo.name });
box.add(text);
this.actor.connect('clicked', Lang.bind(this, function () {
docInfo.launch();
Main.overview.hide();
}));
this._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;
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
},
getUri: function() {
return this._info.uri;
},
getDragActorSource: function() {
@ -317,12 +327,14 @@ DashDocDisplay.prototype = {
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay));
this._actorsByUri = {};
this._docManager = DocInfo.getDocManager();
this._docManager.connect('changed', Lang.bind(this, function(mgr) {
this._redisplay();
}));
this._redisplay();
this._docManager.connect('changed', Lang.bind(this, this._onDocsChanged));
this._pendingDocsChange = true;
this._checkDocExistence = false;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
@ -351,90 +363,119 @@ DashDocDisplay.prototype = {
_getPreferredHeight: function(actor, forWidth, alloc) {
let children = actor.get_children();
// Two columns, where we go vertically down first. So just take
// the height of half of the children as our preferred height.
// The width of an item is our allocated width, minus spacing, divided in half.
this._itemWidth = Math.floor((forWidth - DEFAULT_SPACING) / 2);
let firstColumnChildren = children.length / 2;
alloc.min_size = 0;
for (let i = 0; i < firstColumnChildren; i++) {
let maxNatural = 0;
for (let i = 0; i < children.length; 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;
}
let [minSize, naturalSize] = child.get_preferred_height(this._itemWidth);
maxNatural = Math.max(maxNatural, naturalSize);
}
this._itemHeight = maxNatural;
let firstColumnChildren = Math.ceil(children.length / 2);
alloc.natural_size = (firstColumnChildren * maxNatural +
(firstColumnChildren - 1) * DEFAULT_SPACING);
},
_allocate: function(actor, box, flags) {
let width = box.x2 - box.x1;
let height = box.y2 - box.y1;
// Make sure this._itemWidth/Height have been computed, even
// if the parent actor didn't check our size before allocating.
// (Not clear if that is required or not as a Clutter
// invariant; this is safe and cheap because of caching.)
actor.get_preferred_height(width);
let children = actor.get_children();
// The width of an item is our allocated width, minus spacing, divided in half.
let itemWidth = Math.floor((width - DEFAULT_SPACING) / 2);
let x = box.x1;
let y = box.y1;
let x = 0;
let y = 0;
let columnIndex = 0;
let i = 0;
// Loop over the children, going vertically down first. When we run
// out of vertical space (our y variable is bigger than box.y2), switch
// to the second column.
for (; i < children.length; i++) {
while (i < children.length) {
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) {
if (y + this._itemHeight > box.y2) {
// Is this the second column, or we're in
// the first column and can't even fit one
// item? In that case, break.
if (columnIndex == 1 || i == 0) {
break;
}
// Set x to the halfway point.
columnIndex += 1;
x = x + itemWidth + DEFAULT_SPACING;
x = x + this._itemWidth + DEFAULT_SPACING;
// And y is back to the top.
y = box.y1;
y = 0;
// Retry this same item, now that we're in the second column.
// By looping back to the top here, we re-test the size
// again for the second column.
continue;
}
let childBox = new Clutter.ActorBox();
childBox.x1 = x;
childBox.y1 = y;
childBox.x2 = childBox.x1 + itemWidth;
childBox.y2 = y + naturalSize;
childBox.x2 = childBox.x1 + this._itemWidth;
childBox.y2 = y + this._itemHeight;
y = childBox.y2 + DEFAULT_SPACING;
child.show();
child.allocate(childBox, flags);
this.actor.set_skip_paint(child, false);
i++;
}
// Everything else didn't fit, just hide it.
for (; i < children.length; i++) {
children[i].hide();
if (this._checkDocExistence) {
// Now we know how many docs we are displaying, queue a check to see if any of them
// have been deleted. If they are deleted, then we'll get a 'changed' signal; since
// we'll now be displaying items we weren't previously, we'll check again to see
// if they were deleted, and so forth and so on.
// TODO: We should change this to ask for as many as we can fit in the given space:
// https://bugzilla.gnome.org/show_bug.cgi?id=603522#c23
this._docManager.queueExistenceCheck(i);
this._checkDocExistence = false;
}
for (; i < children.length; i++)
this.actor.set_skip_paint(children[i], true);
},
_onDocsChanged: function() {
this._checkDocExistence = true;
Main.queueDeferredWork(this._workId);
},
_redisplay: function() {
// Should be kept alive by the _actorsByUri
this.actor.remove_all();
let docs = this._docManager.getItems();
let docUrls = [];
for (let url in docs) {
docUrls.push(url);
let docs = this._docManager.getTimestampOrderedInfos();
for (let i = 0; i < docs.length && i < MAX_DASH_DOCS; i++) {
let doc = docs[i];
let display = this._actorsByUri[doc.uri];
if (display) {
this.actor.add_actor(display.actor);
} else {
let display = new DashDocDisplayItem(doc);
this.actor.add_actor(display.actor);
this._actorsByUri[doc.uri] = display;
}
}
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);
// Any unparented actors must have been deleted
for (let uri in this._actorsByUri) {
let display = this._actorsByUri[uri];
if (display.actor.get_parent() == null) {
display.actor.destroy();
delete this._actorsByUri[uri];
}
}
this.emit('changed');
}
@ -442,3 +483,41 @@ DashDocDisplay.prototype = {
Signals.addSignalMethods(DashDocDisplay.prototype);
function DocSearchProvider() {
this._init();
}
DocSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function(name) {
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
this._docManager = DocInfo.getDocManager();
},
getResultMeta: function(resultId) {
let docInfo = this._docManager.lookupByUri(resultId);
if (!docInfo)
return null;
return { 'id': resultId,
'name': docInfo.name,
'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)};
},
activateResult: function(id) {
let docInfo = this._docManager.lookupByUri(id);
docInfo.launch();
},
getInitialResultSet: function(terms) {
return this._docManager.initialSearch(terms);
},
getSubsearchResultSet: function(previousResults, terms) {
return this._docManager.subsearch(previousResults, terms);
},
expandSearch: function(terms) {
log('TODO expand docs search');
}
};

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

@ -0,0 +1,98 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;;
const GLib = imports.gi.GLib;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Gettext_gtk20 = imports.gettext.domain('gtk20');
const Tweener = imports.ui.tweener;
const Format = imports.misc.format;
// "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);
};
}
// Replace @method with something that throws an error instead
function _blockMethod(method, replacement, reason) {
let match = method.match(/^(.+)\.([^.]+)$/);
if (!match)
throw new Error('Bad method name "' + method + '"');
let proto = 'imports.gi.' + match[1] + '.prototype';
let property = match[2];
if (!global.set_property_mutable(proto, property, true))
throw new Error('Bad method name "' + method + '"');
// eval() is evil in general, but we know it's safe here since
// set_property_mutable() would have failed if proto was
// malformed.
let node = eval(proto);
let msg = 'Do not use "' + method + '".';
if (replacement)
msg += ' Use "' + replacement + '" instead.';
if (reason)
msg += ' (' + reason + ')';
node[property] = function() {
throw new Error(msg);
};
global.set_property_mutable(proto, property, false);
}
function init() {
Tweener.init();
String.prototype.format = Format.format;
// Set the default direction for St widgets (this needs to be done before any use of St)
if (Gettext_gtk20.gettext('default:LTR') == 'default:RTL') {
St.Widget.set_default_direction(St.TextDirection.RTL);
}
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
if (slowdownEnv) {
let factor = parseFloat(slowdownEnv);
if (!isNaN(factor) && factor > 0.0)
St.set_slow_down_factor(factor);
}
_patchContainerClass(St.BoxLayout);
_patchContainerClass(St.Table);
Clutter.Actor.prototype.toString = function() {
return St.describe_actor(this);
};
_blockMethod('Clutter.Event.get_state', 'Shell.get_event_state',
'gjs\'s handling of Clutter.ModifierType is broken. See bug 597292.');
_blockMethod('Gdk.Display.get_device_state', 'global.get_pointer',
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
_blockMethod('Gdk.Window.get_device_position', 'global.get_pointer',
'gjs\'s handling of Gdk.ModifierType is broken. See bug 597292.');
// Now close the back door to prevent extensions from trying to
// abuse it. We can't actually delete it since
// Shell.Global.prototype itself is read-only.
global.set_property_mutable('imports.gi.Shell.Global.prototype', 'set_property_mutable', true);
Shell.Global.prototype.set_property_mutable = undefined;
}

156
js/ui/extensionSystem.js Normal file
View File

@ -0,0 +1,156 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4
};
const ExtensionType = {
SYSTEM: 1,
PER_USER: 2
};
// Maps uuid -> metadata object
const extensionMeta = {};
// Maps uuid -> importer object (extension directory tree)
const extensions = {};
// Array of uuids
var disabledExtensions;
// GFile for user extensions
var userExtensionsDir = null;
function loadExtension(dir, enabled, type) {
let info;
let baseErrorString = 'While loading extension from "' + dir.get_parse_name() + '": ';
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
global.logError(baseErrorString + 'Missing metadata.json');
return;
}
let [success, metadataContents, len, etag] = metadataFile.load_contents(null);
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
global.logError(baseErrorString + 'Failed to parse metadata.json: ' + e);
return;
}
let requiredProperties = ['uuid', 'name', 'description'];
for (let i = 0; i < requiredProperties; i++) {
let prop = requiredProperties[i];
if (!meta[prop]) {
global.logError(baseErrorString + 'missing "' + prop + '" property in metadata.json');
return;
}
}
// Encourage people to add this
if (!meta['url']) {
global.log(baseErrorString + 'Warning: Missing "url" property in metadata.json');
}
let base = dir.get_basename();
if (base != meta.uuid) {
global.logError(baseErrorString + 'uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + base + '"');
return;
}
extensionMeta[meta.uuid] = meta;
extensionMeta[meta.uuid].type = type;
extensionMeta[meta.uuid].path = dir.get_path();
if (!enabled) {
extensionMeta[meta.uuid].state = ExtensionState.DISABLED;
return;
}
// Default to error, we set success as the last step
extensionMeta[meta.uuid].state = ExtensionState.ERROR;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
global.logError(baseErrorString + 'Missing extension.js');
return;
}
let stylesheetPath = null;
let themeContext = St.ThemeContext.get_for_stage(global.stage);
let theme = themeContext.get_theme();
let stylesheetFile = dir.get_child('stylesheet.css');
if (stylesheetFile.query_exists(null)) {
try {
theme.load_stylesheet(stylesheetFile.get_path());
} catch (e) {
global.logError(baseErrorString + 'Stylesheet parse error: ' + e);
return;
}
}
let extensionModule;
try {
global.add_extension_importer('imports.ui.extensionSystem.extensions', meta.uuid, dir.get_path());
extensionModule = extensions[meta.uuid].extension;
} catch (e) {
if (stylesheetPath != null)
theme.unload_stylesheet(stylesheetPath);
global.logError(baseErrorString + e);
return;
}
if (!extensionModule.main) {
global.logError(baseErrorString + 'missing \'main\' function');
return;
}
try {
extensionModule.main();
} catch (e) {
if (stylesheetPath != null)
theme.unload_stylesheet(stylesheetPath);
global.logError(baseErrorString + 'Failed to evaluate main function:' + e);
return;
}
extensionMeta[meta.uuid].state = ExtensionState.ENABLED;
global.log('Loaded extension ' + meta.uuid);
}
function init() {
let userExtensionsPath = GLib.build_filenamev([global.userdatadir, 'extensions']);
userExtensionsDir = Gio.file_new_for_path(userExtensionsPath);
try {
userExtensionsDir.make_directory_with_parents(null);
} catch (e) {
global.logError('' + e);
}
disabledExtensions = global.settings.get_strv('disabled-extensions', -1);
}
function _loadExtensionsIn(dir, type) {
let fileEnum = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NONE, null);
let file, info;
while ((info = fileEnum.next_file(null)) != null) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
continue;
let name = info.get_name();
let enabled = disabledExtensions.indexOf(name) < 0;
let child = dir.get_child(name);
loadExtension(child, enabled, type);
}
fileEnum.close(null);
}
function loadExtensions() {
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
let systemDataDirs = GLib.get_system_data_dirs();
for (let i = 0; i < systemDataDirs.length; i++) {
let dirPath = systemDataDirs[i] + '/gnome-shell/extensions';
let dir = Gio.file_new_for_path(dirPath);
if (dir.query_exists(null))
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
}
}

View File

@ -1,57 +1,21 @@
/* -*- 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 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 St = imports.gi.St;
const Button = imports.ui.button;
const DND = imports.ui.dnd;
const Link = imports.ui.link;
const Main = imports.ui.main;
const RedisplayFlags = { NONE: 0,
RESET_CONTROLS: 1 << 0,
FULL: 1 << 1,
SUBSEARCH: 1 << 2 };
SUBSEARCH: 1 << 2,
IMMEDIATE: 1 << 3 };
const ITEM_DISPLAY_NAME_COLOR = new Clutter.Color();
ITEM_DISPLAY_NAME_COLOR.from_pixel(0xffffffff);
const ITEM_DISPLAY_DESCRIPTION_COLOR = new Clutter.Color();
ITEM_DISPLAY_DESCRIPTION_COLOR.from_pixel(0xffffffbb);
const ITEM_DISPLAY_BACKGROUND_COLOR = new Clutter.Color();
ITEM_DISPLAY_BACKGROUND_COLOR.from_pixel(0x00000000);
const ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR = new Clutter.Color();
ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR.from_pixel(0x4f6fadaa);
const DISPLAY_CONTROL_SELECTED_COLOR = new Clutter.Color();
DISPLAY_CONTROL_SELECTED_COLOR.from_pixel(0x112288ff);
const PREVIEW_BOX_BACKGROUND_COLOR = new Clutter.Color();
PREVIEW_BOX_BACKGROUND_COLOR.from_pixel(0xADADADf0);
const DEFAULT_PADDING = 4;
const ITEM_DISPLAY_HEIGHT = 50;
// Used by subclasses
const ITEM_DISPLAY_ICON_SIZE = 48;
const ITEM_DISPLAY_PADDING = 1;
const ITEM_DISPLAY_PADDING_RIGHT = 2;
const DEFAULT_COLUMN_GAP = 6;
const PREVIEW_ICON_SIZE = 96;
const PREVIEW_BOX_PADDING = 6;
const PREVIEW_BOX_SPACING = DEFAULT_PADDING;
const PREVIEW_BOX_CORNER_RADIUS = 10;
// how far relative to the full item width the preview box should be placed
const PREVIEW_PLACING = 3/4;
const PREVIEW_DETAILS_MIN_WIDTH = PREVIEW_ICON_SIZE * 2;
const INFORMATION_BUTTON_SIZE = 16;
/* This is a virtual class that represents a single display item containing
* a name, a description, and an icon. It allows selecting an item and represents
@ -63,12 +27,8 @@ function GenericDisplayItem() {
GenericDisplayItem.prototype = {
_init: function() {
this.actor = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: ITEM_DISPLAY_PADDING,
reactive: true,
background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
corner_radius: 4,
height: ITEM_DISPLAY_HEIGHT });
this.actor = new St.BoxLayout({ style_class: 'generic-display-item',
reactive: true });
this.actor._delegate = this;
this.actor.connect('button-release-event',
@ -80,47 +40,21 @@ GenericDisplayItem.prototype = {
}));
let draggable = DND.makeDraggable(this.actor);
draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
this._infoContent = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: DEFAULT_PADDING });
this.actor.append(this._infoContent, Big.BoxPackFlags.EXPAND);
this._iconBin = new St.Bin();
this.actor.add(this._iconBin);
this._iconBox = new Big.Box();
this._infoContent.append(this._iconBox, Big.BoxPackFlags.NONE);
this._infoText = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: DEFAULT_PADDING });
this._infoContent.append(this._infoText, Big.BoxPackFlags.EXPAND);
let infoIconUri = "file://" + global.imagedir + "info.svg";
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(Shell.TextureCachePolicy.FOREVER,
infoIconUri,
INFORMATION_BUTTON_SIZE,
INFORMATION_BUTTON_SIZE);
this._informationButton = new Button.IconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
let buttonBox = new Big.Box({ width: INFORMATION_BUTTON_SIZE + 2 * DEFAULT_PADDING,
height: INFORMATION_BUTTON_SIZE,
padding_left: DEFAULT_PADDING, padding_right: DEFAULT_PADDING,
y_align: Big.BoxAlignment.CENTER });
buttonBox.append(this._informationButton.actor, Big.BoxPackFlags.NONE);
this.actor.append(buttonBox, Big.BoxPackFlags.END);
// Connecting to the button-press-event for the information button ensures that the actor,
// which is a draggable actor, does not get the button-press-event and doesn't initiate
// the dragging, which then prevents us from getting the button-release-event for the button.
this._informationButton.actor.connect('button-press-event',
Lang.bind(this,
function() {
return true;
}));
this._informationButton.actor.connect('button-release-event',
Lang.bind(this,
function() {
// Selects the item by highlighting it and displaying its details
this.emit('show-details');
return true;
}));
this._infoText = new St.BoxLayout({ style_class: 'generic-display-item-text',
vertical: true });
this.actor.add(this._infoText, { expand: true, y_fill: false });
this._name = null;
this._description = null;
@ -152,24 +86,13 @@ GenericDisplayItem.prototype = {
//// Public methods ////
// Shows the information button when the item was drawn under the mouse pointer.
onDrawnUnderPointer: function() {
this._informationButton.show();
},
// Highlights the item by setting a different background color than the default
// if isSelected is true, removes the highlighting otherwise.
markSelected: function(isSelected) {
let color;
if (isSelected) {
color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR;
this._informationButton.forceShow(true);
}
else {
color = ITEM_DISPLAY_BACKGROUND_COLOR;
this._informationButton.forceShow(false);
}
this.actor.background_color = color;
if (isSelected)
this.actor.add_style_pseudo_class('selected');
else
this.actor.remove_style_pseudo_class('selected');
},
/*
@ -178,44 +101,36 @@ GenericDisplayItem.prototype = {
*/
createDetailsActor: function() {
let details = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PREVIEW_BOX_SPACING });
let details = new St.BoxLayout({ style_class: 'generic-display-container',
vertical: true });
let mainDetails = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: PREVIEW_BOX_SPACING });
let mainDetails = new St.BoxLayout({ style_class: 'generic-display-container' });
// Inner box with name and description
let textDetails = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
spacing: PREVIEW_BOX_SPACING });
let detailsName = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans bold 14px",
line_wrap: true,
text: this._name.text });
textDetails.append(detailsName, Big.BoxPackFlags.NONE);
let textDetails = new St.BoxLayout({ style_class: 'generic-display-details',
vertical: true });
let detailsName = new St.Label({ style_class: 'generic-display-details-name',
text: this._name.text });
textDetails.add(detailsName);
let detailsDescription = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans 14px",
line_wrap: true,
text: this._description.text });
textDetails.append(detailsDescription, Big.BoxPackFlags.NONE);
let detailsDescription = new St.Label({ text: this._description.text });
textDetails.add(detailsDescription);
this._detailsDescriptions.push(detailsDescription);
mainDetails.append(textDetails, Big.BoxPackFlags.EXPAND);
mainDetails.add(textDetails, { expand: true });
let previewIcon = this._createPreviewIcon();
let largePreviewIcon = this._createLargePreviewIcon();
if (previewIcon != null && largePreviewIcon == null) {
mainDetails.prepend(previewIcon, Big.BoxPackFlags.NONE);
mainDetails.insert_actor(previewIcon, 0);
}
details.append(mainDetails, Big.BoxPackFlags.NONE);
details.add(mainDetails);
if (largePreviewIcon != null) {
let largePreview = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL });
largePreview.append(largePreviewIcon, Big.BoxPackFlags.NONE);
details.append(largePreview, Big.BoxPackFlags.NONE);
details.add(largePreviewIcon);
}
return details;
@ -223,14 +138,14 @@ GenericDisplayItem.prototype = {
// Destroys the item.
destroy: function() {
this.actor.destroy();
this.actor.destroy();
},
//// Pure virtual public methods ////
// Performes an action associated with launching this item, such as opening a file or an application.
launch: function() {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
//// Protected methods ////
@ -260,20 +175,15 @@ GenericDisplayItem.prototype = {
}
this._icon = this._createIcon();
this._iconBox.append(this._icon, Big.BoxPackFlags.NONE);
this._iconBin.set_child(this._icon);
this._name = new Clutter.Text({ color: ITEM_DISPLAY_NAME_COLOR,
font_name: "Sans 14px",
ellipsize: Pango.EllipsizeMode.END,
text: nameText });
this._infoText.append(this._name, Big.BoxPackFlags.EXPAND);
this._name = new St.Label({ style_class: 'generic-display-item-name',
text: nameText });
this._infoText.add(this._name);
this._description = new Clutter.Text({ color: ITEM_DISPLAY_DESCRIPTION_COLOR,
font_name: "Sans 12px",
ellipsize: Pango.EllipsizeMode.END,
text: descriptionText ? descriptionText : ""
});
this._infoText.append(this._description, Big.BoxPackFlags.EXPAND);
this._description = new St.Label({ style_class: 'generic-display-item-description',
text: descriptionText ? descriptionText : '' });
this._infoText.add(this._description);
},
// Sets the description text for the item, including the description text
@ -299,22 +209,15 @@ GenericDisplayItem.prototype = {
// Returns an icon for the item.
_createIcon: function() {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
// Returns a preview icon for the item.
_createPreviewIcon: function() {
throw new Error("Not implemented");
},
throw new Error('Not implemented');
}
//// Private methods ////
// Hides the information button once the item starts being dragged.
_onDragBegin : function (draggable, time) {
// For some reason, we are not getting leave-event signal when we are dragging an item,
// so we should remove the link manually.
this._informationButton.actor.hide();
}
};
Signals.addSignalMethods(GenericDisplayItem.prototype);
@ -331,16 +234,16 @@ GenericDisplay.prototype = {
this._search = '';
this._expanded = false;
this._maxItemsPerPage = null;
this._list = new Shell.OverflowList({ spacing: 6.0,
item_height: ITEM_DISPLAY_HEIGHT });
this.actor = new St.ScrollView({ x_fill: true,
y_fill: false,
vshadows: true });
this._list = new St.BoxLayout({ style_class: 'generic-display-container',
vertical: true });
this.actor.add_actor(this._list);
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
this._list.connect('notify::n-pages', Lang.bind(this, function () {
this._updateDisplayControl(true);
}));
this._list.connect('notify::page', Lang.bind(this, function () {
this._updateDisplayControl(false);
}));
this._pendingRedisplay = RedisplayFlags.NONE;
this.actor.connect('notify::mapped', Lang.bind(this, this._onMappedNotify));
// map<itemId, Object> where Object represents the item info
this._allItems = {};
@ -352,13 +255,6 @@ GenericDisplay.prototype = {
this._displayedItems = {};
this._openDetailIndex = -1;
this._selectedIndex = -1;
// These two are public - .actor is the normal "actor subclass" property,
// but we also expose a .displayControl actor which is separate.
// See also getNavigationArea.
this.actor = this._list;
this.displayControl = new Big.Box({ background_color: ITEM_DISPLAY_BACKGROUND_COLOR,
spacing: 12,
orientation: Big.BoxOrientation.HORIZONTAL});
},
//// Public methods ////
@ -366,12 +262,18 @@ GenericDisplay.prototype = {
// Sets the search string and displays the matching items.
setSearch: function(text) {
let lowertext = text.toLowerCase();
if (lowertext == this._search)
if (lowertext == this._search) {
return;
let flags = RedisplayFlags.RESET_CONTROLS;
}
let flags = RedisplayFlags.IMMEDIATE;
if (this._search != '') {
if (lowertext.indexOf(this._search) == 0)
// Because we combine search terms with OR, we have to be sure that no new term
// was introduced before deciding that the new search results will be a subset of
// the existing search results.
if (lowertext.indexOf(this._search) == 0 &&
lowertext.split(/\s+/).length == this._search.split(/\s+/).length) {
flags |= RedisplayFlags.SUBSEARCH;
}
}
this._search = lowertext;
this._redisplay(flags);
@ -391,7 +293,7 @@ GenericDisplay.prototype = {
// to the bottom one. Returns true if the selection actually moved up, false if it wrapped
// around to the bottom.
selectUp: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
let selectedUp = true;
let prev = this._selectedIndex - 1;
if (this._selectedIndex <= 0) {
@ -406,7 +308,7 @@ GenericDisplay.prototype = {
// to the top one. Returns true if the selection actually moved down, false if it wrapped
// around to the top.
selectDown: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
let selectedDown = true;
let next = this._selectedIndex + 1;
if (this._selectedIndex == count - 1) {
@ -425,7 +327,7 @@ GenericDisplay.prototype = {
// Selects the last item among the displayed items.
selectLastItem: function() {
let count = this._list.displayedCount;
let count = this._getVisibleCount();
if (this.hasItems())
this._selectIndex(count - 1);
},
@ -445,7 +347,7 @@ GenericDisplay.prototype = {
// 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);
// log('this._mathedItems.length: ' + this._matchedItems.length + ' this._list.displayedCount ' + this._list.displayedCount);
return this._matchedItemKeys.length > 0;
},
@ -462,6 +364,7 @@ GenericDisplay.prototype = {
resetState: function() {
this._filterReset();
this._openDetailIndex = -1;
this.actor.get_vscroll_bar().get_adjustment().value = 0;
},
// Returns an actor which acts as a sidebar; this is used for
@ -475,29 +378,21 @@ GenericDisplay.prototype = {
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 ////
_redisplayFull: function() {
_recreateDisplayItems: function() {
this._removeAllDisplayItems();
this._setDefaultList();
for (let itemId in this._allItems) {
this._addDisplayItem(itemId);
}
},
// Creates a display item based on the information associated with itemId
// and adds it to the displayed items.
// and adds it to the list of displayed items, but does not yet display it.
_addDisplayItem : function(itemId) {
if (this._displayedItems.hasOwnProperty(itemId)) {
log("Tried adding a display item for " + itemId + ", but an item with this item id is already among displayed items.");
log('Tried adding a display item for ' + itemId + ', but an item with this item id is already among displayed items.');
return;
}
@ -508,14 +403,14 @@ GenericDisplay.prototype = {
Lang.bind(this,
function() {
// update the selection
this._selectIndex(this._list.get_actor_index(displayItem.actor));
this._selectIndex(this._list.get_children().indexOf(displayItem.actor));
this.activateSelected();
}));
displayItem.connect('show-details',
Lang.bind(this,
function() {
let index = this._list.get_actor_index(displayItem.actor);
let index = this._list.get_children().indexOf(displayItem.actor);
/* Close the details pane if already open */
if (index == this._openDetailIndex) {
this._openDetailIndex = -1;
@ -525,15 +420,15 @@ GenericDisplay.prototype = {
this.emit('show-details', index);
}
}));
this._list.add_actor(displayItem.actor);
this._displayedItems[itemId] = displayItem;
},
// Removes an item identifed by the itemId from the displayed items.
_removeDisplayItem: function(itemId) {
let count = this._list.displayedCount;
let children = this._list.get_children();
let count = children.length;
let displayItem = this._displayedItems[itemId];
let displayItemIndex = this._list.get_actor_index(displayItem.actor);
let displayItemIndex = children.indexOf(displayItem.actor);
if (this.hasSelected() && count == 1) {
this.unsetSelected();
@ -556,7 +451,7 @@ GenericDisplay.prototype = {
// Return true if there's an active search or other constraint
// on the list
_filterActive: function() {
return this._search != "";
return this._search != '';
},
// Called when we are resetting state
@ -628,94 +523,83 @@ GenericDisplay.prototype = {
/*
* Updates the displayed items, applying the search string if one exists.
* @flags: Flags controlling redisplay behavior as follows:
* RESET_CONTROLS - indicates if the page selection should be reset when displaying the matching results.
* We reset the page selection when the change in results was initiated by the user by
* entering a different search criteria or by viewing the results list in a different
* size mode, but we keep the page selection the same if the results got updated on
* their own while the user was browsing through the result pages.
* SUBSEARCH - Indicates that the current _search is a superstring of the previous
* one, which implies we only need to re-search through previous results.
* FULL - Indicates that we need recreate all displayed items.
* IMMEDIATE - Do the full redisplay even if we're not mapped. This is useful
* if you want to get the number of matched items and show/hide a section based on
* that number.
*/
_redisplay: function(flags) {
let resetPage = (flags & RedisplayFlags.RESET_CONTROLS) > 0;
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) > 0;
let fullReload = (flags & RedisplayFlags.FULL) > 0;
let immediate = (flags & RedisplayFlags.IMMEDIATE) != 0;
if (!immediate && !this.actor.mapped) {
this._pendingRedisplay |= flags;
return;
}
let isSubSearch = (flags & RedisplayFlags.SUBSEARCH) != 0;
let fullReload = (flags & RedisplayFlags.FULL) != 0;
let hadSelected = this.hasSelected();
this.unsetSelected();
if (!this._initialLoadComplete || !this._refreshCache())
if (!this._initialLoadComplete)
fullReload = true;
if (!this._refreshCache())
fullReload = true;
if (fullReload) {
this._recreateDisplayItems();
this._initialLoadComplete = true;
this._redisplayFull();
} if (isSubSearch) {
}
if (isSubSearch) {
this._redisplaySubSearch();
} else {
this._redisplayReordering();
}
if (resetPage)
this._list.page = 0;
if (hadSelected) {
this._selectedIndex = -1;
this.selectFirstItem();
}
Mainloop.idle_add(Lang.bind(this, this._checkInformationIcon),
Meta.PRIORITY_BEFORE_REDRAW);
this.emit('redisplayed');
},
// 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.
_checkInformationIcon: 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;
},
//// Pure virtual protected methods ////
// Performs the steps needed to have the latest information about the items.
// Implementation should return %true if we are up to date, and %false
// if a full reload occurred.
_refreshCache: function() {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
// Sets the list of the displayed items based on the default sorting order.
// The default sorting order is specific to each implementing class.
_setDefaultList: function() {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
// Compares items associated with the item ids based on the order in which the
// items should be displayed.
// Intended to be used as a compareFunction for array.sort().
// Returns an integer value indicating the result of the comparison.
// Compares items associated with the item ids based on the order in which the
// items should be displayed.
// Intended to be used as a compareFunction for array.sort().
// Returns an integer value indicating the result of the comparison.
_compareItems: function(itemIdA, itemIdB) {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
// Checks if the item info can be a match for the search string.
// Returns a boolean flag indicating if that's the case.
_isInfoMatching: function(itemInfo, search) {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
// Creates a display item based on itemInfo.
_createDisplayItem: function(itemInfo) {
throw new Error("Not implemented");
throw new Error('Not implemented');
},
//// Private methods ////
@ -756,59 +640,10 @@ GenericDisplay.prototype = {
return matchScores;
},
/*
* Updates the display control to reflect the matched items set and the page selected.
*
* resetDisplayControl - indicates if the display control should be re-created because
* the results or the space allocated for them changed. If it's false,
* the existing display control is used and only the page links are
* updated to reflect the current page selection.
*/
_updateDisplayControl: function(resetDisplayControl) {
if (resetDisplayControl) {
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,
font_name: "Sans Bold 16px",
text: (i+1) + "",
reactive: (i == pageNumber) ? false : true});
this.displayControl.append(pageControl.actor, Big.BoxPackFlags.NONE);
// we use pageNumberLocalScope to get the page number right in the callback function
let pageNumberLocalScope = i;
pageControl.connect('clicked',
Lang.bind(this,
function(o, event) {
this.displayPage(pageNumberLocalScope);
}));
}
} else {
let pageControlActors = this.displayControl.get_children();
for (let i = 0; i < pageControlActors.length; i++) {
let pageControlActor = pageControlActors[i];
if (i == this._list.page) {
pageControlActor.color = DISPLAY_CONTROL_SELECTED_COLOR;
pageControlActor.reactive = false;
} else {
pageControlActor.color = ITEM_DISPLAY_DESCRIPTION_COLOR;
pageControlActor.reactive = true;
}
}
}
if (this.hasSelected()) {
this.selectFirstItem();
}
},
// Returns a display item based on its index in the ordering of the
// display children.
_findDisplayedByIndex: function(index) {
let actor = this._list.get_displayed_actor(index);
let actor = this._list.get_children()[index];
return this._findDisplayedByActor(actor);
},
@ -834,12 +669,24 @@ GenericDisplay.prototype = {
this._selectedIndex = index;
if (index < 0)
return
return;
// Mark the new item as selected and create its details pane
let item = this._findDisplayedByIndex(index);
item.markSelected(true);
this.emit('selected');
},
_getVisibleCount: function() {
return this._list.get_n_children();
},
_onMappedNotify: function () {
let mapped = this.actor.mapped;
if (mapped && this._pendingRedisplay > RedisplayFlags.NONE)
this._redisplay(this._pendingRedisplay);
this._pendingRedisplay = RedisplayFlags.NONE;
}
};

285
js/ui/iconGrid.js Normal file
View File

@ -0,0 +1,285 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Lang = imports.lang;
const Params = imports.misc.params;
const ICON_SIZE = 48;
function BaseIcon(label, createIcon) {
this._init(label, createIcon);
}
BaseIcon.prototype = {
_init : function(label, params) {
params = Params.parse(params, { createIcon: null,
setSizeManually: false });
this.actor = new St.Bin({ style_class: 'overview-icon',
x_fill: true,
y_fill: true });
this.actor._delegate = this;
this.actor.connect('style-changed',
Lang.bind(this, this._onStyleChanged));
this._spacing = 0;
let box = new Shell.GenericContainer();
box.connect('allocate', Lang.bind(this, this._allocate));
box.connect('get-preferred-width',
Lang.bind(this, this._getPreferredWidth));
box.connect('get-preferred-height',
Lang.bind(this, this._getPreferredHeight));
this.actor.set_child(box);
this.iconSize = ICON_SIZE;
this._iconBin = new St.Bin();
box.add_actor(this._iconBin);
this._name = new St.Label({ text: label });
box.add_actor(this._name);
if (params.createIcon)
this.createIcon = params.createIcon;
this._setSizeManually = params.setSizeManually;
this.icon = this.createIcon(this.iconSize);
this._iconBin.set_child(this.icon);
},
_allocate: function(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(-1);
let [iconMinHeight, iconNatHeight] = this._iconBin.get_preferred_height(-1);
let preferredHeight = labelNatHeight + this._spacing + iconNatHeight;
let labelHeight = availHeight >= preferredHeight ? labelNatHeight
: labelMinHeight;
let iconSize = availHeight - this._spacing - labelHeight;
let iconPadding = (availWidth - iconSize) / 2;
let childBox = new Clutter.ActorBox();
childBox.x1 = iconPadding;
childBox.y1 = 0;
childBox.x2 = availWidth - iconPadding;
childBox.y2 = iconSize;
this._iconBin.allocate(childBox, flags);
childBox.x1 = 0;
childBox.x2 = availWidth;
childBox.y1 = iconSize + this._spacing;
childBox.y2 = childBox.y1 + labelHeight;
this._name.allocate(childBox, flags);
},
_getPreferredWidth: function(actor, forHeight, alloc) {
this._getPreferredHeight(actor, -1, alloc);
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let [iconMinHeight, iconNatHeight] = this._iconBin.get_preferred_height(forWidth);
let [labelMinHeight, labelNatHeight] = this._name.get_preferred_height(forWidth);
alloc.min_size = iconMinHeight + this._spacing + labelMinHeight;
alloc.natural_size = iconNatHeight + this._spacing + labelNatHeight;
},
// This can be overridden by a subclass, or by the createIcon
// parameter to _init()
createIcon: function(size) {
throw new Error('no implementation of createIcon in ' + this);
},
setIconSize: function(size) {
if (!this._setSizeManually)
throw new Error('setSizeManually has to be set to use setIconsize');
this._setIconSize(size);
},
_setIconSize: function(size) {
if (size == this.iconSize)
return;
this.icon.destroy();
this.iconSize = size;
this.icon = this.createIcon(this.iconSize);
this._iconBin.child = this.icon;
},
_onStyleChanged: function() {
let success, len;
let node = this.actor.get_theme_node();
[success, len] = node.get_length('spacing', false);
if (success)
this._spacing = spacing;
if (this._setSizeManually)
return;
[success, len] = node.get_length('icon-size', false);
if (success)
this._setIconSize(len);
}
};
function IconGrid(params) {
this._init(params);
}
IconGrid.prototype = {
_init: function(params) {
params = Params.parse(params, { rowLimit: null, columnLimit: null });
this._rowLimit = params.rowLimit;
this._colLimit = params.columnLimit;
this.actor = new St.BoxLayout({ style_class: 'icon-grid',
vertical: true });
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._item_size = ICON_SIZE;
this._grid = new Shell.GenericContainer();
this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
this.actor.connect('style-changed', Lang.bind(this, this._onStyleChanged));
this._grid.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._grid.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._grid.connect('allocate', Lang.bind(this, this._allocate));
},
_getPreferredWidth: function (grid, forHeight, alloc) {
let children = this._grid.get_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
children.length)
: children.length;
let totalSpacing = Math.max(0, nColumns - 1) * this._spacing;
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
alloc.min_size = this._item_size;
alloc.natural_size = nColumns * this._item_size + totalSpacing;
},
_getPreferredHeight: function (grid, forWidth, alloc) {
let children = this._grid.get_children();
let [nColumns, usedWidth] = this._computeLayout(forWidth);
let nRows;
if (nColumns > 0)
nRows = Math.ceil(children.length / nColumns);
else
nRows = 0;
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * this._spacing;
let height = nRows * this._item_size + totalSpacing;
alloc.min_size = height;
alloc.natural_size = height;
},
_allocate: function (grid, box, flags) {
let children = this._grid.get_children();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let overallPaddingX = Math.floor((availWidth - usedWidth) / 2);
let x = box.x1 + overallPaddingX;
let y = box.y1;
let columnIndex = 0;
let rowIndex = 0;
for (let i = 0; i < children.length; i++) {
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight]
= children[i].get_preferred_size();
/* Center the item in its allocation horizontally */
let width = Math.min(this._item_size, childNaturalWidth);
let childXSpacing = Math.max(0, width - childNaturalWidth) / 2;
let height = Math.min(this._item_size, childNaturalHeight);
let childYSpacing = Math.max(0, height - childNaturalHeight) / 2;
let childBox = new Clutter.ActorBox();
if (St.Widget.get_default_direction() == St.TextDirection.RTL) {
let _x = box.x2 - (x + width);
childBox.x1 = Math.floor(_x - childXSpacing);
} else {
childBox.x1 = Math.floor(x + childXSpacing);
}
childBox.y1 = Math.floor(y + childYSpacing);
childBox.x2 = childBox.x1 + width;
childBox.y2 = childBox.y1 + height;
if (this._rowLimit && rowIndex >= this._rowLimit) {
this._grid.set_skip_paint(children[i], true);
} else {
children[i].allocate(childBox, flags);
this._grid.set_skip_paint(children[i], false);
}
columnIndex++;
if (columnIndex == nColumns) {
columnIndex = 0;
rowIndex++;
}
if (columnIndex == 0) {
y += this._item_size + this._spacing;
x = box.x1 + overallPaddingX;
} else {
x += this._item_size + this._spacing;
}
}
},
_computeLayout: function (forWidth) {
let children = this._grid.get_children();
let nColumns = 0;
let usedWidth = 0;
while ((this._colLimit == null || nColumns < this._colLimit) &&
(usedWidth + this._item_size <= forWidth)) {
usedWidth += this._item_size + this._spacing;
nColumns += 1;
}
if (nColumns > 0)
usedWidth -= this._spacing;
return [nColumns, usedWidth];
},
_onStyleChanged: function() {
let themeNode = this.actor.get_theme_node();
let [success, len] = themeNode.get_length('spacing', false);
if (success)
this._spacing = len;
[success, len] = themeNode.get_length('-shell-grid-item-size', false);
if (success)
this._item_size = len;
this._grid.queue_relayout();
},
removeAll: function () {
this._grid.get_children().forEach(Lang.bind(this, function (child) {
child.destroy();
}));
},
addItem: function(actor) {
this._grid.add_actor(actor);
},
getItemAtIndex: function(index) {
return this._grid.get_children()[index];
},
visibleItemsCount: function() {
return this._grid.get_children().length - this._grid.get_n_skip_paint();
}
};

View File

@ -1,19 +1,20 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
const SHADE_COLOR = new Clutter.Color();
SHADE_COLOR.from_pixel(0x00000044);
/**
* Lightbox:
* @container: parent Clutter.Container
* @width: (optional) shade actor width
* @height: (optional) shade actor height
* @params: (optional) additional parameters:
* - inhibitEvents: whether to inhibit events for @container
* - width: shade actor width
* - height: shade actor height
* - fadeTime: seconds used to fade in/out
*
* Lightbox creates a dark translucent "shade" actor to hide the
* contents of @container, and allows you to specify particular actors
@ -27,30 +28,37 @@ SHADE_COLOR.from_pixel(0x00000044);
*
* By default, the shade window will have the height and width of
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height
* this by passing an explicit width and height in @params.
*/
function Lightbox(container, width, height) {
this._init(container, width, height);
function Lightbox(container, params) {
this._init(container, params);
}
Lightbox.prototype = {
_init : function(container, width, height) {
_init : function(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
height: null,
fadeTime: null
});
this._container = container;
this._children = container.get_children();
this.actor = new Clutter.Rectangle({ color: SHADE_COLOR,
x: 0,
y: 0,
border_width: 0,
reactive: true });
this._fadeTime = params.fadeTime;
this.actor = new St.Bin({ x: 0,
y: 0,
style_class: 'lightbox',
reactive: params.inhibitEvents });
container.add_actor(this.actor);
this.actor.raise_top();
this.actor.hide();
this._destroySignalId = this.actor.connect('destroy', Lang.bind(this, this.destroy));
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
if (width && height) {
this.actor.width = width;
this.actor.height = height;
if (params.width && params.height) {
this.actor.width = params.width;
this.actor.height = params.height;
this._allocationChangedSignalId = 0;
} else {
this.actor.width = container.width;
@ -65,8 +73,13 @@ Lightbox.prototype = {
},
_allocationChanged : function(container, box, flags) {
this.actor.width = this._container.width;
this.actor.height = this._container.height;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this.actor.width = this.width;
this.actor.height = this.height;
return false;
}));
this.width = this._container.width;
this.height = this._container.height;
},
_actorAdded : function(container, newChild) {
@ -91,6 +104,35 @@ Lightbox.prototype = {
}
},
show: function() {
if (this._fadeTime) {
this.actor.opacity = 0;
Tweener.addTween(this.actor,
{ opacity: 255,
time: this._fadeTime,
transition: 'easeOutQuad'
});
} else {
this.actor.opacity = 255;
}
this.actor.show();
},
hide: function() {
if (this._fadeTime) {
Tweener.addTween(this.actor,
{ opacity: 0,
time: this._fadeTime,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this.actor.hide();
})
});
} else {
this.actor.hide();
}
},
_actorRemoved : function(container, child) {
let index = this._children.indexOf(child);
if (index != -1) // paranoia
@ -134,18 +176,24 @@ Lightbox.prototype = {
/**
* destroy:
*
* Destroys the lightbox. This is called automatically if the
* lightbox's container is destroyed.
* Destroys the lightbox.
*/
destroy : function() {
this.actor.destroy();
},
/**
* _onDestroy:
*
* This is called when the lightbox' actor is destroyed, either
* by destroying its container or by explicitly calling this.destroy().
*/
_onDestroy: function() {
if (this._allocationChangedSignalId != 0)
this._container.disconnect(this._allocationChangedSignalId);
this._container.disconnect(this._actorAddedSignalId);
this._container.disconnect(this._actorRemovedSignalId);
this.actor.disconnect(this._destroySignalId);
this.highlight(null);
this.actor.destroy();
}
};

View File

@ -1,80 +1,23 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
// Link is a clickable link. Right now it just handles properly capturing
// press and release events and short-circuiting the button handling in
// ClutterText, but more features like different colors for hover/pressed states
// or a different mouse cursor could be implemented.
//
// The properties passed in are forwarded to the Clutter.Text() constructor,
// so can include, 'text', 'font_name', etc.
function Link(props) {
this._init(props);
}
Link.prototype = {
_init : function(props) {
let realProps = { reactive: true };
let realProps = { reactive: true,
track_hover: true,
style_class: 'shell-link' };
// The user can pass in reactive: false to override the above and get
// a non-reactive link (a link to the current page, perhaps)
Lang.copyProperties(props, realProps);
Lang.copyProperties(props, realProps);
this.actor = new Clutter.Text(realProps);
this.actor._delegate = this;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
this._buttonDown = false;
this._havePointer = false;
},
// Update the text of the link
setText : function(text) {
this.actor.text = text;
},
// We want to react on buttonDown, but if we override button-release-event for
// ClutterText, but not button-press-event, we get a stuck grab. Tracking
// buttonDown and doing the grab isn't really necessary, but doing it makes
// the behavior perfectly correct if the user clicks on one actor, drags
// to another and releases - that should not trigger either actor.
_onButtonPress : function(actor, event) {
this._buttonDown = true;
this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
Clutter.grab_pointer(actor);
return true;
},
_onButtonRelease : function(actor, event) {
if (this._buttonDown) {
this._buttonDown = false;
Clutter.ungrab_pointer(actor);
if (this._havePointer)
this.emit('clicked');
}
return true;
},
_onEnter : function(actor, event) {
if (event.get_source() == actor)
this._havePointer = true;
return false;
},
_onLeave : function(actor, event) {
if (event.get_source() == actor)
this._havePointer = false;
return false;
this.actor = new St.Button(realProps);
}
};

File diff suppressed because it is too large Load Diff

1431
js/ui/magnifier.js Normal file

File diff suppressed because it is too large Load Diff

378
js/ui/magnifierDBus.js Normal file
View File

@ -0,0 +1,378 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const Main = imports.ui.main;
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
const MAG_SERVICE_PATH = '/org/gnome/Magnifier';
const ZOOM_SERVICE_NAME = 'org.gnome.Magnifier.ZoomRegion';
const ZOOM_SERVICE_PATH = '/org/gnome/Magnifier/ZoomRegion';
// Subset of gnome-mag's Magnifier dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
const MagnifierIface = {
name: MAG_SERVICE_NAME,
methods: [
{ name: 'setActive', inSignature: 'b', outSignature: '' },
{ name: 'isActive', inSignature: '', outSignature: 'b' },
{ name: 'showCursor', inSignature: '', outSignature: '' },
{ name: 'hideCursor', inSignature: '', outSignature: '' },
{ name: 'createZoomRegion', inSignature: 'ddaiai', outSignature: 'o' },
{ name: 'addZoomRegion', inSignature: 'o', outSignature: 'b' },
{ name: 'getZoomRegions', inSignature: '', outSignature: 'ao' },
{ name: 'clearAllZoomRegions', inSignature: '', outSignature: '' },
{ name: 'fullScreenCapable', inSignature: '', outSignature: 'b' },
{ name: 'setCrosswireSize', inSignature: 'i', outSignature: '' },
{ name: 'getCrosswireSize', inSignature: '', outSignature: 'i' },
{ name: 'setCrosswireLength', inSignature: 'i', outSignature: '' },
{ name: 'getCrosswireLength', inSignature: '', outSignature: 'i' },
{ name: 'setCrosswireClip', inSignature: 'b', outSignature: '' },
{ name: 'getCrosswireClip', inSignature: '', outSignature: 'b' },
{ name: 'setCrosswireColor', inSignature: 'u', outSignature: '' },
{ name: 'getCrosswireColor', inSignature: '', outSignature: 'u' }
],
signals: [],
properties: []
};
// Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded. See:
// http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
const ZoomRegionIface = {
name: ZOOM_SERVICE_NAME,
methods: [
{ name: 'setMagFactor', inSignature: 'dd', outSignature: ''},
{ name: 'getMagFactor', inSignature: '', outSignature: 'dd' },
{ name: 'setRoi', inSignature: 'ai', outSignature: '' },
{ name: 'getRoi', inSignature: '', outSignature: 'ai' },
{ name: 'shiftContentsTo', inSignature: 'ii', outSignature: 'b' },
{ name: 'moveResize', inSignature: 'ai', outSignature: '' }
],
signals: [],
properties: []
};
// For making unique ZoomRegion DBus proxy object paths of the form:
// '/org/gnome/Magnifier/ZoomRegion/zoomer0',
// '/org/gnome/Magnifier/ZoomRegion/zoomer1', etc.
let _zoomRegionInstanceCount = 0;
function ShellMagnifier() {
this._init();
}
ShellMagnifier.prototype = {
_init: function() {
this._zoomers = {};
DBus.session.exportObject(MAG_SERVICE_PATH, this);
},
/**
* setActive:
* @activate: Boolean to activate or de-activate the magnifier.
*/
setActive: function(activate) {
Main.magnifier.setActive(activate);
},
/**
* isActive:
* @return Whether the magnifier is active (boolean).
*/
isActive: function() {
return Main.magnifier.isActive();
},
/**
* showCursor:
* Show the system mouse pointer.
*/
showCursor: function() {
Main.magnifier.showSystemCursor();
},
/**
* hideCursor:
* Hide the system mouse pointer.
*/
hideCursor: function() {
Main.magnifier.hideSystemCursor();
},
/**
* createZoomRegion:
* Create a new ZoomRegion and return its object path.
* @xMagFactor: The power to set horizontal magnification of the
* ZoomRegion. A value of 1.0 means no magnification. A
* value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification of the
* ZoomRegion.
* @roi Array of integers defining the region of the
* screen/desktop to magnify. The array has the form
* [left, top, right, bottom].
* @viewPort Array of integers, [left, top, right, bottom] that defines
* the position of the ZoomRegion on screen.
* @return The newly created ZoomRegion.
*/
createZoomRegion: function(xMagFactor, yMagFactor, roi, viewPort) {
let ROI = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
let viewBox = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
let realZoomRegion = Main.magnifier.createZoomRegion(xMagFactor, yMagFactor, ROI, viewBox);
let objectPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
_zoomRegionInstanceCount++;
let zoomRegionProxy = new ShellMagnifierZoomRegion(objectPath, realZoomRegion);
let proxyAndZoomRegion = {};
proxyAndZoomRegion.proxy = zoomRegionProxy;
proxyAndZoomRegion.zoomRegion = realZoomRegion;
this._zoomers[objectPath] = proxyAndZoomRegion;
return objectPath;
},
/**
* addZoomRegion:
* Append the given ZoomRegion to the magnifier's list of ZoomRegions.
* @zoomerObjectPath: The object path for the zoom region proxy.
*/
addZoomRegion: function(zoomerObjectPath) {
let proxyAndZoomRegion = this._zoomers[zoomerObjectPath];
if (proxyAndZoomRegion && proxyAndZoomRegion.zoomRegion) {
Main.magnifier.addZoomRegion(proxyAndZoomRegion.zoomRegion);
return true;
}
else
return false;
},
/**
* getZoomRegions:
* Return a list of ZoomRegion object paths for this Magnifier.
* @return: The Magnifier's zoom region list as an array of DBus object
* paths.
*/
getZoomRegions: function() {
// There may be more ZoomRegions in the magnifier itself than have
// been added through dbus. Make sure all of them are associated with
// an object path and proxy.
let zoomRegions = Main.magnifier.getZoomRegions();
let objectPaths = [];
let thoseZoomers = this._zoomers;
zoomRegions.forEach (function(aZoomRegion, index, array) {
let found = false;
for (let objectPath in thoseZoomers) {
let proxyAndZoomRegion = thoseZoomers[objectPath];
if (proxyAndZoomRegion.zoomRegion === aZoomRegion) {
objectPaths.push(objectPath);
found = true;
break;
}
}
if (!found) {
// Got a ZoomRegion with no DBus proxy, make one.
let newPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
_zoomRegionInstanceCount++;
let zoomRegionProxy = new ShellMagnifierZoomRegion(newPath, aZoomRegion);
let proxyAndZoomer = {};
proxyAndZoomer.proxy = zoomRegionProxy;
proxyAndZoomer.zoomRegion = aZoomRegion;
thoseZoomers[newPath] = proxyAndZoomer;
objectPaths.push(newPath);
}
});
return objectPaths;
},
/**
* clearAllZoomRegions:
* Remove all the zoom regions from this Magnfier's ZoomRegion list.
*/
clearAllZoomRegions: function() {
Main.magnifier.clearAllZoomRegions();
for (let objectPath in this._zoomers) {
let proxyAndZoomer = this._zoomers[objectPath];
proxyAndZoomer.proxy = null;
proxyAndZoomer.zoomRegion = null;
delete this._zoomers[objectPath];
DBus.session.unexportObject(proxyAndZoomer);
}
this._zoomers = {};
},
/**
* fullScreenCapable:
* Consult if the Magnifier can magnify in full-screen mode.
* @return Always return true.
*/
fullScreenCapable: function() {
return true;
},
/**
* setCrosswireSize:
* Set the crosswire size of all ZoomRegions.
* @size: The thickness of each line in the cross wire.
*/
setCrosswireSize: function(size) {
Main.magnifier.setCrosshairsThickness(size);
},
/**
* getCrosswireSize:
* Get the crosswire size of all ZoomRegions.
* @return: The thickness of each line in the cross wire.
*/
getCrosswireSize: function() {
return Main.magnifier.getCrosshairsThickness();
},
/**
* setCrosswireLength:
* Set the crosswire length of all zoom-regions..
* @size: The length of each line in the cross wire.
*/
setCrosswireLength: function(length) {
Main.magnifier.setCrosshairsLength(length);
},
/**
* setCrosswireSize:
* Set the crosswire size of all zoom-regions.
* @size: The thickness of each line in the cross wire.
*/
getCrosswireLength: function() {
return Main.magnifier.getCrosshairsLength();
},
/**
* setCrosswireClip:
* Set if the crosswire will be clipped by the cursor image..
* @clip: Flag to indicate whether to clip the crosswire.
*/
setCrosswireClip: function(clip) {
Main.magnifier.setCrosshairsClip(clip);
},
/**
* getCrosswireClip:
* Get the crosswire clip value.
* @return: Whether the crosswire is clipped by the cursor image.
*/
getCrosswireClip: function() {
return Main.magnifier.getCrosshairsClip();
},
/**
* setCrosswireColor:
* Set the crosswire color of all ZoomRegions.
* @color: Unsigned int of the form rrggbbaa.
*/
setCrosswireColor: function(color) {
Main.magnifier.setCrosshairsColor('#%08x'.format(color));
},
/**
* getCrosswireClip:
* Get the crosswire color of all ZoomRegions.
* @return: The crosswire color as an unsigned int in the form rrggbbaa.
*/
getCrosswireColor: function() {
let colorString = Main.magnifier.getCrosshairsColor();
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
};
/**
* ShellMagnifierZoomRegion:
* Object that implements the DBus ZoomRegion interface.
* @zoomerObjectPath: String that is the path to a DBus ZoomRegion.
* @zoomRegion: The actual zoom region associated with the object path.
*/
function ShellMagnifierZoomRegion(zoomerObjectPath, zoomRegion) {
this._init(zoomerObjectPath, zoomRegion);
}
ShellMagnifierZoomRegion.prototype = {
_init: function(zoomerObjectPath, zoomRegion) {
this._zoomRegion = zoomRegion;
DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
DBus.session.exportObject(zoomerObjectPath, this);
},
/**
* setMagFactor:
* @xMagFactor: The power to set the horizontal magnification factor to
* of the magnified view. A value of 1.0 means no
* magnification. A value of 2.0 doubles the size.
* @yMagFactor: The power to set the vertical magnification factor to
* of the magnified view.
*/
setMagFactor: function(xMagFactor, yMagFactor) {
this._zoomRegion.setMagFactor(xMagFactor, yMagFactor);
},
/**
* getMagFactor:
* @return an array, [xMagFactor, yMagFactor], containing the horizontal
* and vertical magnification powers. A value of 1.0 means no
* magnification. A value of 2.0 means the contents are doubled
* in size, and so on.
*/
getMagFactor: function() {
return this._zoomRegion.getMagFactor();
},
/**
* setRoi:
* Sets the "region of interest" that the ZoomRegion is magnifying.
* @roi Array, [left, top, right, bottom], defining the region of the
* screen to magnify. The values are in screen (unmagnified)
* coordinate space.
*/
setRoi: function(roi) {
let roiObject = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
this._zoomRegion.setROI(roiObject);
},
/**
* getRoi:
* Retrieves the "region of interest" -- the rectangular bounds of that part
* of the desktop that the magnified view is showing (x, y, width, height).
* The bounds are given in non-magnified coordinates.
* @return an array, [left, top, right, bottom], representing the bounding
* rectangle of what is shown in the magnified view.
*/
getRoi: function() {
let roi = this._zoomRegion.getROI();
roi[2] += roi[0];
roi[3] += roi[1];
return roi;
},
/**
* Set the "region of interest" by centering the given screen coordinate
* within the zoom region.
* @x The x-coord of the point to place at the center of the zoom region.
* @y The y-coord.
* @return Whether the shift was successful (for GS-mag, this is always
* true).
*/
shiftContentsTo: function(x, y) {
this._zoomRegion.scrollContentsTo(x, y);
return true;
},
/**
* moveResize
* Sets the position and size of the ZoomRegion on screen.
* @viewPort Array, [left, top, right, bottom], defining the position and
* size on screen to place the zoom region.
*/
moveResize: function(viewPort) {
let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
this._zoomRegion.setViewPort(viewRect);
}
};
DBus.conformExport(ShellMagnifier.prototype, MagnifierIface);
DBus.conformExport(ShellMagnifierZoomRegion.prototype, ZoomRegionIface);

View File

@ -1,48 +1,80 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
imports.gi.versions.Clutter = '1.0';
imports.gi.versions.Gio = '2.0';
imports.gi.versions.Gdk = '3.0';
imports.gi.versions.GdkPixbuf = '2.0';
imports.gi.versions.Gtk = '3.0';
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GConf = imports.gi.GConf;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Chrome = imports.ui.chrome;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
const MessageTray = imports.ui.messageTray;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
const PlaceDisplay = imports.ui.placeDisplay;
const RunDialog = imports.ui.runDialog;
const LookingGlass = imports.ui.lookingGlass;
const NotificationDaemon = imports.ui.notificationDaemon;
const WindowAttentionHandler = imports.ui.windowAttentionHandler;
const Scripting = imports.ui.scripting;
const ShellDBus = imports.ui.shellDBus;
const Sidebar = imports.ui.sidebar;
const Tweener = imports.ui.tweener;
const TelepathyClient = imports.ui.telepathyClient;
const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier;
const StatusIconDispatcher = imports.ui.statusIconDispatcher;
const DEFAULT_BACKGROUND_COLOR = new Clutter.Color();
DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff);
let chrome = null;
let panel = null;
let sidebar = null;
let placesManager = null;
let overview = null;
let runDialog = null;
let lookingGlass = null;
let wm = null;
let messageTray = null;
let notificationDaemon = null;
let windowAttentionHandler = null;
let telepathyClient = null;
let recorder = null;
let shellDBusService = null;
let modalCount = 0;
let modalActorFocusStack = [];
let uiGroup = null;
let magnifier = null;
let statusIconDispatcher = null;
let _errorLogStack = [];
let _startDate;
let background = null;
function start() {
// Add a binding for "global" in the global JS namespace; (gjs
// Add a binding for 'global' in the global JS namespace; (gjs
// keeps the web browser convention of having that namespace be
// called "window".)
// called 'window'.)
window.global = Shell.Global.get();
Gio.DesktopAppInfo.set_desktop_env("GNOME");
// Now monkey patch utility functions into the global proxy;
// This is easier and faster than indirecting down into global
// if we want to call back up into JS.
global.logError = _logError;
global.log = _logDebug;
Gio.DesktopAppInfo.set_desktop_env('GNOME');
global.grab_dbus_service();
shellDBusService = new ShellDBus.GnomeShell();
@ -52,48 +84,60 @@ function start() {
// back into sync ones.
DBus.session.flush();
Tweener.init();
Environment.init();
// Ensure ShellAppMonitor is initialized; this will
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
// needs to load all the .desktop files, and ShellAppMonitor
// needs to load all the .desktop files, and ShellWindowTracker
// 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();
Shell.WindowTracker.get_default();
Shell.AppUsage.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
// when we are running inside Xephyr.
global.stage.color = DEFAULT_BACKGROUND_COLOR;
// Mutter currently hardcodes putting "Yessir. The compositor is running""
// 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 = St.ThemeContext.get_for_stage (global.stage);
let stylesheetPath = global.datadir + '/theme/gnome-shell.css';
let theme = new St.Theme ({ application_stylesheet: stylesheetPath });
themeContext.set_theme (theme);
global.connect('panel-run-dialog', function(panel) {
// Make sure not more than one run dialog is shown.
getRunDialog().open();
});
let shellwm = global.window_manager;
shellwm.takeover_keybinding("panel_main_menu");
shellwm.connect("keybinding::panel_main_menu", function () {
shellwm.takeover_keybinding('panel_main_menu');
shellwm.connect('keybinding::panel_main_menu', function () {
overview.toggle();
});
shellwm.takeover_keybinding("panel_run_dialog");
shellwm.connect("keybinding::panel_run_dialog", function () {
shellwm.takeover_keybinding('panel_run_dialog');
shellwm.connect('keybinding::panel_run_dialog', function () {
getRunDialog().open();
});
// Set up stage hierarchy to group all UI actors under one container.
uiGroup = new Clutter.Group();
global.window_group.reparent(uiGroup);
global.overlay_group.reparent(uiGroup);
global.stage.add_actor(uiGroup);
placesManager = new PlaceDisplay.PlacesManager();
overview = new Overview.Overview();
chrome = new Chrome.Chrome();
magnifier = new Magnifier.Magnifier();
statusIconDispatcher = new StatusIconDispatcher.StatusIconDispatcher();
panel = new Panel.Panel();
sidebar = new Sidebar.Sidebar();
wm = new WindowManager.WindowManager();
messageTray = new MessageTray.MessageTray();
notificationDaemon = new NotificationDaemon.NotificationDaemon();
windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
telepathyClient = new TelepathyClient.Client();
_startDate = new Date();
let recorderSettings = new Gio.Settings({ schema: 'org.gnome.shell.recorder' });
global.screen.connect('toggle-recording', function() {
if (recorder == null) {
@ -103,26 +147,107 @@ function start() {
if (recorder.is_recording()) {
recorder.pause();
} else {
// read the parameters from GSettings always in case they have changed
recorder.set_framerate(recorderSettings.get_int('framerate'));
recorder.set_filename('shell-%d%u-%c.' + recorderSettings.get_string('file-extension'));
let pipeline = recorderSettings.get_string('pipeline');
if (!pipeline.match(/^\s*$/))
recorder.set_pipeline(pipeline);
else
recorder.set_pipeline(null);
recorder.record();
}
});
_relayout();
background = global.create_root_pixmap_actor();
global.stage.add_actor(background);
background.lower_bottom();
global.gdk_screen.connect('monitors-changed', _relayout);
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
panel.startupAnimation();
let display = global.screen.get_display();
display.connect('overlay-key', Lang.bind(overview, overview.toggle));
global.connect('panel-main-menu', Lang.bind(overview, overview.toggle));
global.stage.connect('captured-event', _globalKeyPressHandler);
// Perform initial relayout here
_relayout();
_log('info', 'loaded at ' + _startDate);
log('GNOME Shell started at ' + _startDate);
Mainloop.idle_add(_removeUnusedWorkspaces);
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
}
/**
* _log:
* @category: string message type ('info', 'error')
* @msg: A message string
* ...: Any further arguments are converted into JSON notation,
* and appended to the log message, separated by spaces.
*
* Log a message into the LookingGlass error
* stream. This is primarily intended for use by the
* extension system as well as debugging.
*/
function _log(category, msg) {
let text = msg;
if (arguments.length > 2) {
text += ': ';
for (let i = 2; i < arguments.length; i++) {
text += JSON.stringify(arguments[i]);
if (i < arguments.length - 1)
text += ' ';
}
}
_errorLogStack.push({timestamp: new Date().getTime(),
category: category,
message: text });
}
function _logError(msg) {
return _log('error', msg);
}
function _logDebug(msg) {
return _log('debug', msg);
}
// Used by the error display in lookingGlass.js
function _getAndClearErrorStack() {
let errors = _errorLogStack;
_errorLogStack = [];
return errors;
}
function _relayout() {
panel.actor.set_size(global.screen_width, Panel.PANEL_HEIGHT);
let primary = global.get_primary_monitor();
panel.actor.set_position(primary.x, primary.y);
panel.actor.set_size(primary.width, Panel.PANEL_HEIGHT);
overview.relayout();
background.set_size(global.screen_width, global.screen_height);
// To avoid updating the position and size of the workspaces
// in the overview, we just hide the overview. The positions
// will be updated when it is next shown. We do the same for
// the calendar popdown.
overview.hide();
panel.hideCalendar();
}
// metacity-clutter currently uses the same prefs as plain metacity,
@ -174,9 +299,9 @@ function _globalKeyPressHandler(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.Print) {
// We want to be able to take screenshots of the shell at all times
let gconf = Shell.GConf.get_default();
let command = gconf.get_string("/apps/metacity/keybinding_commands/command_screenshot");
if (command != null && command != "") {
let gconf = GConf.Client.get_default();
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
if (command != null && command != '') {
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
p.run();
@ -186,6 +311,9 @@ function _globalKeyPressHandler(actor, event) {
}
} else if (type == Clutter.EventType.KEY_RELEASE) {
let symbol = event.get_key_symbol();
let keyCode = event.get_key_code();
let modifierState = Shell.get_event_state(event);
// Check the overview key first, this isn't a Meta.KeyBindingAction yet
if (symbol == Clutter.Super_L || symbol == Clutter.Super_R) {
// The super key is the default for triggering the overview, and should
// get us out of the overview when we are already in it.
@ -193,8 +321,25 @@ function _globalKeyPressHandler(actor, event) {
overview.hide();
return true;
} else if (symbol == Clutter.F2 && (event.get_state() & Clutter.ModifierType.MOD1_MASK)) {
getRunDialog().open();
}
// Whitelist some of the Metacity actions
let display = global.screen.get_display();
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = display.get_keybinding_action(symbol, keyCode, modifierState);
switch (action) {
case Meta.KeyBindingAction.WORKSPACE_LEFT:
wm.actionMoveWorkspaceLeft();
return true;
case Meta.KeyBindingAction.WORKSPACE_RIGHT:
wm.actionMoveWorkspaceRight();
return true;
case Meta.KeyBindingAction.PANEL_RUN_DIALOG:
case Meta.KeyBindingAction.COMMAND_2:
getRunDialog().open();
return true;
}
}
@ -228,8 +373,8 @@ function _findModal(actor) {
*/
function pushModal(actor) {
if (modalCount == 0) {
if (!global.begin_modal(currentTime())) {
log("pushModal: invocation of begin_modal failed");
if (!global.begin_modal(global.get_current_time())) {
log('pushModal: invocation of begin_modal failed');
return false;
}
}
@ -281,7 +426,7 @@ function popModal(actor) {
if (modalCount > 0)
return;
global.end_modal(currentTime());
global.end_modal(global.get_current_time());
global.set_stage_input_mode(Shell.StageInputMode.NORMAL);
}
@ -300,58 +445,21 @@ function getRunDialog() {
return runDialog;
}
function createAppLaunchContext() {
let context = new Gdk.AppLaunchContext();
context.set_timestamp(currentTime());
// Make sure that the app is opened on the current workspace even if
// the user switches before it starts
context.set_desktop(global.screen.get_active_workspace_index());
return context;
}
/**
* currentTime:
*
* Gets the current X server time from the current Clutter, Gdk, or X
* event. If called from outside an event handler, this may return
* %Clutter.CURRENT_TIME (aka 0), or it may return a slightly
* out-of-date timestamp.
*/
function currentTime() {
// meta_display_get_current_time() will return the correct time
// when handling an X or Gdk event, but will return CurrentTime
// from some Clutter event callbacks.
//
// clutter_get_current_event_time() will return the correct time
// from a Clutter event callback, but may return an out-of-date
// timestamp if called at other times.
//
// So we try meta_display_get_current_time() first, since we
// can recognize a "wrong" answer from that, and then fall back
// to clutter_get_current_event_time().
let time = global.screen.get_display().get_current_time();
if (time != Clutter.CURRENT_TIME)
return time;
return Clutter.get_current_event_time();
}
/**
* activateWindow:
* @window: the Meta.Window to activate
* @time: (optional) current event time
* @workspaceNum: (optional) window's workspace number
*
* Activates @window, switching to its workspace first if necessary
* Activates @window, switching to its workspace first if necessary,
* and switching out of the overview if it's currently active
*/
function activateWindow(window, time) {
function activateWindow(window, time, workspaceNum) {
let activeWorkspaceNum = global.screen.get_active_workspace_index();
let windowWorkspaceNum = window.get_workspace().index();
let windowWorkspaceNum = (workspaceNum !== undefined) ? workspaceNum : window.get_workspace().index();
if (!time)
time = currentTime();
time = global.get_current_time();
if (windowWorkspaceNum != activeWorkspaceNum) {
let workspace = global.screen.get_workspace_by_index(windowWorkspaceNum);
@ -359,4 +467,123 @@ function activateWindow(window, time) {
} else {
window.activate(time);
}
overview.hide();
}
// TODO - replace this timeout with some system to guess when the user might
// be e.g. just reading the screen and not likely to interact.
const DEFERRED_TIMEOUT_SECONDS = 20;
var _deferredWorkData = {};
// Work scheduled for some point in the future
var _deferredWorkQueue = [];
// Work we need to process before the next redraw
var _beforeRedrawQueue = [];
// Counter to assign work ids
var _deferredWorkSequence = 0;
var _deferredTimeoutId = 0;
function _runDeferredWork(workId) {
if (!_deferredWorkData[workId])
return;
let index = _deferredWorkQueue.indexOf(workId);
if (index < 0)
return;
_deferredWorkQueue.splice(index, 1);
_deferredWorkData[workId].callback();
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
Mainloop.source_remove(_deferredTimeoutId);
_deferredTimeoutId = 0;
}
}
function _runAllDeferredWork() {
while (_deferredWorkQueue.length > 0)
_runDeferredWork(_deferredWorkQueue[0]);
}
function _runBeforeRedrawQueue() {
for (let i = 0; i < _beforeRedrawQueue.length; i++) {
let workId = _beforeRedrawQueue[i];
_runDeferredWork(workId);
}
_beforeRedrawQueue = [];
}
function _queueBeforeRedraw(workId) {
_beforeRedrawQueue.push(workId);
if (_beforeRedrawQueue.length == 1) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, function () {
_runBeforeRedrawQueue();
return false;
});
}
}
/**
* initializeDeferredWork:
* @actor: A #ClutterActor
* @callback: Function to invoke to perform work
*
* This function sets up a callback to be invoked when either the
* given actor is mapped, or after some period of time when the machine
* is idle. This is useful if your actor isn't always visible on the
* screen (for example, all actors in the overview), and you don't want
* to consume resources updating if the actor isn't actually going to be
* displaying to the user.
*
* Note that queueDeferredWork is called by default immediately on
* initialization as well, under the assumption that new actors
* will need it.
*
* Returns: A string work identifer
*/
function initializeDeferredWork(actor, callback, props) {
// Turn into a string so we can use as an object property
let workId = '' + (++_deferredWorkSequence);
_deferredWorkData[workId] = { 'actor': actor,
'callback': callback };
actor.connect('notify::mapped', function () {
if (!(actor.mapped && _deferredWorkQueue.indexOf(workId) >= 0))
return;
_queueBeforeRedraw(workId);
});
actor.connect('destroy', function() {
let index = _deferredWorkQueue.indexOf(workId);
if (index >= 0)
_deferredWorkQueue.splice(index, 1);
delete _deferredWorkData[workId];
});
queueDeferredWork(workId);
return workId;
}
/**
* queueDeferredWork:
* @workId: work identifier
*
* Ensure that the work identified by @workId will be
* run on map or timeout. You should call this function
* for example when data being displayed by the actor has
* changed.
*/
function queueDeferredWork(workId) {
let data = _deferredWorkData[workId];
if (!data) {
global.logError('invalid work id ', workId);
return;
}
if (_deferredWorkQueue.indexOf(workId) < 0)
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, function () {
_runAllDeferredWork();
_deferredTimeoutId = 0;
return false;
});
}
}

1525
js/ui/messageTray.js Normal file

File diff suppressed because it is too large Load Diff

450
js/ui/notificationDaemon.js Normal file
View File

@ -0,0 +1,450 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
const St = imports.gi.St;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Params = imports.misc.params;
let nextNotificationId = 1;
// Should really be defined in dbus.js
const BusIface = {
name: 'org.freedesktop.DBus',
methods: [{ name: 'GetConnectionUnixProcessID',
inSignature: 's',
outSignature: 'i' }]
};
const Bus = function () {
this._init();
};
Bus.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
};
DBus.proxifyPrototype(Bus.prototype, BusIface);
const NotificationDaemonIface = {
name: 'org.freedesktop.Notifications',
methods: [{ name: 'Notify',
inSignature: 'susssasa{sv}i',
outSignature: 'u'
},
{ name: 'CloseNotification',
inSignature: 'u',
outSignature: ''
},
{ name: 'GetCapabilities',
inSignature: '',
outSignature: 'as'
},
{ name: 'GetServerInformation',
inSignature: '',
outSignature: 'ssss'
}],
signals: [{ name: 'NotificationClosed',
inSignature: 'uu' },
{ name: 'ActionInvoked',
inSignature: 'us' }]
};
const NotificationClosedReason = {
EXPIRED: 1,
DISMISSED: 2,
APP_CLOSED: 3,
UNDEFINED: 4
};
const Urgency = {
LOW: 0,
NORMAL: 1,
CRITICAL: 2
};
const rewriteRules = {
'XChat': [
{ pattern: /^XChat: Private message from: (\S*) \(.*\)$/,
replacement: '&lt;$1&gt;' },
{ pattern: /^XChat: New public message from: (\S*) \((.*)\)$/,
replacement: '$2 &lt;$1&gt;' },
{ pattern: /^XChat: Highlighted message from: (\S*) \((.*)\)$/,
replacement: '$2 &lt;$1&gt;' }
]
};
function NotificationDaemon() {
this._init();
}
NotificationDaemon.prototype = {
_init: function() {
DBus.session.exportObject('/org/freedesktop/Notifications', this);
this._everAcquiredName = false;
DBus.session.acquire_name('org.freedesktop.Notifications',
// We pass MANY_INSTANCES so that if
// notification-daemon is running, we'll
// get queued behind it and then get the
// name after killing it below
DBus.MANY_INSTANCES,
Lang.bind(this, this._acquiredName),
Lang.bind(this, this._lostName));
this._sources = {};
this._senderToPid = {};
this._notifications = {};
this._busProxy = new Bus();
Main.statusIconDispatcher.connect('message-icon-added', Lang.bind(this, this._onTrayIconAdded));
Main.statusIconDispatcher.connect('message-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
Shell.WindowTracker.get_default().connect('notify::focus-app',
Lang.bind(this, this._onFocusAppChanged));
Main.overview.connect('hidden',
Lang.bind(this, this._onFocusAppChanged));
},
_acquiredName: function() {
this._everAcquiredName = true;
},
_lostName: function() {
if (this._everAcquiredName)
log('Lost name org.freedesktop.Notifications!');
else if (GLib.getenv('GNOME_SHELL_NO_REPLACE'))
log('Failed to acquire org.freedesktop.Notifications');
else {
log('Failed to acquire org.freedesktop.Notifications; trying again');
// kill the notification-daemon. pkill is more portable
// than killall, but on Linux at least it won't match if
// you pass more than 15 characters of the process name...
// However, if you use the '-f' flag to match the entire
// command line, it will work, but we have to be careful
// in that case that we don't match 'gedit
// notification-daemon.c' or whatever...
let p = new Shell.Process({ args: ['pkill', '-f',
'^([^ ]*/)?(notification-daemon|notify-osd)$']});
p.run();
}
},
_iconForNotificationData: function(icon, hints, size) {
let textureCache = St.TextureCache.get_default();
if (icon) {
if (icon.substr(0, 7) == 'file://')
return textureCache.load_uri_async(icon, size, size);
else if (icon[0] == '/') {
let uri = GLib.filename_to_uri(icon, null);
return textureCache.load_uri_async(uri, size, size);
} else
return textureCache.load_icon_name(icon, St.IconType.FULLCOLOR, size);
} else if (hints.icon_data) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints.icon_data;
return textureCache.load_from_raw(data, data.length, hasAlpha,
width, height, rowStride, size);
} else {
let stockIcon;
switch (hints.urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'gtk-dialog-info';
break;
case Urgency.CRITICAL:
stockIcon = 'gtk-dialog-error';
break;
}
return textureCache.load_icon_name(stockIcon, St.IconType.FULLCOLOR, size);
}
},
_newSource: function(title, pid) {
let source = new Source(title, pid);
this._sources[pid] = source;
source.connect('clicked', Lang.bind(this,
function() {
source.destroy();
}));
source.connect('destroy', Lang.bind(this,
function() {
delete this._sources[pid];
}));
Main.messageTray.add(source);
return source;
},
Notify: function(appName, replacesId, icon, summary, body,
actions, hints, timeout) {
let id;
// Filter out notifications from Empathy, since we
// handle that information from telepathyClient.js
if (appName == 'Empathy') {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = nextNotificationId++;
Mainloop.idle_add(Lang.bind(this,
function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
}));
return id;
}
summary = GLib.markup_escape_text(summary, -1);
let rewrites = rewriteRules[appName];
if (rewrites) {
for (let i = 0; i < rewrites.length; i++) {
let rule = rewrites[i];
if (summary.search(rule.pattern) != -1)
summary = summary.replace(rule.pattern, rule.replacement);
}
}
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
let ndata = { appName: appName,
icon: icon,
summary: summary,
body: body,
actions: actions,
hints: hints,
timeout: timeout };
if (replacesId != 0 && this._notifications[replacesId]) {
ndata.id = id = replacesId;
ndata.notification = this._notifications[replacesId].notification;
} else {
replacesId = 0;
ndata.id = id = nextNotificationId++;
}
this._notifications[id] = ndata;
let sender = DBus.getCurrentMessageContext().sender;
let pid = this._senderToPid[sender];
let source = pid ? this._sources[pid] : null;
if (source) {
this._notifyForSource(source, ndata);
return id;
}
if (replacesId) {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return id;
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this,
function (pid, ex) {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
this._senderToPid[sender] = pid;
source = this._sources[pid];
if (!source)
source = this._newSource(appName, pid);
source.connect('destroy', Lang.bind(this,
function() {
delete this._senderToPid[sender];
}));
this._notifyForSource(source, ndata);
}));
return id;
},
_notifyForSource: function(source, ndata) {
let [id, icon, summary, body, actions, hints, notification] =
[ndata.id, ndata.icon, ndata.summary, ndata.body,
ndata.actions, ndata.hints, ndata.notification];
let iconActor = this._iconForNotificationData(icon, hints, source.ICON_SIZE);
if (notification == null) {
notification = new MessageTray.Notification(source, summary, body, { icon: iconActor });
ndata.notification = notification;
notification.connect('dismissed', Lang.bind(this,
function(n) {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
}));
notification.connect('destroy', Lang.bind(this,
function(n) {
delete this._notifications[id];
}));
notification.connect('action-invoked', Lang.bind(this, this._actionInvoked, source, id));
} else {
notification.update(summary, body, { icon: iconActor,
clear: true });
}
if (actions.length) {
for (let i = 0; i < actions.length - 1; i += 2)
notification.addButton(actions[i], actions[i + 1]);
}
notification.setUrgent(hints.urgency == Urgency.CRITICAL);
let sourceIconActor = source.useNotificationIcon ? this._iconForNotificationData(icon, hints, source.ICON_SIZE) : null;
source.notify(notification, sourceIconActor);
},
CloseNotification: function(id) {
let ndata = this._notifications[id];
if (ndata) {
if (ndata.notification)
ndata.notification.destroy();
delete this._notifications[id];
}
this._emitNotificationClosed(id, NotificationClosedReason.APP_CLOSED);
},
GetCapabilities: function() {
return [
'actions',
'body',
// 'body-hyperlinks',
// 'body-images',
'body-markup',
// 'icon-multi',
'icon-static',
// 'sound',
'x-gnome-icon-buttons'
];
},
GetServerInformation: function() {
return [
'GNOME Shell',
'GNOME',
'0.1', // FIXME, get this from somewhere
'1.0'
];
},
_onFocusAppChanged: function() {
let tracker = Shell.WindowTracker.get_default();
if (!tracker.focus_app)
return;
for (let id in this._sources) {
let source = this._sources[id];
if (source.app == tracker.focus_app) {
source.destroy();
return;
}
}
},
_actionInvoked: function(notification, action, source, id) {
source.destroy();
this._emitActionInvoked(id, action);
},
_emitNotificationClosed: function(id, reason) {
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'NotificationClosed', 'uu',
[id, reason]);
},
_emitActionInvoked: function(id, action) {
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'ActionInvoked', 'us',
[id, action]);
},
_onTrayIconAdded: function(o, icon) {
let source = this._sources[icon.pid];
if (!source)
source = this._newSource(icon.title, icon.pid);
source.setTrayIcon(icon);
},
_onTrayIconRemoved: function(o, icon) {
let source = this._sources[icon.pid];
if (source)
source.destroy();
}
};
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
function Source(title, pid) {
this._init(title, pid);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(title, pid) {
MessageTray.Source.prototype._init.call(this, title);
this._pid = pid;
this._setApp();
if (this.app)
this.title = this.app.get_name();
else
this.useNotificationIcon = true;
},
notify: function(notification, icon) {
if (!this.app)
this._setApp();
if (!this.app && icon)
this._setSummaryIcon(icon);
MessageTray.Source.prototype.notify.call(this, notification);
},
_setApp: function() {
this.app = Shell.WindowTracker.get_default().get_app_from_pid(this._pid);
if (!this.app)
return;
// Only override the icon if we were previously using
// notification-based icons (ie, not a trayicon)
if (this.useNotificationIcon) {
this.useNotificationIcon = false;
this._setSummaryIcon(this.app.create_icon_texture (this.ICON_SIZE));
}
},
setTrayIcon: function(icon) {
this._setSummaryIcon(icon);
this.useNotificationIcon = false;
},
clicked: function() {
this.openApp();
MessageTray.Source.prototype.clicked.call(this);
},
openApp: function() {
if (this.app == null)
return;
let windows = this.app.get_windows();
if (windows.length > 0) {
let mostRecentWindow = windows[0];
Main.activateWindow(mostRecentWindow);
}
}
};

View File

@ -1,30 +1,27 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Lang = imports.lang;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay;
const GenericDisplay = imports.ui.genericDisplay;
const Link = imports.ui.link;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Dash = imports.ui.dash;
const Tweener = imports.ui.tweener;
const Workspaces = imports.ui.workspaces;
const ROOT_OVERVIEW_COLOR = new Clutter.Color();
ROOT_OVERVIEW_COLOR.from_pixel(0x000000ff);
const WorkspacesView = imports.ui.workspacesView;
// Time for initial animation going into Overview mode
const ANIMATION_TIME = 0.25;
// Time for pane menus to fade in/out
const PANE_FADE_TIME = 0.1;
// We divide the screen into a grid of rows and columns, which we use
// to help us position the Overview components, such as the side panel
// that lists applications and documents, the workspaces display, and
@ -74,10 +71,101 @@ const SHADOW_WIDTH = 6;
const NUMBER_OF_SECTIONS_IN_SEARCH = 2;
const INFO_BAR_HIDE_TIMEOUT = 10;
let wideScreen = false;
let displayGridColumnWidth = null;
let displayGridRowHeight = null;
let addRemoveButtonSize = null;
function InfoBar() {
this._init();
}
InfoBar.prototype = {
_init: function() {
this.actor = new St.Bin({ style_class: 'info-bar-panel',
x_fill: true,
y_fill: false });
this._label = new St.Label();
this._undo = new St.Button({ style_class: 'info-bar-link-button' });
let bin = new St.Bin({ x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.actor.set_child(bin);
let box = new St.BoxLayout({ style_class: 'info-bar' });
bin.set_child(box);
this._timeoutId = 0;
box.add(this._label, {'y-fill' : false, 'y-align' : St.Align.MIDDLE});
box.add(this._undo);
this.actor.set_opacity(0);
this._undoCallback = null;
this._undo.connect('clicked', Lang.bind(this, this._onUndoClicked));
},
_onUndoClicked: function() {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
if (this._undoCallback)
this._undoCallback();
this.actor.set_opacity(0);
this._undoCallback = null;
},
_hideDone: function() {
this._undoCallback = null;
},
_hide: function() {
Tweener.addTween(this.actor,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onCompleteScope: this
});
},
_onTimeout: function() {
this._timeoutId = 0;
this._hide();
return false;
},
setMessage: function(text, undoCallback, undoLabel) {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
this._timeout = false;
this._label.text = text;
Tweener.addTween(this.actor,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME
});
this._timeoutId = Mainloop.timeout_add_seconds(INFO_BAR_HIDE_TIMEOUT, Lang.bind(this, this._onTimeout));
if (undoLabel)
this._undo.label = undoLabel;
else
this._undo.label = _("Undo");
this._undoCallback = undoCallback;
if (undoCallback)
this._undo.show();
else
this._undo.hide();
}
};
function Overview() {
this._init();
@ -85,8 +173,21 @@ function Overview() {
Overview.prototype = {
_init : function() {
this._group = new Clutter.Group();
this._group = new St.Group({ style_class: 'overview' });
this._group._delegate = this;
this._group.connect('destroy', Lang.bind(this,
function() {
if (this._lightbox) {
this._lightbox.destroy();
this._lightbox = null;
}
}));
this.infoBar = new InfoBar();
this._group.add_actor(this.infoBar.actor);
this._workspacesManager = null;
this._lightbox = null;
this.visible = false;
this.animationInProgress = false;
@ -111,7 +212,7 @@ Overview.prototype = {
this._group.add_actor(this._transparentBackground);
// Background color for the Overview
this._backOver = new Clutter.Rectangle({ color: ROOT_OVERVIEW_COLOR });
this._backOver = new St.Label();
this._group.add_actor(this._backOver);
this._group.hide();
@ -122,9 +223,7 @@ Overview.prototype = {
this._group.add_actor(this._dash.actor);
// Container to hold popup pane chrome.
this._paneContainer = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
spacing: 6
});
this._paneContainer = new St.BoxLayout({ style_class: 'overview-pane' });
// Note here we explicitly don't set the paneContainer to be reactive yet; that's done
// inside the notify::visible handler on panes.
this._paneContainer.connect('button-release-event', Lang.bind(this, function(background) {
@ -134,79 +233,118 @@ Overview.prototype = {
this._group.add_actor(this._paneContainer);
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._paneContainer.hide();
this._coverPane.lower_bottom();
this._workspaces = null;
this.workspaces = null;
},
_onViewChanged: function() {
if (!this.visible)
return;
this.workspaces = this._workspacesManager.workspacesView;
// Show new workspacesView
this._group.add_actor(this.workspaces.actor);
this._workspacesBar.raise(this.workspaces.actor);
this._dash.actor.raise(this.workspaces.actor);
},
_recalculateGridSizes: function () {
wideScreen = (global.screen_width/global.screen_height > WIDE_SCREEN_CUT_OFF_RATIO) &&
(global.screen_height >= WIDE_SCREEN_MINIMUM_HEIGHT);
let primary = global.get_primary_monitor();
wideScreen = (primary.width/primary.height > WIDE_SCREEN_CUT_OFF_RATIO) &&
(primary.height >= WIDE_SCREEN_MINIMUM_HEIGHT);
// We divide the screen into an imaginary grid which helps us determine the layout of
// different visual components.
if (wideScreen) {
displayGridColumnWidth = global.screen_width / COLUMNS_WIDE_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_WIDE_SCREEN;
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_WIDE_SCREEN);
displayGridRowHeight = Math.floor(primary.height / ROWS_WIDE_SCREEN);
} else {
displayGridColumnWidth = global.screen_width / COLUMNS_REGULAR_SCREEN;
displayGridRowHeight = global.screen_height / ROWS_REGULAR_SCREEN;
displayGridColumnWidth = Math.floor(primary.width / COLUMNS_REGULAR_SCREEN);
displayGridRowHeight = Math.floor(primary.height / ROWS_REGULAR_SCREEN);
}
},
relayout: function () {
let screenHeight = global.screen_height;
let screenWidth = global.screen_width;
let primary = global.get_primary_monitor();
let rtl = (St.Widget.get_default_direction () == St.TextDirection.RTL);
this._recalculateGridSizes();
this._group.set_position(primary.x, primary.y);
this._group.set_size(primary.width, primary.height);
let contentY = Panel.PANEL_HEIGHT;
let contentHeight = screenHeight - contentY;
let contentHeight = primary.height - contentY;
this._coverPane.set_position(0, contentY);
this._coverPane.set_size(screenWidth, contentHeight);
this._coverPane.set_size(primary.width, 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)
// We scale the vertical padding by (primary.height / primary.width)
// so that the workspace preserves its aspect ratio.
this._workspacesHeight = displayGridRowHeight * workspaceRowsUsed
- WORKSPACE_GRID_PADDING * (screenHeight / screenWidth) * 2;
this._workspacesHeight = Math.floor(displayGridRowHeight * workspaceRowsUsed
- WORKSPACE_GRID_PADDING * (primary.height / primary.width) * 2);
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
this._workspacesY = displayGridRowHeight + WORKSPACE_GRID_PADDING * (screenHeight / screenWidth);
if (rtl) {
this._workspacesX = WORKSPACE_GRID_PADDING;
} else {
this._workspacesX = displayGridColumnWidth + WORKSPACE_GRID_PADDING;
}
this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width));
if (rtl) {
this._dash.actor.set_position(primary.width - displayGridColumnWidth, contentY);
} else {
this._dash.actor.set_position(0, contentY);
}
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._dash.searchResults.actor.height = this._workspacesHeight;
this.infoBar.actor.set_position(displayGridColumnWidth, Panel.PANEL_HEIGHT);
this.infoBar.actor.set_size(primary.width - displayGridColumnWidth, this._workspacesY - Panel.PANEL_HEIGHT);
this.infoBar.actor.raise_top();
// place the 'Add Workspace' button in the bottom row of the grid
addRemoveButtonSize = Math.floor(displayGridRowHeight * 3/5);
this._addButtonX = this._workspacesX + this._workspacesWidth - addRemoveButtonSize;
this._addButtonY = screenHeight - Math.floor(displayGridRowHeight * 4/5);
this._workspacesBarX = this._workspacesX;
this._workspacesBarWidth = this._workspacesWidth;
this._workspacesBarY = primary.height - displayGridRowHeight;
this._backOver.set_position(0, contentY);
this._backOver.set_size(global.screen_width, contentHeight);
// The parent (this._group) is positioned at the top left of the primary monitor
// while this._backOver occupies the entire screen.
this._backOver.set_position(- primary.x, - primary.y);
this._backOver.set_size(global.screen_width, global.screen_height);
this._paneContainer.set_position(this._dash.actor.x + this._dash.actor.width + DEFAULT_PADDING,
contentY);
this._workspacesY);
// Dynamic width
this._paneContainer.height = contentHeight;
this._paneContainer.height = this._workspacesHeight;
if (rtl) {
this._paneContainer.connect('notify::width', Lang.bind(this, function (paneContainer) {
paneContainer.x = this._dash.actor.x - (DEFAULT_PADDING + paneContainer.width);
}));
}
this._transparentBackground.set_position(this._paneContainer.x, this._paneContainer.y);
this._transparentBackground.set_size(global.screen_width - this._paneContainer.x,
this._paneContainer.height);
this._transparentBackground.set_position(primary.x, primary.y);
this._transparentBackground.set_size(primary.width, primary.height);
if (this._activeDisplayPane != null)
this._activeDisplayPane.actor.width = displayGridColumnWidth * 2;
},
addPane: function (pane) {
this._paneContainer.append(pane.actor, Big.BoxPackFlags.NONE);
addPane: function (pane, align) {
pane.actor.height = .9 * this._workspacesHeight;
this._paneContainer.add(pane.actor, { expand: true,
y_fill: false,
y_align: align });
// When a pane is displayed, we raise the transparent background to the top
// and connect to button-release-event on it, then raise the pane above that.
// The idea here is that clicking anywhere outside the pane should close it.
@ -214,16 +352,28 @@ Overview.prototype = {
let backgroundEventId = null;
pane.connect('open-state-changed', Lang.bind(this, function (pane, isOpen) {
if (isOpen) {
pane.actor.width = displayGridColumnWidth * 2;
this._activeDisplayPane = pane;
this._transparentBackground.raise_top();
this._paneContainer.raise_top();
this._paneContainer.show();
this._paneReady = false;
if (backgroundEventId != null)
this._transparentBackground.disconnect(backgroundEventId);
backgroundEventId = this._transparentBackground.connect('button-release-event', Lang.bind(this, function () {
this._activeDisplayPane.close();
backgroundEventId = this._transparentBackground.connect('captured-event', Lang.bind(this, function (actor, event) {
if (event.get_source() != this._transparentBackground)
return false;
if (event.type() == Clutter.EventType.BUTTON_PRESS)
this._paneReady = true;
if (event.type() == Clutter.EventType.BUTTON_RELEASE
&& this._paneReady)
this._activeDisplayPane.close();
return true;
}));
if (!this._lightbox)
this._lightbox = new Lightbox.Lightbox(this._group,
{ fadeTime: PANE_FADE_TIME });
this._lightbox.show();
this._lightbox.highlight(this._paneContainer);
} else if (pane == this._activeDisplayPane) {
this._activeDisplayPane = null;
if (backgroundEventId != null) {
@ -231,39 +381,37 @@ Overview.prototype = {
backgroundEventId = null;
}
this._transparentBackground.lower_bottom();
this._paneContainer.lower_bottom();
this._paneContainer.hide();
this._lightbox.hide();
}
}));
},
//// Draggable target interface ////
//// Public methods ////
// Closes any active panes if a GenericDisplayItem is being
// dragged over the Overview, i.e. as soon as it starts being dragged.
// This allows the user to place the item on any workspace.
handleDragOver : function(source, actor, x, y, time) {
if (source instanceof GenericDisplay.GenericDisplayItem
|| source instanceof AppDisplay.BaseWellItem) {
beginItemDrag: function(source) {
// Close any active panes if @source is a GenericDisplayItem.
// This allows the user to place the item on any workspace.
if (source instanceof GenericDisplay.GenericDisplayItem)
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
return true;
}
return false;
this.emit('item-drag-begin');
},
//// Public methods ////
endItemDrag: function(source) {
this.emit('item-drag-end');
},
// 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();
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 [posX, posY] = this.workspaces.getActiveWorkspacePosition();
let scale = this.getZoomedInScale();
return [- posX * scale, - posY * scale];
@ -291,20 +439,28 @@ Overview.prototype = {
this._dash.show();
/* TODO: make this stuff dynamic */
this._workspaces = new Workspaces.Workspaces(this._workspacesWidth, this._workspacesHeight,
this._workspacesX, this._workspacesY);
this._group.add_actor(this._workspaces.actor);
this._workspacesManager =
new WorkspacesView.WorkspacesManager(this._workspacesWidth,
this._workspacesHeight,
this._workspacesX,
this._workspacesY);
this._workspacesManager.connect('view-changed',
Lang.bind(this, this._onViewChanged));
this.workspaces = this._workspacesManager.workspacesView;
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);
this._dash.actor.raise(this.workspaces.actor);
// Create (+) button
this._addButton = new AddWorkspaceButton(addRemoveButtonSize, this._addButtonX, this._addButtonY, Lang.bind(this, this._acceptNewWorkspaceDrop));
this._addButton.actor.connect('button-release-event', Lang.bind(this, this._addNewWorkspace));
this._group.add_actor(this._addButton.actor);
this._addButton.actor.raise(this._workspaces.actor);
this._workspacesBar = this._workspacesManager.controlsBar.actor;
this._workspacesBar.set_position(this._workspacesBarX,
this._workspacesBarY);
this._workspacesBar.width = this._workspacesBarWidth;
this._group.add_actor(this._workspacesBar);
this._workspacesBar.raise(this.workspaces.actor);
// All the the actors in the window group are completely obscured,
// hiding the group holding them while the Overview is displayed greatly
@ -322,9 +478,10 @@ Overview.prototype = {
// The opposite transition is used in hide().
this._group.scaleX = this._group.scaleY = this.getZoomedInScale();
[this._group.x, this._group.y] = this.getZoomedInPosition();
let primary = global.get_primary_monitor();
Tweener.addTween(this._group,
{ x: 0,
y: 0,
{ x: primary.x,
y: primary.y,
scaleX: 1,
scaleY: 1,
transition: 'easeOutQuad',
@ -333,7 +490,7 @@ Overview.prototype = {
onCompleteScope: this
});
// Make Dash fade in so that it doesn't appear to big.
// Make Dash fade in so that it doesn't appear too big.
this._dash.actor.opacity = 0;
Tweener.addTween(this._dash.actor,
{ opacity: 255,
@ -353,7 +510,7 @@ Overview.prototype = {
this._hideInProgress = true;
if (this._activeDisplayPane != null)
this._activeDisplayPane.close();
this._workspaces.hide();
this.workspaces.hide();
// Create a zoom in effect by transforming the Overview group so that
// the active workspace fills up the whole screen. The opposite
@ -398,21 +555,7 @@ Overview.prototype = {
* and will return %null.
*/
getWorkspacesForWindow: function(metaWindow) {
return this._workspaces;
},
/**
* activateWindow:
* @metaWindow: A #MetaWindow
* @time: Event timestamp integer
*
* Make the given MetaWindow be the focus window, switching
* to the workspace it's on if necessary. This function
* should only be used when the Overview is currently active;
* outside of that, use the relevant methods on MetaDisplay.
*/
activateWindow: function (metaWindow, time) {
this._workspaces.activateWindowFromOverview(metaWindow, time);
return this.workspaces;
},
//// Private methods ////
@ -430,13 +573,18 @@ Overview.prototype = {
_hideDone: function() {
global.window_group.show();
this._workspaces.destroy();
this._workspaces = null;
this.workspaces.destroy();
this.workspaces = null;
this._workspacesBar.destroy();
this._workspacesBar = null;
this._workspacesManager = null;
this._dash.hide();
this._group.hide();
this.visible = false;
this.visible = false;
this.animationInProgress = false;
this._hideInProgress = false;
@ -444,43 +592,6 @@ Overview.prototype = {
Main.popModal(this._dash.actor);
this.emit('hidden');
},
_addNewWorkspace: function() {
global.screen.append_new_workspace(false, Main.currentTime());
},
_acceptNewWorkspaceDrop: function(source, dropActor, x, y, time) {
this._addNewWorkspace();
return this._workspaces.acceptNewWorkspaceDrop(source, dropActor, x, y, time);
}
};
Signals.addSignalMethods(Overview.prototype);
function AddWorkspaceButton(buttonSize, buttonX, buttonY, acceptDropCallback) {
this._init(buttonSize, buttonX, buttonY, acceptDropCallback);
}
AddWorkspaceButton.prototype = {
_init: function(buttonSize, buttonX, buttonY, acceptDropCallback) {
this.actor = new Clutter.Group({ x: buttonX,
y: buttonY,
width: global.screen_width - buttonX,
height: global.screen_height - buttonY,
reactive: true });
this.actor._delegate = this;
this._acceptDropCallback = acceptDropCallback;
let plus = new Clutter.Texture({ x: 0,
y: 0,
width: buttonSize,
height: buttonSize });
plus.set_from_file(global.imagedir + 'add-workspace.svg');
this.actor.add_actor(plus);
},
// Draggable target interface
acceptDrop: function(source, actor, x, y, time) {
return this._acceptDropCallback(source, actor, x, y, time);
}
};

File diff suppressed because it is too large Load Diff

78
js/ui/panelMenu.js Normal file
View File

@ -0,0 +1,78 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const St = imports.gi.St;
const Lang = imports.lang;
const PopupMenu = imports.ui.popupMenu;
const Main = imports.ui.main;
function Button(menuAlignment) {
this._init(menuAlignment);
}
Button.prototype = {
_init: function(menuAlignment) {
this.actor = new St.Bin({ style_class: 'panel-button',
reactive: true,
x_fill: true,
y_fill: false,
track_hover: true });
this.actor._delegate = this;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, /* FIXME */ 0);
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
Main.chrome.addActor(this.menu.actor, { visibleInOverview: true,
affectsStruts: false });
this.menu.actor.hide();
},
_onButtonPress: function(actor, event) {
this.menu.toggle();
},
_onOpenStateChanged: function(menu, open) {
if (open)
this.actor.add_style_pseudo_class('pressed');
else
this.actor.remove_style_pseudo_class('pressed');
}
};
/* SystemStatusButton:
*
* This class manages one System Status indicator (network, keyboard,
* volume, bluetooth...), which is just a PanelMenuButton with an
* icon and a tooltip
*/
function SystemStatusButton() {
this._init.apply(this, arguments);
}
SystemStatusButton.prototype = {
__proto__: Button.prototype,
_init: function(iconName,tooltipText) {
Button.prototype._init.call(this, St.Align.START);
this._iconActor = null;
this.setIcon(iconName);
this.setTooltip(tooltipText);
},
setIcon: function(iconName) {
this._iconName = iconName;
if (this._iconActor)
this._iconActor.destroy();
this._iconActor = St.TextureCache.get_default().load_icon_name(this._iconName, St.IconType.SYMBOLIC, 24);
this.actor.set_child(this._iconActor);
},
setTooltip: function(text) {
if (text != null) {
this.tooltip = text;
this.actor.has_tooltip = true;
this.actor.tooltip_text = text;
} else {
this.actor.has_tooltip = false;
this.tooltip = null;
}
}
};

613
js/ui/placeDisplay.js Normal file
View File

@ -0,0 +1,613 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const GConf = imports.gi.GConf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const DND = imports.ui.dnd;
const Main = imports.ui.main;
const Search = imports.ui.search;
const NAUTILUS_PREFS_DIR = '/apps/nautilus/preferences';
const DESKTOP_IS_HOME_KEY = NAUTILUS_PREFS_DIR + '/desktop_is_home_dir';
const PLACES_ICON_SIZE = 16;
/**
* Represents a place object, which is most normally a bookmark entry,
* a mount/volume, or a special place like the Home Folder, Computer, and Network.
*
* @name: String title
* @iconFactory: A JavaScript callback which will create an icon texture given a size parameter
* @launch: A JavaScript callback to launch the entry
*/
function PlaceInfo(id, name, iconFactory, launch) {
this._init(id, name, iconFactory, launch);
}
PlaceInfo.prototype = {
_init: function(id, name, iconFactory, launch) {
this.id = id;
this.name = name;
this._lowerName = name.toLowerCase();
this.iconFactory = iconFactory;
this.launch = launch;
},
matchTerms: function(terms) {
let mtype = Search.MatchType.NONE;
for (let i = 0; i < terms.length; i++) {
let term = terms[i];
let idx = this._lowerName.indexOf(term);
if (idx == 0) {
mtype = Search.MatchType.PREFIX;
} else if (idx > 0) {
if (mtype == Search.MatchType.NONE)
mtype = Search.MatchType.SUBSTRING;
} else {
return Search.MatchType.NONE;
}
}
return mtype;
},
isRemovable: function() {
return false;
}
};
function PlaceDeviceInfo(mount) {
this._init(mount);
}
PlaceDeviceInfo.prototype = {
__proto__: PlaceInfo.prototype,
_init: function(mount) {
this._mount = mount;
this.name = mount.get_name();
this._lowerName = this.name.toLowerCase();
this.id = 'mount:' + mount.get_root().get_uri();
},
iconFactory: function(size) {
let icon = this._mount.get_icon();
return St.TextureCache.get_default().load_gicon(icon, size);
},
launch: function() {
Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(),
global.create_app_launch_context());
},
isRemovable: function() {
return this._mount.can_unmount();
},
remove: function() {
if (!this.isRemovable())
return;
if (this._mount.can_eject())
this._mount.eject(0, null, Lang.bind(this, this._removeFinish));
else
this._mount.unmount(0, null, Lang.bind(this, this._removeFinish));
},
_removeFinish: function(o, res, data) {
try {
if (this._mount.can_eject())
this._mount.eject_finish(res);
else
this._mount.unmount_finish(res);
} catch (e) {
let message = _("Failed to unmount '%s'").format(o.get_name());
Main.overview.infoBar.setMessage(message,
Lang.bind(this, this.remove),
_("Retry"));
}
}
};
function PlacesManager() {
this._init();
}
PlacesManager.prototype = {
_init: function() {
let gconf = GConf.Client.get_default();
gconf.add_dir(NAUTILUS_PREFS_DIR, GConf.ClientPreloadType.PRELOAD_NONE);
this._defaultPlaces = [];
this._mounts = [];
this._bookmarks = [];
this._isDesktopHome = gconf.get_bool(DESKTOP_IS_HOME_KEY);
let homeFile = Gio.file_new_for_path (GLib.get_home_dir());
let homeUri = homeFile.get_uri();
let homeLabel = Shell.util_get_label_for_uri (homeUri);
let homeIcon = Shell.util_get_icon_for_uri (homeUri);
this._home = new PlaceInfo('special:home', homeLabel,
function(size) {
return St.TextureCache.get_default().load_gicon(homeIcon, size);
},
function() {
Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context());
});
let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP);
let desktopFile = Gio.file_new_for_path (desktopPath);
let desktopUri = desktopFile.get_uri();
let desktopLabel = Shell.util_get_label_for_uri (desktopUri);
let desktopIcon = Shell.util_get_icon_for_uri (desktopUri);
this._desktopMenu = new PlaceInfo('special:desktop', desktopLabel,
function(size) {
return St.TextureCache.get_default().load_gicon(desktopIcon, size);
},
function() {
Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context());
});
this._connect = new PlaceInfo('special:connect', _("Connect to..."),
function (size) {
return St.TextureCache.get_default().load_icon_name('applications-internet', St.IconType.FULLCOLOR, size);
},
function () {
new Shell.Process({ args: ['nautilus-connect-server'] }).run();
});
let networkApp = null;
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('gnome-network-scheme.desktop');
} catch(e) {
try {
networkApp = Shell.AppSystem.get_default().load_from_desktop_file('network-scheme.desktop');
} catch(e) {
log('Cannot create "Network" item, .desktop file not found or corrupt.');
}
}
if (networkApp != null) {
this._network = new PlaceInfo('special:network', networkApp.get_name(),
function(size) {
return networkApp.create_icon_texture(size);
},
function () {
networkApp.launch();
});
}
this._defaultPlaces.push(this._home);
this._desktopMenuIndex = this._defaultPlaces.length;
if (!this._isDesktopHome)
this._defaultPlaces.push(this._desktopMenu);
if (this._network)
this._defaultPlaces.push(this._network);
this._defaultPlaces.push(this._connect);
/*
* Show devices, code more or less ported from nautilus-places-sidebar.c
*/
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();
this._bookmarksPath = GLib.build_filenamev([GLib.get_home_dir(), '.gtk-bookmarks']);
this._bookmarksFile = Gio.file_new_for_path(this._bookmarksPath);
let monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._bookmarkTimeoutId = 0;
monitor.connect('changed', Lang.bind(this, function () {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
this._bookmarkTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
this._bookmarkTimeoutId = 0;
this._reloadBookmarks();
return false;
}));
}));
this._reloadBookmarks();
gconf.notify_add(DESKTOP_IS_HOME_KEY, Lang.bind(this, this._updateDesktopMenuVisibility));
},
_updateDevices: function() {
this._mounts = [];
/* 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]);
}
/* We emit two signals, one for a generic 'all places' update
* and the other for one specific to mounts. We do this because
* clients like PlaceDisplay may only care about places in general
* being updated while clients like DashPlaceDisplay care which
* specific type of place got updated.
*/
this.emit('mounts-updated');
this.emit('places-updated');
},
_reloadBookmarks: function() {
this._bookmarks = [];
if (!GLib.file_test(this._bookmarksPath, GLib.FileTest.EXISTS))
return;
let [success, bookmarksContent, len] = GLib.file_get_contents(this._bookmarksPath);
if (!success)
return;
let bookmarks = bookmarksContent.split('\n');
let bookmarksToLabel = {};
let bookmarksOrder = [];
for (let i = 0; i < bookmarks.length; i++) {
let bookmarkLine = bookmarks[i];
let components = bookmarkLine.split(' ');
let bookmark = components[0];
if (bookmark in bookmarksToLabel)
continue;
let label = null;
if (components.length > 1)
label = components.slice(1).join(' ');
bookmarksToLabel[bookmark] = label;
bookmarksOrder.push(bookmark);
}
for (let i = 0; i < bookmarksOrder.length; i++) {
let bookmark = bookmarksOrder[i];
let label = bookmarksToLabel[bookmark];
let file = Gio.file_new_for_uri(bookmark);
if (!file.query_exists(null))
continue;
if (label == null)
label = Shell.util_get_label_for_uri(bookmark);
if (label == null)
continue;
let icon = Shell.util_get_icon_for_uri(bookmark);
let item = new PlaceInfo('bookmark:' + bookmark, label,
function(size) {
return St.TextureCache.get_default().load_gicon(icon, size);
},
function() {
Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context());
});
this._bookmarks.push(item);
}
/* See comment in _updateDevices for explanation why there are two signals. */
this.emit('bookmarks-updated');
this.emit('places-updated');
},
_updateDesktopMenuVisibility: function() {
let gconf = GConf.Client.get_default();
this._isDesktopHome = gconf.get_boolean(DESKTOP_IS_HOME_KEY);
if (this._isDesktopHome)
this._removeById(this._defaultPlaces, 'special:desktop');
else
this._defaultPlaces.splice(this._desktopMenuIndex, 0,
this._desktopMenu);
/* See comment in _updateDevices for explanation why there are two signals. */
this.emit('defaults-updated');
this.emit('places-updated');
},
_addMount: function(mount) {
let devItem = new PlaceDeviceInfo(mount);
this._mounts.push(devItem);
},
getAllPlaces: function () {
return this.getDefaultPlaces().concat(this.getBookmarks(), this.getMounts());
},
getDefaultPlaces: function () {
return this._defaultPlaces;
},
getBookmarks: function () {
return this._bookmarks;
},
getMounts: function () {
return this._mounts;
},
_lookupIndexById: function(sourceArray, id) {
for (let i = 0; i < sourceArray.length; i++) {
let place = sourceArray[i];
if (place.id == id)
return i;
}
return -1;
},
lookupPlaceById: function(id) {
let colonIdx = id.indexOf(':');
let type = id.substring(0, colonIdx);
let sourceArray = null;
if (type == 'special')
sourceArray = this._defaultPlaces;
else if (type == 'mount')
sourceArray = this._mounts;
else if (type == 'bookmark')
sourceArray = this._bookmarks;
return sourceArray[this._lookupIndexById(sourceArray, id)];
},
_removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
}
};
Signals.addSignalMethods(PlacesManager.prototype);
/**
* An entry in the places menu.
* @info The corresponding PlaceInfo to populate this entry.
*/
function DashPlaceDisplayItem(info) {
this._init(info);
}
DashPlaceDisplayItem.prototype = {
_init: function(info) {
this.name = info.name;
this._info = info;
this._icon = info.iconFactory(PLACES_ICON_SIZE);
this.actor = new St.Clickable({ style_class: 'places-item',
reactive: true,
x_align: St.Align.START,
x_fill: true });
let box = new St.BoxLayout({ style_class: 'places-item-box' });
this.actor.set_child(box);
let bin = new St.Bin({ child: this._icon });
box.add(bin);
let text = new St.Label({ text: info.name });
box.add(text, { expand: true, x_fill: true });
if (info.isRemovable()) {
let removeIcon = St.TextureCache.get_default().load_icon_name ('media-eject', St.IconType.FULLCOLOR, PLACES_ICON_SIZE);
let removeIconBox = new St.Clickable({ child: removeIcon,
reactive: true });
box.add(removeIconBox);
removeIconBox.connect('clicked',
Lang.bind(this, function() {
this._info.remove();
}));
}
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor._delegate = this;
this._draggable = DND.makeDraggable(this.actor);
this._draggable.connect('drag-begin',
Lang.bind(this, function() {
Main.overview.beginItemDrag(this);
}));
this._draggable.connect('drag-end',
Lang.bind(this, function() {
Main.overview.endItemDrag(this);
}));
},
_onClicked: function(b) {
this._info.launch();
Main.overview.hide();
},
getDragActorSource: function() {
return this._icon;
},
getDragActor: function(stageX, stageY) {
return this._info.iconFactory(PLACES_ICON_SIZE);
},
//// Drag and drop methods ////
shellWorkspaceLaunch: function() {
this._info.launch();
}
};
function DashPlaceDisplay() {
this._init();
}
DashPlaceDisplay.prototype = {
_init: function() {
// Places is divided semi-arbitrarily into left and right; a grid would
// look better in that there would be an even number of items left+right,
// but it seems like we want some sort of differentiation between actions
// like "Connect to server..." and regular folders
this.actor = new St.Table({ style_class: 'places-section',
homogeneous: true });
this._defaultsList = [];
this._bookmarksList = [];
this._mountsList = [];
Main.placesManager.connect('defaults-updated', Lang.bind(this, this._updateDefaults));
Main.placesManager.connect('bookmarks-updated', Lang.bind(this, this._updateBookmarks));
Main.placesManager.connect('mounts-updated', Lang.bind(this, this._updateMounts));
this._updateDefaults();
this._updateMounts();
this._updateBookmarks();
},
_updateDefaults: function() {
for (let i = 0; i < this._defaultsList.length; i++)
this._defaultsList[i].destroy();
this._defaultsList = [];
let places = Main.placesManager.getDefaultPlaces();
for (let i = 0; i < places.length; i++) {
this._defaultsList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._defaultsList[i], {row: i, col: 0});
}
this._updateMounts();
},
_updateMounts: function() {
for (let i = 0; i < this._mountsList.length; i++)
this._mountsList[i].destroy();
this._mountsList = [];
let places = Main.placesManager.getMounts();
for (let i = 0; i < places.length; i++) {
this._mountsList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._mountsList[i], {row: this._defaultsList.length + i, col: 0});
}
},
_updateBookmarks: function() {
for (let i = 0; i < this._bookmarksList.length; i++)
this._bookmarksList[i].destroy();
this._bookmarksList = [];
let places = Main.placesManager.getBookmarks();
for (let i = 0; i < places.length; i ++) {
this._bookmarksList[i] = new DashPlaceDisplayItem(places[i]).actor;
this.actor.add(this._bookmarksList[i], {row: i, col: 1});
}
}
};
Signals.addSignalMethods(DashPlaceDisplay.prototype);
function PlaceSearchProvider() {
this._init();
}
PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
},
getResultMeta: function(resultId) {
let placeInfo = Main.placesManager.lookupPlaceById(resultId);
if (!placeInfo)
return null;
return { 'id': resultId,
'name': placeInfo.name,
'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) };
},
activateResult: function(id) {
let placeInfo = Main.placesManager.lookupPlaceById(id);
placeInfo.launch();
},
_compareResultMeta: function (idA, idB) {
let infoA = Main.placesManager.lookupPlaceById(idA);
let infoB = Main.placesManager.lookupPlaceById(idB);
return infoA.name.localeCompare(infoB.name);
},
_searchPlaces: function(places, terms) {
let multiplePrefixResults = [];
let prefixResults = [];
let multipleSubstringResults = [];
let substringResults = [];
terms = terms.map(String.toLowerCase);
for (let i = 0; i < places.length; i++) {
let place = places[i];
let mtype = place.matchTerms(terms);
if (mtype == Search.MatchType.MULTIPLE_PREFIX)
multiplePrefixResults.push(place.id);
else if (mtype == Search.MatchType.PREFIX)
prefixResults.push(place.id);
else if (mtype == Search.MatchType.MULTIPLE_SUBSTRING)
multipleSubstringResults.push(place.id);
else if (mtype == Search.MatchType.SUBSTRING)
substringResults.push(place.id);
}
multiplePrefixResults.sort(this._compareResultMeta);
prefixResults.sort(this._compareResultMeta);
multipleSubstringResults.sort(this._compareResultMeta);
substringResults.sort(this._compareResultMeta);
return multiplePrefixResults.concat(prefixResults.concat(multipleSubstringResults.concat(substringResults)));
},
getInitialResultSet: function(terms) {
let places = Main.placesManager.getAllPlaces();
return this._searchPlaces(places, terms);
},
getSubsearchResultSet: function(previousResults, terms) {
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
return this._searchPlaces(places, terms);
}
};

View File

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

1011
js/ui/popupMenu.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
/* -*- 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 GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell');
@ -13,31 +13,183 @@ const _ = Gettext.gettext;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const BOX_BACKGROUND_COLOR = new Clutter.Color();
BOX_BACKGROUND_COLOR.from_pixel(0x000000cc);
const MAX_FILE_DELETED_BEFORE_INVALID = 10;
const BOX_TEXT_COLOR = new Clutter.Color();
BOX_TEXT_COLOR.from_pixel(0xffffffff);
const HISTORY_KEY = 'command-history';
const HISTORY_LIMIT = 512;
const DIALOG_WIDTH = 320;
const DIALOG_PADDING = 6;
const ICON_SIZE = 24;
const ICON_BOX_SIZE = 36;
const DIALOG_FADE_TIME = 0.1;
function CommandCompleter() {
this._init();
}
CommandCompleter.prototype = {
_init : function() {
this._changedCount = 0;
this._paths = GLib.getenv('PATH').split(':');
this._paths.push(GLib.get_home_dir());
this._valid = false;
this._updateInProgress = false;
this._childs = new Array(this._paths.length);
this._monitors = new Array(this._paths.length);
for (let i = 0; i < this._paths.length; i++) {
this._childs[i] = [];
let file = Gio.file_new_for_path(this._paths[i]);
let info;
try {
info = file.query_info(Gio.FILE_ATTRIBUTE_STANDARD_TYPE, Gio.FileQueryInfoFlags.NONE, null);
} catch (e) {
// FIXME catchall
this._paths[i] = null;
continue;
}
if (info.get_attribute_uint32(Gio.FILE_ATTRIBUTE_STANDARD_TYPE) != Gio.FileType.DIRECTORY)
continue;
this._paths[i] = file.get_path();
this._monitors[i] = file.monitor_directory(Gio.FileMonitorFlags.NONE, null);
if (this._monitors[i] != null) {
this._monitors[i].connect('changed', Lang.bind(this, this._onChanged));
}
}
this._paths = this._paths.filter(function(a) {
return a != null;
});
this._update(0);
},
_onGetEnumerateComplete : function(obj, res) {
this._enumerator = obj.enumerate_children_finish(res);
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
},
_onNextFileComplete : function(obj, res) {
let files = obj.next_files_finish(res);
for (let i = 0; i < files.length; i++) {
this._childs[this._i].push(files[i].get_name());
}
if (files.length) {
this._enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onNextFileComplete));
} else {
this._enumerator.close(null);
this._enumerator = null;
this._update(this._i + 1);
}
},
update : function() {
if (this._valid)
return;
this._update(0);
},
_update : function(i) {
if (i == 0 && this._updateInProgress)
return;
this._updateInProgress = true;
this._changedCount = 0;
this._i = i;
if (i >= this._paths.length) {
this._valid = true;
this._updateInProgress = false;
return;
}
let file = Gio.file_new_for_path(this._paths[i]);
this._childs[this._i] = [];
file.enumerate_children_async(Gio.FILE_ATTRIBUTE_STANDARD_NAME, Gio.FileQueryInfoFlags.NONE, GLib.PRIORITY_LOW, null, Lang.bind(this, this._onGetEnumerateComplete));
},
_onChanged : function(m, f, of, type) {
if (!this._valid)
return;
let path = f.get_parent().get_path();
let k = undefined;
for (let i = 0; i < this._paths.length; i++) {
if (this._paths[i] == path)
k = i;
}
if (k === undefined) {
return;
}
if (type == Gio.FileMonitorEvent.CREATED) {
this._childs[k].push(f.get_basename());
}
if (type == Gio.FileMonitorEvent.DELETED) {
this._changedCount++;
if (this._changedCount > MAX_FILE_DELETED_BEFORE_INVALID) {
this._valid = false;
}
let name = f.get_basename();
this._childs[k] = this._childs[k].filter(function(e) {
return e != name;
});
}
if (type == Gio.FileMonitorEvent.UNMOUNTED) {
this._childs[k] = [];
}
},
getCompletion: function(text) {
let common = '';
let notInit = true;
if (!this._valid) {
this._update(0);
return common;
}
function _getCommon(s1, s2) {
let k = 0;
for (; k < s1.length && k < s2.length; k++) {
if (s1[k] != s2[k])
break;
}
if (k == 0)
return '';
return s1.substr(0, k);
}
function _hasPrefix(s1, prefix) {
return s1.indexOf(prefix) == 0;
}
for (let i = 0; i < this._childs.length; i++) {
for (let k = 0; k < this._childs[i].length; k++) {
if (!_hasPrefix(this._childs[i][k], text))
continue;
if (notInit) {
common = this._childs[i][k];
notInit = false;
}
common = _getCommon(common, this._childs[i][k]);
}
}
if (common.length)
return common.substr(text.length);
return common;
}
};
function RunDialog() {
this._init();
};
}
RunDialog.prototype = {
_init : function() {
this._isOpen = false;
let gconf = Shell.GConf.get_default();
gconf.connect('changed::development_tools', Lang.bind(this, function () {
this._enableInternalCommands = gconf.get_boolean('development_tools');
global.settings.connect('changed::development-tools', Lang.bind(this, function () {
this._enableInternalCommands = global.settings.get_boolean('development-tools');
}));
this._enableInternalCommands = global.settings.get_boolean('development-tools');
this._history = global.settings.get_strv(HISTORY_KEY);
this._historyIndex = -1;
global.settings.connect('changed::' + HISTORY_KEY, Lang.bind(this, function() {
this._history = global.settings.get_strv(HISTORY_KEY);
this._historyIndex = this._history.length;
}));
this._enableInternalCommands = gconf.get_boolean('development_tools');
this._internalCommands = { 'lg':
Lang.bind(this, function() {
@ -60,121 +212,194 @@ RunDialog.prototype = {
// All actors are inside _group. We create it initially
// hidden then show it in show()
this._group = new Clutter.Group({ visible: false });
global.stage.add_actor(this._group);
this._group = new Clutter.Group({ visible: false,
x: 0, y: 0 });
Main.uiGroup.add_actor(this._group);
this._lightbox = new Lightbox.Lightbox(this._group);
this._lightbox = new Lightbox.Lightbox(this._group,
{ inhibitEvents: true });
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 });
this._box = new St.Bin({ x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this._group.add_actor(boxH);
this._lightbox.highlight(boxH);
this._group.add_actor(this._box);
this._lightbox.highlight(this._box);
let boxV = new Big.Box({ orientation: Big.BoxOrientation.VERTICAL,
y_align: Big.BoxAlignment.CENTER });
let dialogBox = new St.BoxLayout({ style_class: 'run-dialog', vertical: true });
boxH.append(boxV, Big.BoxPackFlags.NONE);
this._box.set_child(dialogBox);
let label = new St.Label({ style_class: 'run-dialog-label',
text: _("Please enter a command:") });
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 });
dialogBox.add(label, { expand: true, y_fill: false });
boxH.append(dialogBox, Big.BoxPackFlags.NONE);
let entry = new St.Entry({ style_class: 'run-dialog-entry' });
let label = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '18px Sans',
text: _("Please enter a command:") });
this._entryText = entry.clutter_text;
dialogBox.add(entry, { expand: true });
dialogBox.append(label, Big.BoxPackFlags.EXPAND);
this._errorBox = new St.BoxLayout();
this._entry = new Clutter.Text({ color: BOX_TEXT_COLOR,
font_name: '20px Sans Bold',
editable: true,
activatable: true,
singleLineMode: true });
dialogBox.add(this._errorBox, { expand: true });
dialogBox.append(this._entry, Big.BoxPackFlags.EXPAND);
let errorIcon = new St.Button({ style_class: 'run-dialog-error-icon' });
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._errorBox.add(errorIcon);
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 St.Label({ style_class: 'run-dialog-error-label' });
this._errorMessage.clutter_text.line_wrap = true;
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.add(this._errorMessage, { expand: true });
this._errorBox.hide();
this._entry.connect('activate', Lang.bind(this, function (o, e) {
this._run(o.get_text());
if (!this._commandError)
this.close();
}));
this._entry.connect('key-press-event', Lang.bind(this, function(o, e) {
this._pathCompleter = new Gio.FilenameCompleter();
this._commandCompleter = new CommandCompleter();
this._group.connect('notify::visible', Lang.bind(this._commandCompleter, this._commandCompleter.update));
this._entryText.connect('key-press-event', Lang.bind(this, function(o, e) {
let symbol = e.get_key_symbol();
if (symbol == Clutter.Down) {
this._setCommandFromHistory(this._historyIndex++);
return true;
}
if (symbol == Clutter.Up) {
this._setCommandFromHistory(this._historyIndex--);
return true;
}
if (symbol == Clutter.Return || symbol == Clutter.KP_Enter) {
if (Shell.get_event_state(e) & Clutter.ModifierType.CONTROL_MASK)
this._run(o.get_text(), true);
else
this._run(o.get_text(), false);
if (!this._commandError)
this.close();
}
if (symbol == Clutter.Escape) {
this.close();
return true;
}
if (symbol == Clutter.slash) {
// Need preload data before get completion. GFilenameCompleter load content of parent directory.
// Parent directory for /usr/include/ is /usr/. So need to add fake name('a').
let text = o.get_text().concat('/a');
let prefix;
if (text.lastIndexOf(' ') == -1)
prefix = text;
else
prefix = text.substr(text.lastIndexOf(' ') + 1);
this._getCompletion(prefix);
return false;
}
if (symbol == Clutter.Tab) {
let text = o.get_text();
let prefix;
if (text.lastIndexOf(' ') == -1)
prefix = text;
else
prefix = text.substr(text.lastIndexOf(' ') + 1);
let postfix = this._getCompletion(prefix);
if (postfix != null && postfix.length > 0) {
o.insert_text(postfix, -1);
o.set_cursor_position(text.length + postfix.length);
if (postfix[postfix.length - 1] == '/')
this._getCompletion(text + postfix + 'a');
}
return true;
}
return false;
}));
},
_run : function(command) {
_getCompletion : function(text) {
if (text.indexOf('/') != -1) {
return this._pathCompleter.get_completion_suffix(text);
} else {
return this._commandCompleter.getCompletion(text);
}
},
_saveHistory : function() {
if (this._history.length > HISTORY_LIMIT) {
this._history.splice(0, this._history.length - HISTORY_LIMIT);
}
global.settings.set_strv(HISTORY_KEY, this._history);
},
_run : function(input, inTerminal) {
let command = input;
if (this._history.length == 0 ||
this._history[this._history.length - 1] != input) {
this._history.push(input);
this._saveHistory();
}
this._commandError = false;
let f;
if (this._enableInternalCommands)
f = this._internalCommands[command];
f = this._internalCommands[input];
else
f = null;
if (f) {
f();
} else if (command) {
} else if (input) {
try {
this._commandError = false;
if (inTerminal)
command = 'gnome-terminal -x ' + input;
let [ok, len, args] = GLib.shell_parse_argv(command);
let p = new Shell.Process({'args' : args});
let p = new Shell.Process({ 'args' : args });
p.run();
} catch (e) {
this._commandError = true;
/*
* The exception contains an error string like:
* Error invoking Shell.run: Failed to execute child process "foo"
* (No such file or directory)
* We are only interested in the actual error, so parse that out.
*/
let m = /.+\((.+)\)/.exec(e);
let errorStr = "Execution of '" + command + "' failed:\n" + m[1];
this._errorMessage.set_text(errorStr);
this._errorBox.show();
// Mmmh, that failed - see if @input matches an existing file
let path = null;
if (input.charAt(0) == '/') {
path = input;
} else {
if (input.charAt(0) == '~')
input = input.slice(1);
path = GLib.get_home_dir() + '/' + input;
}
if (GLib.file_test(path, GLib.FileTest.EXISTS)) {
let file = Gio.file_new_for_path(path);
Gio.app_info_launch_default_for_uri(file.get_uri(),
global.create_app_launch_context());
} else {
this._commandError = true;
// The exception contains an error string like:
// Error invoking Shell.run: Failed to execute child
// process "foo" (No such file or directory)
// We are only interested in the actual error, so parse
//that out.
let m = /.+\((.+)\)/.exec(e);
let errorStr = _("Execution of '%s' failed:").format(command) + '\n' + m[1];
this._errorMessage.set_text(errorStr);
this._errorBox.show();
}
}
}
},
_setCommandFromHistory: function(lastI) {
if (this._historyIndex < 0)
this._historyIndex = 0;
if (this._historyIndex > this._history.length)
this._historyIndex = this._history.length;
let text = this._entryText.get_text();
if (text) {
this._history[lastI] = text;
}
if (this._history[this._historyIndex]) {
this._entryText.set_text(this._history[this._historyIndex]);
} else
this._entryText.set_text('');
},
open : function() {
if (this._isOpen) // Already shown
return;
@ -182,10 +407,25 @@ RunDialog.prototype = {
if (!Main.pushModal(this._group))
return;
this._isOpen = true;
this._group.show();
// Position the dialog on the current monitor
let monitor = global.get_focus_monitor();
global.stage.set_key_focus(this._entry);
this._historyIndex = this._history.length;
this._box.set_position(monitor.x, monitor.y);
this._box.set_size(monitor.width, monitor.height);
this._isOpen = true;
this._lightbox.show();
this._group.opacity = 0;
this._group.show();
Tweener.addTween(this._group,
{ opacity: 255,
time: DIALOG_FADE_TIME,
transition: 'easeOutQuad'
});
global.stage.set_key_focus(this._entryText);
},
close : function() {
@ -193,14 +433,20 @@ RunDialog.prototype = {
return;
this._isOpen = false;
this._errorBox.hide();
this._commandError = false;
this._group.hide();
this._entry.text = '';
Main.popModal(this._group);
Tweener.addTween(this._group,
{ opacity: 0,
time: DIALOG_FADE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this, function() {
this._errorBox.hide();
this._group.hide();
this._entryText.set_text('');
})
});
}
};
Signals.addSignalMethods(RunDialog.prototype);

260
js/ui/scripting.js Normal file
View File

@ -0,0 +1,260 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
// This module provides functionality for driving the shell user interface
// in an automated fashion. The primary current use case for this is
// automated performance testing (see runPerfScript()), but it could
// be applied to other forms of automation, such as testing for
// correctness as well.
//
// When scripting an automated test we want to make a series of calls
// in a linear fashion, but we also want to be able to let the main
// loop run so actions can finish. For this reason we write the script
// as a generator function that yields when it want to let the main
// loop run.
//
// yield Scripting.sleep(1000);
// main.overview.show();
// yield Scripting.waitLeisure();
//
// While it isn't important to the person writing the script, the actual
// yielded result is a function that the caller uses to provide the
// callback for resuming the script.
/**
* sleep:
* @milliseconds: number of milliseconds to wait
*
* Used within an automation script to pause the the execution of the
* current script for the specified amount of time. Use as
* 'yield Scripting.sleep(500);'
*/
function sleep(milliseconds) {
let cb;
Mainloop.timeout_add(milliseconds, function() {
if (cb)
cb();
return false;
});
return function(callback) {
cb = callback;
};
}
/**
* waitLeisure:
*
* Used within an automation script to pause the the execution of the
* current script until the shell is completely idle. Use as
* 'yield Scripting.waitLeisure();'
*/
function waitLeisure() {
let cb;
global.run_at_leisure(function() {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
/**
* defineScriptEvent
* @name: The event will be called script.<name>
* @description: Short human-readable description of the event
*
* Convenience function to define a zero-argument performance event
* within the 'script' namespace that is reserved for events defined locally
* within a performance automation script
*/
function defineScriptEvent(name, description) {
Shell.PerfLog.get_default().define_event("script." + name,
description,
"");
}
/**
* scriptEvent
* @name: Name registered with defineScriptEvent()
*
* Convenience function to record a script-local performance event
* previously defined with defineScriptEvent
*/
function scriptEvent(name) {
Shell.PerfLog.get_default().event("script." + name);
}
/**
* collectStatistics
*
* Convenience function to trigger statistics collection
*/
function collectStatistics() {
Shell.PerfLog.get_default().collect_statistics();
}
function _step(g, finish, onError) {
try {
let waitFunction = g.next();
waitFunction(function() {
_step(g, finish, onError);
});
} catch (err if err instanceof StopIteration) {
if (finish)
finish();
} catch (err) {
if (onError)
onError(err);
}
}
function _collect(scriptModule, outputFile) {
let eventHandlers = {};
for (let f in scriptModule) {
let m = /([A-Za-z]+)_([A-Za-z]+)/.exec(f);
if (m)
eventHandlers[m[1] + "." + m[2]] = scriptModule[f];
}
Shell.PerfLog.get_default().replay(
function(time, eventName, signature, arg) {
if (eventName in eventHandlers)
eventHandlers[eventName](time, arg);
});
if ('finish' in scriptModule)
scriptModule.finish();
if (outputFile) {
let f = Gio.file_new_for_path(outputFile);
let raw = f.replace(null, false,
Gio.FileCreateFlags.NONE,
null);
let out = Gio.BufferedOutputStream.new_sized (raw, 4096);
Shell.write_string_to_stream (out, "{\n");
Shell.write_string_to_stream(out, '"events":\n');
Shell.PerfLog.get_default().dump_events(out);
let monitors = global.get_monitors()
let primary = global.get_primary_monitor()
Shell.write_string_to_stream(out, ',\n"monitors":\n[');
for (let i = 0; i < monitors.length; i++) {
let monitor = monitors[i];
let is_primary = (monitor.x == primary.x &&
monitor.y == primary.y &&
monitor.width == primary.width &&
monitor.height == primary.height);
if (i != 0)
Shell.write_string_to_stream(out, ', ');
Shell.write_string_to_stream(out, '"%s%dx%d+%d+%d"'.format(is_primary ? "*" : "",
monitor.width, monitor.height,
monitor.x, monitor.y));
}
Shell.write_string_to_stream(out, ' ]');
Shell.write_string_to_stream(out, ',\n"metrics":\n[ ');
let first = true;
for (let name in scriptModule.METRICS) {
let metric = scriptModule.METRICS[name];
if (!first)
Shell.write_string_to_stream(out, ',\n ');
first = false;
Shell.write_string_to_stream(out,
'{ "name": ' + JSON.stringify(name) + ',\n' +
' "description": ' + JSON.stringify(metric.description) + ',\n' +
' "units": ' + JSON.stringify(metric.units) + ',\n' +
' "value": ' + JSON.stringify(metric.value) + ' }');
}
Shell.write_string_to_stream(out, ' ]');
Shell.write_string_to_stream (out, ',\n"log":\n');
Shell.PerfLog.get_default().dump_log(out);
Shell.write_string_to_stream (out, '\n}\n');
out.close(null);
} else {
let metrics = [];
for (let metric in scriptModule.METRICS)
metrics.push(metric);
metrics.sort();
print ('------------------------------------------------------------');
for (let i = 0; i < metrics.length; i++) {
let metric = metrics[i];
print ('# ' + scriptModule.METRIC_DESCRIPTIONS[metric]);
print (metric + ': ' + scriptModule.METRICS[metric]);
}
print ('------------------------------------------------------------');
}
}
/**
* runPerfScript
* @scriptModule: module object with run and finish functions
* and event handlers
*
* Runs a script for automated collection of performance data. The
* script is defined as a Javascript module with specified contents.
*
* First the run() function within the module will be called as a
* generator to automate a series of actions. These actions will
* trigger performance events and the script can also record its
* own performance events.
*
* Then the recorded event log is replayed using handler functions
* within the module. The handler for the event 'foo.bar' is called
* foo_bar().
*
* Finally if the module has a function called finish(), that will
* be called.
*
* The event handler and finish functions are expected to fill in
* metrics to an object within the module called METRICS. Each
* property of this object represents an individual metric. The
* name of the property is the name of the metric, the value
* of the property is an object with the following properties:
*
* description: human readable description of the metric
* units: a string representing the units of the metric. It has
* the form '<unit> <unit> ... / <unit> / <unit> ...'. Certain
* unit values are recognized: s, ms, us, B, KiB, MiB. Other
* values can appear but are uninterpreted. Examples 's',
* '/ s', 'frames', 'frames / s', 'MiB / s / frame'
* value: computed value of the metric
*
* The resulting metrics will be written to @outputFile as JSON, or,
* if @outputFile is not provided, logged.
*
* After running the script and collecting statistics from the
* event log, GNOME Shell will exit.
**/
function runPerfScript(scriptModule, outputFile) {
Shell.PerfLog.get_default().set_enabled(true);
let g = scriptModule.run();
_step(g,
function() {
_collect(scriptModule, outputFile);
Meta.exit(Meta.ExitCode.SUCCESS);
},
function(err) {
log("Script failed: " + err + "\n" + err.stack);
Meta.exit(Meta.ExitCode.ERROR);
});
}

288
js/ui/search.js Normal file
View File

@ -0,0 +1,288 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Signals = imports.signals;
const RESULT_ICON_SIZE = 24;
// Not currently referenced by the search API, but
// this enumeration can be useful for provider
// implementations.
const MatchType = {
NONE: 0,
SUBSTRING: 1,
MULTIPLE_SUBSTRING: 2,
PREFIX: 3,
MULTIPLE_PREFIX: 4
};
function SearchResultDisplay(provider) {
this._init(provider);
}
SearchResultDisplay.prototype = {
_init: function(provider) {
this.provider = provider;
this.actor = null;
this.selectionIndex = -1;
},
/**
* renderResults:
* @results: List of identifier strings
* @terms: List of search term strings
*
* Display the given search matches which resulted
* from the given terms. It's expected that not
* all results will fit in the space for the container
* actor; in this case, show as many as makes sense
* for your result type.
*
* The terms are useful for search match highlighting.
*/
renderResults: function(results, terms) {
throw new Error('Not implemented');
},
/**
* clear:
* Remove all results from this display and reset the selection index.
*/
clear: function() {
this.actor.get_children().forEach(function (actor) { actor.destroy(); });
this.selectionIndex = -1;
},
/**
* getSelectionIndex:
*
* Returns the index of the selected actor, or -1 if none.
*/
getSelectionIndex: function() {
return this.selectionIndex;
},
/**
* getVisibleResultCount:
*
* Returns: The number of actors visible.
*/
getVisibleResultCount: function() {
throw new Error('Not implemented');
},
/**
* selectIndex:
* @index: Integer index
*
* Move selection to the given index.
* Return true if successful, false if no more results
* available.
*/
selectIndex: function() {
throw new Error('Not implemented');
},
/**
* Activate the currently selected search result.
*/
activateSelected: function() {
throw new Error('Not implemented');
}
};
/**
* SearchProvider:
*
* Subclass this object to add a new result type
* to the search system, then call registerProvider()
* in SearchSystem with an instance.
*/
function SearchProvider(title) {
this._init(title);
}
SearchProvider.prototype = {
_init: function(title) {
this.title = title;
},
/**
* getInitialResultSet:
* @terms: Array of search terms, treated as logical AND
*
* Called when the user first begins a search (most likely
* therefore a single term of length one or two), or when
* a new term is added.
*
* Should return an array of result identifier strings representing
* items which match the given search terms. This
* is expected to be a substring match on the metadata for a given
* item. Ordering of returned results is up to the discretion of the provider,
* but you should follow these heruistics:
*
* * Put items where the term matches multiple criteria (e.g. name and
* description) before single matches
* * Put items which match on a prefix before non-prefix substring matches
*
* This function should be fast; do not perform unindexed full-text searches
* or network queries.
*/
getInitialResultSet: function(terms) {
throw new Error('Not implemented');
},
/**
* getSubsearchResultSet:
* @previousResults: Array of item identifiers
* @newTerms: Updated search terms
*
* Called when a search is performed which is a "subsearch" of
* the previous search; i.e. when every search term has exactly
* one corresponding term in the previous search which is a prefix
* of the new term.
*
* This allows search providers to only search through the previous
* result set, rather than possibly performing a full re-query.
*/
getSubsearchResultSet: function(previousResults, newTerms) {
throw new Error('Not implemented');
},
/**
* getResultInfo:
* @id: Result identifier string
*
* Return an object with 'id', 'name', (both strings) and 'icon' (Clutter.Texture)
* properties which describe the given search result.
*/
getResultMeta: function(id) {
throw new Error('Not implemented');
},
/**
* createResultContainer:
*
* Search providers may optionally override this to render their
* results in a custom fashion. The default implementation
* will create a vertical list.
*
* Returns: An instance of SearchResultDisplay.
*/
createResultContainerActor: function() {
return null;
},
/**
* createResultActor:
* @resultMeta: Object with result metadata
* @terms: Array of search terms, should be used for highlighting
*
* Search providers may optionally override this to render a
* particular serch result in a custom fashion. The default
* implementation will show the icon next to the name.
*
* The actor should be an instance of St.Widget, with the style class
* 'dash-search-result-content'.
*/
createResultActor: function(resultMeta, terms) {
return null;
},
/**
* activateResult:
* @id: Result identifier string
*
* Called when the user chooses a given result.
*/
activateResult: function(id) {
throw new Error('Not implemented');
},
/**
* expandSearch:
*
* Called when the user clicks on the header for this
* search section. Should typically launch an external program
* displaying search results for that item type.
*/
expandSearch: function(terms) {
throw new Error('Not implemented');
}
};
Signals.addSignalMethods(SearchProvider.prototype);
function SearchSystem() {
this._init();
}
SearchSystem.prototype = {
_init: function() {
this._providers = [];
this.reset();
},
registerProvider: function (provider) {
this._providers.push(provider);
},
getProviders: function() {
return this._providers;
},
getTerms: function() {
return this._previousTerms;
},
reset: function() {
this._previousTerms = [];
this._previousResults = [];
},
updateSearch: function(searchString) {
searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
if (searchString == '')
return null;
let terms = searchString.split(/\s+/);
let isSubSearch = terms.length == this._previousTerms.length;
if (isSubSearch) {
for (let i = 0; i < terms.length; i++) {
if (terms[i].indexOf(this._previousTerms[i]) != 0) {
isSubSearch = false;
break;
}
}
}
let results = [];
if (isSubSearch) {
for (let i = 0; i < this._previousResults.length; i++) {
let [provider, previousResults] = this._previousResults[i];
try {
let providerResults = provider.getSubsearchResultSet(previousResults, terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
} catch (error) {
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
}
}
} else {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
try {
let providerResults = provider.getInitialResultSet(terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
} catch (error) {
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
}
}
}
this._previousTerms = terms;
this._previousResults = results;
return results;
}
};
Signals.addSignalMethods(SearchSystem.prototype);

View File

@ -1,23 +1,20 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const GnomeShellIface = {
name: "org.gnome.Shell",
methods: [{ name: "Eval",
inSignature: "s",
outSignature: "bs"
name: 'org.gnome.Shell',
methods: [{ name: 'Eval',
inSignature: 's',
outSignature: 'bs'
}
],
signals: [],
properties: [{ name: "OverviewActive",
signature: "b",
access: "readwrite" }]
properties: [{ name: 'OverviewActive',
signature: 'b',
access: 'readwrite' }]
};
function GnomeShell() {
@ -48,6 +45,9 @@ GnomeShell.prototype = {
let success;
try {
returnValue = JSON.stringify(eval(code));
// A hack; DBus doesn't have null/undefined
if (returnValue == undefined)
returnValue = '';
success = true;
} catch (e) {
returnValue = JSON.stringify(e);

View File

@ -1,176 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Main = imports.ui.main;
const Panel = imports.ui.panel;
const Tweener = imports.ui.tweener;
const Widget = imports.ui.widget;
const WidgetBox = imports.ui.widgetBox;
const SIDEBAR_SPACING = 4;
const SIDEBAR_PADDING = 4;
// The total sidebar width is the widget width plus the widget padding
// (counted twice for the widget box, and once again for the
// out-of-screen padding), plus the empty space between the border of
// the bar and of the windows
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
function Sidebar() {
this._init();
}
Sidebar.prototype = {
_init : function() {
// 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
// WidgetBox corners on the screen edge side.)
this.actor = new Clutter.Group({ x: -WidgetBox.WIDGETBOX_PADDING,
y: Panel.PANEL_HEIGHT,
width: SIDEBAR_EXPANDED_WIDTH });
// The actual widgets go into a Big.Box inside this.actor. The
// box's width will vary during the expand/collapse animations,
// but this.actor's width will remain constant until we adjust
// it at the end of the animation, because we don't want the
// wm strut to move and cause windows to move multiple times
// during the animation.
this.box = new Big.Box ({ padding_top: SIDEBAR_PADDING,
padding_bottom: SIDEBAR_PADDING,
padding_right: 0,
padding_left: 0,
spacing: SIDEBAR_SPACING });
this.actor.add_actor(this.box);
this._gconf = Shell.GConf.get_default();
this._expanded = this._gconf.get_boolean ("sidebar/expanded");
if (!this._expanded)
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
this._visible = this._gconf.get_boolean ("sidebar/visible");
if (this._visible)
Main.chrome.addActor(this.actor);
this._widgets = [];
this.addWidget(new ToggleWidget());
let default_widgets = this._gconf.get_string_list("sidebar/widgets");
for (let i = 0; i < default_widgets.length; i++)
this.addWidget(default_widgets[i]);
this._gconf.connect('changed::sidebar/expanded',
Lang.bind(this, this._expandedChanged));
this._gconf.connect('changed::sidebar/visible',
Lang.bind(this, this._visibleChanged));
},
addWidget: function(widget) {
let widgetBox;
try {
widgetBox = new WidgetBox.WidgetBox(widget, this._expanded);
} catch(e) {
logError(e, "Failed to add widget '" + widget + "'");
return;
}
this.box.append(widgetBox.actor, Big.BoxPackFlags.NONE);
this._widgets.push(widgetBox);
},
_visibleChanged: function() {
let visible = this._gconf.get_boolean("sidebar/visible");
if (visible == this._visible)
return;
this._visible = visible;
if (visible)
Main.chrome.addActor(this.actor);
else
Main.chrome.removeActor(this.actor);
},
_expandedChanged: function() {
let expanded = this._gconf.get_boolean("sidebar/expanded");
if (expanded == this._expanded)
return;
this._expanded = expanded;
if (expanded)
this._expand();
else
this._collapse();
},
_expand: function() {
this._expanded = true;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].expand();
// Updated the strut/stage area after the animation completes
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
onComplete: function () {
this.actor.width = SIDEBAR_EXPANDED_WIDTH;
} });
},
_collapse: function() {
this._expanded = false;
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].collapse();
// Updated the strut/stage area after the animation completes
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
onComplete: function () {
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
} });
},
destroy: function() {
this.hide();
for (let i = 0; i < this._widgets.length; i++)
this._widgets[i].destroy();
this.actor.destroy();
}
};
const LEFT_DOUBLE_ARROW = "\u00AB";
const RIGHT_DOUBLE_ARROW = "\u00BB";
function ToggleWidget() {
this._init();
}
ToggleWidget.prototype = {
__proto__ : Widget.Widget.prototype,
_init : function() {
this._gconf = Shell.GConf.get_default();
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: LEFT_DOUBLE_ARROW,
reactive: true });
this.actor.connect('button-release-event',
Lang.bind(this, this._collapse));
this.collapsedActor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: RIGHT_DOUBLE_ARROW,
reactive: true });
this.collapsedActor.connect('button-release-event',
Lang.bind(this, this._expand));
},
_collapse : function () {
this._gconf.set_boolean ("sidebar/expanded", false);
},
_expand : function () {
this._gconf.set_boolean ("sidebar/expanded", true);
}
};

View File

@ -0,0 +1,237 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const GConf = imports.gi.GConf;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const KEY_A11Y_DIR = "/desktop/gnome/accessibility";
const KEY_STICKY_KEYS_ENABLED = KEY_A11Y_DIR + "/keyboard/stickykeys_enable";
const KEY_BOUNCE_KEYS_ENABLED = KEY_A11Y_DIR + "/keyboard/bouncekeys_enable";
const KEY_SLOW_KEYS_ENABLED = KEY_A11Y_DIR + "/keyboard/slowkeys_enable";
const KEY_MOUSE_KEYS_ENABLED = KEY_A11Y_DIR + "/keyboard/mousekeys_enable";
const AT_SCREEN_KEYBOARD_SCHEMA = "org.gnome.desktop.default-applications.at.mobility";
const AT_SCREEN_READER_SCHEMA = "org.gnome.desktop.default-applications.at.visual";
const KEY_FONT_DPI = "/desktop/gnome/font_rendering/dpi";
const DPI_LOW_REASONABLE_VALUE = 50;
const DPI_HIGH_REASONABLE_VALUE = 500;
const DPI_FACTOR_LARGE = 1.25;
const DPI_FACTOR_LARGER = 1.5;
const DPI_FACTOR_LARGEST = 2.0;
const DPI_DEFAULT = 96;
const KEY_META_DIR = "/apps/metacity/general";
const KEY_VISUAL_BELL = KEY_META_DIR + "/visual_bell";
const DESKTOP_INTERFACE_SCHEMA = "org.gnome.desktop.interface";
const KEY_GTK_THEME = "gtk-theme";
const KEY_ICON_THEME = "icon-theme";
const HIGH_CONTRAST_THEME = "HighContrast";
function getDPIFromX() {
let screen = global.get_gdk_screen();
if (screen) {
let width_dpi = (screen.get_width() / (screen.get_width_mm() / 25.4));
let height_dpi = (screen.get_height() / (screen.get_height_mm() / 25.4));
if (width_dpi < DPI_LOW_REASONABLE_VALUE
|| width_dpi > DPI_HIGH_REASONABLE_VALUE
|| height_dpi < DPI_LOW_REASONABLE_VALUE
|| height_dpi > DPI_HIGH_REASONABLE_VALUE)
return DPI_DEFAULT;
else
return (width_dpi + height_dpi) / 2;
}
return DPI_DEFAULT;
}
function ATIndicator() {
this._init.apply(this, arguments);
}
ATIndicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-accessibility', null);
let client = GConf.Client.get_default();
client.add_dir(KEY_A11Y_DIR, GConf.ClientPreloadType.PRELOAD_ONELEVEL, null);
client.notify_add(KEY_A11Y_DIR, Lang.bind(this, this._keyChanged), null, null);
client.add_dir(KEY_META_DIR, GConf.ClientPreloadType.PRELOAD_ONELEVEL, null);
client.notify_add(KEY_META_DIR, Lang.bind(this, this._keyChanged), null, null);
let highContrast = this._buildHCItem();
this.menu.addMenuItem(highContrast);
let magnifier = this._buildMagItem();
this.menu.addMenuItem(magnifier);
let textZoom = this._buildFontItem(client);
this.menu.addMenuItem(textZoom);
let screenReader = this._buildItem(_("Screen Reader"), AT_SCREEN_READER_SCHEMA, 'startup');
this.menu.addMenuItem(screenReader);
let screenKeyboard = this._buildItem(_("Screen Keyboard"), AT_SCREEN_KEYBOARD_SCHEMA, 'startup');
this.menu.addMenuItem(screenKeyboard);
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
this.menu.addMenuItem(visualBell);
let stickyKeys = this._buildItemGConf(_("Sticky Keys"), client, KEY_STICKY_KEYS_ENABLED);
this.menu.addMenuItem(stickyKeys);
let slowKeys = this._buildItemGConf(_("Slow Keys"), client, KEY_SLOW_KEYS_ENABLED);
this.menu.addMenuItem(slowKeys);
let bounceKeys = this._buildItemGConf(_("Bounce Keys"), client, KEY_BOUNCE_KEYS_ENABLED);
this.menu.addMenuItem(bounceKeys);
let mouseKeys = this._buildItemGConf(_("Mouse Keys"), client, KEY_MOUSE_KEYS_ENABLED);
this.menu.addMenuItem(mouseKeys);
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Universal Access Settings"), function() {
let p = new Shell.Process({ args: ['gnome-control-center','universal-access'] });
p.run();
});
},
_buildItemExtended: function(string, initial_value, writable, on_set) {
let widget = new PopupMenu.PopupSwitchMenuItem(string, initial_value);
if (!writable)
widget.actor.reactive = false;
else
widget.connect('toggled', function(item) {
on_set(item.state);
});
return widget;
},
_buildItemGConf: function(string, client, key) {
function on_get() {
return client.get_bool(key);
}
let widget = this._buildItemExtended(string,
client.get_bool(key),
client.key_is_writable(key),
function(enabled) {
client.set_bool(key, enabled);
});
this.connect('gconf-changed', function() {
widget.setToggleState(client.get_bool(key));
});
return widget;
},
_buildItem: function(string, schema, key) {
let settings = new Gio.Settings({ schema: schema });
let widget = this._buildItemExtended(string,
settings.get_boolean(key),
settings.is_writable(key),
function(enabled) {
return settings.set_boolean(key, enabled);
});
settings.connect('changed::'+key, function() {
widget.setToggleState(settings.get_boolean(key));
});
return widget;
},
_buildHCItem: function() {
let settings = new Gio.Settings({ schema: DESKTOP_INTERFACE_SCHEMA });
let gtkTheme = settings.get_string(KEY_GTK_THEME);
let iconTheme = settings.get_string(KEY_ICON_THEME);
let hasHC = (gtkTheme == HIGH_CONTRAST_THEME);
let highContrast = this._buildItemExtended(
_("High Contrast"),
hasHC,
settings.is_writable(KEY_GTK_THEME) && settings.is_writable(KEY_ICON_THEME),
function (enabled) {
if (enabled) {
settings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
settings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
} else {
settings.set_string(KEY_GTK_THEME, gtkTheme);
settings.set_string(KEY_ICON_THEME, iconTheme);
}
});
settings.connect('changed::' + KEY_GTK_THEME, function() {
let value = settings.get_string(KEY_GTK_THEME);
if (value == HIGH_CONTRAST_THEME) {
highContrast.setToggleState(true);
} else {
highContrast.setToggleState(false);
gtkTheme = value;
}
});
settings.connect('changed::' + KEY_ICON_THEME, function() {
let value = settings.get_string(KEY_ICON_THEME);
if (value != HIGH_CONTRAST_THEME)
iconTheme = value;
});
return highContrast;
},
_buildFontItem: function(client) {
let first_gconf_value = client.get_without_default(KEY_FONT_DPI);
let default_value = getDPIFromX();
let first_value = first_gconf_value ? first_gconf_value.get_float() : default_value;
function on_get() {
let u_dpi = client.get_float(KEY_FONT_DPI);
let x_dpi = getDPIFromX();
return (u_dpi - (DPI_FACTOR_LARGE * x_dpi) > -1);
}
let initial_setting = on_get();
let widget = this._buildItemExtended(_("Large Text"),
initial_setting,
client.key_is_writable(KEY_FONT_DPI),
function (enabled) {
if (enabled)
client.set_float(KEY_FONT_DPI, DPI_FACTOR_LARGE * getDPIFromX());
else
client.set_float(KEY_FONT_DPI, (first_value && !initial_setting) ? first_value : default_value);
});
this.connect('gconf-changed', function() {
let active = on_get();
if (!active)
// setting was modified manually, update it
first_value = client.get_float(KEY_FONT_DPI);
widget.setToggleState(on_get());
});
return widget;
},
_buildMagItem: function() {
let mag = Main.magnifier;
let widget = this._buildItemExtended(_("Zoom"),
mag.isActive(),
true,
Lang.bind(mag, mag.setActive));
mag.connect('active-changed', function(magnifier, active) {
widget.setToggleState(active);
});
return widget;
},
_keyChanged: function() {
this.emit('gconf-changed');
}
};
Signals.addSignalMethods(ATIndicator.prototype);

View File

@ -0,0 +1,56 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const MessageTray = imports.ui.messageTray;
const NotificationDaemon = imports.ui.notificationDaemon;
const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'bluetooth-applet': 'bluetooth',
'gnome-volume-control-applet': 'volume',
'nm-applet': 'network',
'gnome-power-manager': 'battery',
'keyboard': 'keyboard',
'gnome-settings-daemon': 'display'
};
function StatusIconDispatcher() {
this._init();
}
StatusIconDispatcher.prototype = {
_init: function() {
this._traymanager = new Shell.TrayManager();
this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._traymanager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
this._traymanager.manage_stage(global.stage);
// Yet-another-Ubuntu-workaround - we have to kill their
// app-indicators, so that applications fall back to normal
// status icons
// http://bugzilla.gnome.org/show_bug.cgi=id=621382
let p = new Shell.Process({ args: ['pkill', '-f', '^([^ ]*/)?indicator-application-service$']});
p.run();
},
_onTrayIconAdded: function(o, icon) {
let wmClass = icon.wm_class.toLowerCase();
let role = STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass];
if (role)
this.emit('status-icon-added', icon, role);
else
this.emit('message-icon-added', icon);
},
_onTrayIconRemoved: function(o, icon) {
let wmClass = icon.wm_class.toLowerCase();
let role = STANDARD_TRAY_ICON_IMPLEMENTATIONS[wmClass];
if (role)
this.emit('status-icon-removed', icon);
else
this.emit('message-icon-removed', icon);
}
};
Signals.addSignalMethods(StatusIconDispatcher.prototype);

177
js/ui/statusMenu.js Normal file
View File

@ -0,0 +1,177 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Gdm = imports.gi.Gdm;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const GnomeSession = imports.misc.gnomeSession;
const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
// Adapted from gdm/gui/user-switch-applet/applet.c
//
// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
// Copyright (C) 2008,2009 Red Hat, Inc.
function StatusMenuButton() {
this._init();
}
StatusMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function() {
PanelMenu.Button.prototype._init.call(this, St.Align.START);
let box = new St.BoxLayout({ name: 'panelStatusMenu' });
this.actor.set_child(box);
this._gdm = Gdm.UserManager.ref_default();
this._user = this._gdm.get_user(GLib.get_user_name());
this._presence = new GnomeSession.Presence();
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._iconBox = new St.Bin();
box.add(this._iconBox, { y_align: St.Align.MIDDLE, y_fill: false });
let textureCache = St.TextureCache.get_default();
this._availableIcon = textureCache.load_icon_name('user-available', St.IconType.SYMBOLIC, 16);
this._busyIcon = textureCache.load_icon_name('user-busy', St.IconType.SYMBOLIC, 16);
this._invisibleIcon = textureCache.load_icon_name('user-invisible', St.IconType.SYMBOLIC, 16);
this._idleIcon = textureCache.load_icon_name('user-idle', St.IconType.SYMBOLIC, 16);
this._presence.connect('StatusChanged', Lang.bind(this, this._updatePresenceIcon));
this._presence.getStatus(Lang.bind(this, this._updatePresenceIcon));
this._name = new St.Label({ text: this._user.get_real_name() });
box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false });
this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName));
this._createSubMenu();
this._gdm.connect('users-loaded', Lang.bind(this, this._updateSwitchUser));
this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser));
this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser));
},
_onDestroy: function() {
this._user.disconnect(this._userNameChangedId);
},
_updateUserName: function() {
this._name.set_text(this._user.get_real_name());
},
_updateSwitchUser: function() {
let users = this._gdm.list_users();
if (users.length > 1)
this._loginScreenItem.actor.show();
else
this._loginScreenItem.actor.hide();
},
_updatePresenceIcon: function(presence, status) {
if (status == GnomeSession.PresenceStatus.AVAILABLE)
this._iconBox.child = this._availableIcon;
else if (status == GnomeSession.PresenceStatus.BUSY)
this._iconBox.child = this._busyIcon;
else if (status == GnomeSession.PresenceStatus.INVISIBLE)
this._iconBox.child = this._invisibleIcon;
else
this._iconBox.child = this._idleIcon;
},
_createSubMenu: function() {
let item;
item = new PopupMenu.PopupImageMenuItem(_("Available"), 'user-available', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.AVAILABLE));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Busy"), 'user-busy', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.BUSY));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Invisible"), 'user-invisible', true);
item.connect('activate', Lang.bind(this, this._setPresenceStatus, GnomeSession.PresenceStatus.INVISIBLE));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Account Information..."), 'user-info');
item.connect('activate', Lang.bind(this, this._onAccountInformationActivate));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("System Settings..."), 'preferences-desktop');
item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Lock Screen"), 'system-lock-screen');
item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Switch User"), 'system-users');
item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
this.menu.addMenuItem(item);
this._loginScreenItem = item;
item = new PopupMenu.PopupImageMenuItem(_("Log Out..."), 'system-log-out');
item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
this.menu.addMenuItem(item);
item = new PopupMenu.PopupImageMenuItem(_("Shut Down..."), 'system-shutdown');
item.connect('activate', Lang.bind(this, this._onShutDownActivate));
this.menu.addMenuItem(item);
},
_setPresenceStatus: function(item, event, status) {
this._presence.setStatus(status);
},
_onAccountInformationActivate: function() {
Main.overview.hide();
this._spawn(['gnome-about-me']);
},
_onPreferencesActivate: function() {
Main.overview.hide();
this._spawn(['gnome-control-center']);
},
_onLockScreenActivate: function() {
Main.overview.hide();
this._spawn(['gnome-screensaver-command', '--lock']);
},
_onLoginScreenActivate: function() {
Main.overview.hide();
this._gdm.goto_login_session();
this._onLockScreenActivate();
},
_onQuitSessionActivate: function() {
Main.overview.hide();
this._spawn(['gnome-session-save', '--logout-dialog']);
},
_onShutDownActivate: function() {
Main.overview.hide();
this._spawn(['gnome-session-save', '--shutdown-dialog']);
},
_spawn: function(args) {
// FIXME: once Shell.Process gets support for signalling
// errors we should pop up an error dialog or something here
// on failure
let p = new Shell.Process({'args' : args});
p.run();
}
};

641
js/ui/telepathyClient.js Normal file
View File

@ -0,0 +1,641 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const Telepathy = imports.misc.telepathy;
let contactManager;
let channelDispatcher;
// See Notification.appendMessage
const SCROLLBACK_RECENT_TIME = 15 * 60; // 15 minutes
const SCROLLBACK_RECENT_LENGTH = 20;
const SCROLLBACK_IDLE_LENGTH = 5;
// A 'Qualified_Property_Value_Map' that represents a single-user
// text-based chat.
let singleUserTextChannel = {};
singleUserTextChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_TEXT_NAME;
singleUserTextChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.CONTACT;
// Some protocols only support 'multi-user' chats, and single-user
// chats are just treated as multi-user chats with only one other
// participant. Telepathy uses HandleType.NONE for all chats in these
// protocols; there's no good way for us to tell if the channel is
// single- or multi-user.
let oneOrMoreUserTextChannel = {};
oneOrMoreUserTextChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_TEXT_NAME;
oneOrMoreUserTextChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.NONE;
// The (non-chat) channel indicating the users whose presence
// information we subscribe to
let subscribedContactsChannel = {};
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.ChannelType'] = Telepathy.CHANNEL_CONTACT_LIST_NAME;
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.TargetHandleType'] = Telepathy.HandleType.LIST;
subscribedContactsChannel[Telepathy.CHANNEL_NAME + '.TargetID'] = 'subscribe';
// This is GNOME Shell's implementation of the Telepathy 'Client'
// interface. Specifically, the shell is a Telepathy 'Observer', which
// lets us see messages even if they belong to another app (eg,
// Empathy).
function Client() {
this._init();
};
Client.prototype = {
_init : function() {
let name = Telepathy.CLIENT_NAME + '.GnomeShell';
DBus.session.exportObject(Telepathy.nameToPath(name), this);
DBus.session.acquire_name(name, DBus.SINGLE_INSTANCE,
function (name) { /* FIXME: acquired */ },
function (name) { /* FIXME: lost */ });
this._accounts = {};
this._sources = {};
contactManager = new ContactManager();
contactManager.connect('presence-changed', Lang.bind(this, this._presenceChanged));
channelDispatcher = new Telepathy.ChannelDispatcher(DBus.session,
Telepathy.CHANNEL_DISPATCHER_NAME,
Telepathy.nameToPath(Telepathy.CHANNEL_DISPATCHER_NAME));
// Acquire existing connections. (Needed to make things work
// through a restart.)
let accountManager = new Telepathy.AccountManager(DBus.session,
Telepathy.ACCOUNT_MANAGER_NAME,
Telepathy.nameToPath(Telepathy.ACCOUNT_MANAGER_NAME));
accountManager.GetRemote('ValidAccounts', Lang.bind(this,
function (accounts, err) {
if (!accounts)
return;
for (let i = 0; i < accounts.length; i++)
this._gotAccount(accounts[i]);
}));
accountManager.connect('AccountValidityChanged', Lang.bind(this, this._accountValidityChanged));
},
_accountValidityChanged: function(accountManager, accountPath, valid) {
if (!valid) {
delete this._accounts[accountPath];
// We don't need to clean up connections, sources, etc; they'll
// get Closed and cleaned up independently.
} else
this._gotAccount(accountPath);
},
_gotAccount: function(accountPath) {
let account = new Telepathy.Account(DBus.session,
Telepathy.ACCOUNT_MANAGER_NAME,
accountPath);
this._accounts[accountPath] = account;
account.GetRemote('Connection', Lang.bind(this,
function (connPath, err) {
if (!connPath || connPath == '/')
return;
let connReq = new Telepathy.ConnectionRequests(DBus.session,
Telepathy.pathToName(connPath),
connPath);
connReq.GetRemote('Channels', Lang.bind(this,
function(channels, err) {
if (!channels)
return;
this._addChannels(accountPath, connPath, channels);
}));
contactManager.addConnection(connPath);
}));
},
get Interfaces() {
return [ Telepathy.CLIENT_OBSERVER_NAME ];
},
get ObserverChannelFilter() {
return [ singleUserTextChannel, oneOrMoreUserTextChannel ];
},
ObserveChannels: function(accountPath, connPath, channels,
dispatchOperation, requestsSatisfied,
observerInfo) {
this._addChannels(accountPath, connPath, channels);
},
_addChannels: function(accountPath, connPath, channelDetailsList) {
for (let i = 0; i < channelDetailsList.length; i++) {
let [channelPath, props] = channelDetailsList[i];
// If this is being called from the startup code then it
// won't have passed through our filters, so we need to
// check the channel/targetHandle type ourselves.
let channelType = props[Telepathy.CHANNEL_NAME + '.ChannelType'];
if (channelType != Telepathy.CHANNEL_TEXT_NAME)
continue;
let targetHandleType = props[Telepathy.CHANNEL_NAME + '.TargetHandleType'];
if (targetHandleType != Telepathy.HandleType.CONTACT &&
targetHandleType != Telepathy.HandleType.NONE)
continue;
let targetHandle = props[Telepathy.CHANNEL_NAME + '.TargetHandle'];
let targetId = props[Telepathy.CHANNEL_NAME + '.TargetID'];
if (this._sources[connPath + ':' + targetHandle])
continue;
let source = new Source(accountPath, connPath, channelPath,
targetHandle, targetHandleType, targetId);
this._sources[connPath + ':' + targetHandle] = source;
source.connect('destroy', Lang.bind(this,
function() {
delete this._sources[connPath + ':' + targetHandle];
}));
}
},
_presenceChanged: function(contactManager, connPath, handle,
type, message) {
let source = this._sources[connPath + ':' + handle];
if (!source)
return;
source.setPresence(type, message);
}
};
DBus.conformExport(Client.prototype, Telepathy.ClientIface);
DBus.conformExport(Client.prototype, Telepathy.ClientObserverIface);
function ContactManager() {
this._init();
};
ContactManager.prototype = {
_init: function() {
this._connections = {};
// Note that if we changed this to '/telepathy/avatars' then
// we would share cache files with empathy. But since this is
// not documented/guaranteed, it seems a little sketchy
this._cacheDir = GLib.get_user_cache_dir() + '/gnome-shell/avatars';
},
addConnection: function(connPath) {
let info = this._connections[connPath];
if (info)
return info;
info = {};
// Figure out the cache subdirectory for this connection by
// parsing the connection manager name (eg, 'gabble') and
// protocol name (eg, 'jabber') from the Connection's path.
// Telepathy requires the D-Bus path for a connection to have
// a specific form, and explicitly says that clients are
// allowed to parse it.
let match = connPath.match(/\/org\/freedesktop\/Telepathy\/Connection\/([^\/]*\/[^\/]*)\/.*/);
if (!match)
throw new Error('Could not parse connection path ' + connPath);
info.cacheDir = this._cacheDir + '/' + match[1];
GLib.mkdir_with_parents(info.cacheDir, 0x1c0); // 0x1c0 = octal 0700
// info.names[handle] is @handle's real name
// info.tokens[handle] is the token for @handle's avatar
info.names = {};
info.tokens = {};
// info.icons[handle] is an array of the icon actors currently
// being displayed for @handle. These will be updated
// automatically if @handle's avatar changes.
info.icons = {};
let connName = Telepathy.pathToName(connPath);
info.connectionAvatars = new Telepathy.ConnectionAvatars(DBus.session, connName, connPath);
info.updatedId = info.connectionAvatars.connect(
'AvatarUpdated', Lang.bind(this, this._avatarUpdated));
info.retrievedId = info.connectionAvatars.connect(
'AvatarRetrieved', Lang.bind(this, this._avatarRetrieved));
info.connectionContacts = new Telepathy.ConnectionContacts(DBus.session, connName, connPath);
info.connectionPresence = new Telepathy.ConnectionSimplePresence(DBus.session, connName, connPath);
info.presenceChangedId = info.connectionPresence.connect(
'PresencesChanged', Lang.bind(this, this._presencesChanged));
let conn = new Telepathy.Connection(DBus.session, connName, connPath);
info.statusChangedId = conn.connect('StatusChanged', Lang.bind(this,
function (status, reason) {
if (status == Telepathy.ConnectionStatus.DISCONNECTED)
this._removeConnection(conn);
}));
let connReq = new Telepathy.ConnectionRequests(DBus.session,
connName, connPath);
connReq.EnsureChannelRemote(subscribedContactsChannel, Lang.bind(this,
function (result, err) {
if (!result)
return;
let [mine, channelPath, props] = result;
this._gotContactsChannel(connPath, channelPath, props);
}));
this._connections[connPath] = info;
return info;
},
_gotContactsChannel: function(connPath, channelPath, props) {
let info = this._connections[connPath];
if (!info)
return;
info.contactsGroup = new Telepathy.ChannelGroup(DBus.session,
Telepathy.pathToName(connPath),
channelPath);
info.contactsListChangedId =
info.contactsGroup.connect('MembersChanged', Lang.bind(this, this._contactsListChanged, info));
info.contactsGroup.GetRemote('Members', Lang.bind(this,
function(contacts, err) {
if (!contacts)
return;
info.connectionContacts.GetContactAttributesRemote(
contacts, [Telepathy.CONNECTION_ALIASING_NAME], false,
Lang.bind(this, this._gotContactAttributes, info));
}));
},
_contactsListChanged: function(group, message, added, removed,
local_pending, remote_pending,
actor, reason, info) {
for (let i = 0; i < removed.length; i++)
delete info.names[removed[i]];
info.connectionContacts.GetContactAttributesRemote(
added, [Telepathy.CONNECTION_ALIASING_NAME], false,
Lang.bind(this, this._gotContactAttributes, info));
},
_gotContactAttributes: function(attrs, err, info) {
if (!attrs)
return;
for (let handle in attrs)
info.names[handle] = attrs[handle][Telepathy.CONNECTION_ALIASING_NAME + '/alias'];
},
_presencesChanged: function(conn, presences, err) {
if (!presences)
return;
let info = this._connections[conn.getPath()];
if (!info)
return;
for (let handle in presences) {
let [type, status, message] = presences[handle];
this.emit('presence-changed', conn.getPath(), handle, type, message);
}
},
_removeConnection: function(conn) {
let info = this._connections[conn.getPath()];
if (!info)
return;
conn.disconnect(info.statusChangedId);
info.connectionAvatars.disconnect(info.updatedId);
info.connectionAvatars.disconnect(info.retrievedId);
info.connectionPresence.disconnect(info.presenceChangedId);
info.contactsGroup.disconnect(info.contactsListChangedId);
delete this._connections[conn.getPath()];
},
_getFileForToken: function(info, token) {
return info.cacheDir + '/' + Telepathy.escapeAsIdentifier(token);
},
_setIcon: function(iconBox, info, handle) {
let textureCache = St.TextureCache.get_default();
let token = info.tokens[handle];
let file;
if (token) {
file = this._getFileForToken(info, token);
if (!GLib.file_test(file, GLib.FileTest.EXISTS))
file = null;
}
if (file) {
let uri = GLib.filename_to_uri(file, null);
iconBox.child = textureCache.load_uri_async(uri, iconBox._size, iconBox._size);
} else {
iconBox.child = textureCache.load_icon_name('stock_person', St.IconType.FULLCOLOR, iconBox._size);
}
},
_updateIcons: function(info, handle) {
if (!info.icons[handle])
return;
for (let i = 0; i < info.icons[handle].length; i++) {
let iconBox = info.icons[handle][i];
this._setIcon(iconBox, info, handle);
}
},
_avatarUpdated: function(conn, handle, token) {
let info = this._connections[conn.getPath()];
if (!info)
return;
if (info.tokens[handle] == token)
return;
info.tokens[handle] = token;
if (token != '') {
let file = this._getFileForToken(info, token);
if (!GLib.file_test(file, GLib.FileTest.EXISTS)) {
info.connectionAvatars.RequestAvatarsRemote([handle]);
return;
}
}
this._updateIcons(info, handle);
},
_avatarRetrieved: function(conn, handle, token, avatarData, mimeType) {
let info = this._connections[conn.getPath()];
if (!info)
return;
let file = this._getFileForToken(info, token);
let success = false;
try {
success = GLib.file_set_contents(file, avatarData, avatarData.length);
} catch (e) {
logError(e, 'Error caching avatar data');
}
if (success)
this._updateIcons(info, handle);
},
createAvatar: function(conn, handle, size) {
let iconBox = new St.Bin({ style_class: 'avatar-box' });
iconBox._size = size;
let info = this._connections[conn.getPath()];
if (!info)
info = this.addConnection(conn.getPath());
if (!info.icons[handle])
info.icons[handle] = [];
info.icons[handle].push(iconBox);
iconBox.connect('destroy', Lang.bind(this,
function() {
let i = info.icons[handle].indexOf(iconBox);
if (i != -1)
info.icons[handle].splice(i, 1);
}));
// If we already have the icon cached and know its token, this
// will fill it in. Otherwise it will fill in the default
// icon.
this._setIcon(iconBox, info, handle);
// Asynchronously load the real avatar if we don't have it yet.
if (info.tokens[handle] == null) {
info.connectionAvatars.GetKnownAvatarTokensRemote([handle], Lang.bind(this,
function (tokens, err) {
let token = tokens && tokens[handle] ? tokens[handle] : '';
this._avatarUpdated(conn, handle, token);
}));
}
return iconBox;
}
};
Signals.addSignalMethods(ContactManager.prototype);
function Source(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
this._init(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function(accountPath, connPath, channelPath, targetHandle, targetHandleType, targetId) {
MessageTray.Source.prototype._init.call(this, targetId);
this._accountPath = accountPath;
let connName = Telepathy.pathToName(connPath);
this._conn = new Telepathy.Connection(DBus.session, connName, connPath);
this._channel = new Telepathy.Channel(DBus.session, connName, channelPath);
this._closedId = this._channel.connect('Closed', Lang.bind(this, this._channelClosed));
this._targetHandle = targetHandle;
this._targetHandleType = targetHandleType;
this._targetId = targetId;
if (targetHandleType == Telepathy.HandleType.CONTACT) {
let aliasing = new Telepathy.ConnectionAliasing(DBus.session, connName, connPath);
aliasing.RequestAliasesRemote([this._targetHandle], Lang.bind(this,
function (aliases, err) {
if (aliases && aliases.length)
this.title = aliases[0];
}));
}
// Since we only create sources when receiving a message, this
// is a plausible default
this._presence = Telepathy.ConnectionPresenceType.AVAILABLE;
this._channelText = new Telepathy.ChannelText(DBus.session, connName, channelPath);
this._receivedId = this._channelText.connect('Received', Lang.bind(this, this._messageReceived));
this._channelText.ListPendingMessagesRemote(false, Lang.bind(this, this._gotPendingMessages));
this._setSummaryIcon(this.createNotificationIcon());
},
createNotificationIcon: function() {
return contactManager.createAvatar(this._conn, this._targetHandle,
this.ICON_SIZE);
},
clicked: function() {
channelDispatcher.EnsureChannelRemote(this._accountPath,
{ 'org.freedesktop.Telepathy.Channel.ChannelType': Telepathy.CHANNEL_TEXT_NAME,
'org.freedesktop.Telepathy.Channel.TargetHandle': this._targetHandle,
'org.freedesktop.Telepathy.Channel.TargetHandleType': this._targetHandleType },
global.get_current_time(),
'',
Lang.bind(this, this._gotChannelRequest));
MessageTray.Source.prototype.clicked.call(this);
},
_gotChannelRequest: function (chanReqPath, ex) {
if (ex) {
log ('EnsureChannelRemote failed? ' + ex);
return;
}
let chanReq = new Telepathy.ChannelRequest(DBus.session, Telepathy.CHANNEL_DISPATCHER_NAME, chanReqPath);
chanReq.ProceedRemote();
},
_gotPendingMessages: function(msgs, err) {
if (!msgs)
return;
for (let i = 0; i < msgs.length; i++)
this._messageReceived.apply(this, [this._channel].concat(msgs[i]));
},
_channelClosed: function() {
this._channel.disconnect(this._closedId);
this._channelText.disconnect(this._receivedId);
this.destroy();
},
_ensureNotification: function() {
if (!Main.messageTray.contains(this))
Main.messageTray.add(this);
if (!this._notification)
this._notification = new Notification(this);
},
_messageReceived: function(channel, id, timestamp, sender,
type, flags, text) {
this._ensureNotification();
this._notification.appendMessage(text);
this.notify(this._notification);
},
respond: function(text) {
this._channelText.SendRemote(Telepathy.ChannelTextMessageType.NORMAL, text);
},
setPresence: function(presence, message) {
let msg, notify;
if (presence == Telepathy.ConnectionPresenceType.AVAILABLE) {
msg = _("%s is online.").format(this.title);
notify = (this._presence == Telepathy.ConnectionPresenceType.OFFLINE);
} else if (presence == Telepathy.ConnectionPresenceType.OFFLINE ||
presence == Telepathy.ConnectionPresenceType.EXTENDED_AWAY) {
presence = Telepathy.ConnectionPresenceType.OFFLINE;
msg = _("%s is offline.").format(this.title);
notify = (this._presence != Telepathy.ConnectionPresenceType.OFFLINE);
} else if (presence == Telepathy.ConnectionPresenceType.AWAY) {
msg = _("%s is away.").format(this.title);
notify = false;
} else if (presence == Telepathy.ConnectionPresenceType.BUSY) {
msg = _("%s is busy.").format(this.title);
notify = false;
} else
return;
this._presence = presence;
if (message)
msg += ' <i>(' + GLib.markup_escape_text(message, -1) + ')</i>';
this._ensureNotification();
this._notification.appendMessage(msg, true);
if (notify)
this.notify(this._notification);
}
};
function Notification(source) {
this._init(source);
}
Notification.prototype = {
__proto__: MessageTray.Notification.prototype,
_init: function(source) {
MessageTray.Notification.prototype._init.call(this, source, source.title, null, { customContent: true });
this._responseEntry = new St.Entry({ style_class: 'chat-response' });
this._responseEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivated));
this.setActionArea(this._responseEntry);
this._history = [];
},
appendMessage: function(text, asTitle) {
if (asTitle)
this.update(text, null, { customContent: true });
else
this.update(this.source.title, text, { customContent: true });
this._append(text, 'chat-received');
},
_append: function(text, style) {
let body = this.addBody(text);
body.add_style_class_name(style);
this.scrollTo(St.Side.BOTTOM);
let now = new Date().getTime() / 1000;
this._history.unshift({ actor: body, time: now });
if (this._history.length > 1) {
// Keep the scrollback from growing too long. If the most
// recent message (before the one we just added) is within
// SCROLLBACK_RECENT_TIME, we will keep
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
// we'll keep SCROLLBACK_IDLE_LENGTH messages.
let lastMessageTime = this._history[1].time;
let maxLength = (lastMessageTime < now - SCROLLBACK_RECENT_TIME) ?
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
if (this._history.length > maxLength) {
let expired = this._history.splice(maxLength);
for (let i = 0; i < expired.length; i++)
expired[i].actor.destroy();
}
}
},
grabFocus: function(lockTray) {
// Need to call the base class function first so that
// it saves where the key focus was before.
MessageTray.Notification.prototype.grabFocus.call(this, lockTray);
global.stage.set_key_focus(this._responseEntry.clutter_text);
},
_onEntryActivated: function() {
let text = this._responseEntry.get_text();
if (text == '')
return;
this._responseEntry.set_text('');
this._append(text, 'chat-sent');
this.source.respond(text);
}
};

View File

@ -1,9 +1,10 @@
/* -*- 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 Shell = imports.gi.Shell;
const St = imports.gi.St;
const Signals = imports.signals;
const Tweener = imports.tweener.tweener;
@ -42,17 +43,8 @@ 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());
}
@ -178,7 +170,7 @@ function resumeTweens() {
function registerSpecialProperty(name, getFunction, setFunction,
parameters, preProcessFunction) {
Tweener.registerSpecialProperty(name, getFunction, setFunction,
parameters, preProcessFunction);
parameters, preProcessFunction);
}
function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
@ -190,7 +182,7 @@ function registerSpecialPropertySplitter(name, splitFunction, parameters) {
}
// The "FrameTicker" object is an object used to feed new frames to
// The 'FrameTicker' object is an object used to feed new frames to
// Tweener so it can update values and redraw. The default frame
// ticker for Tweener just uses a simple timeout at a fixed frame rate
// and has no idea of "catching up" by dropping frames.
@ -215,12 +207,19 @@ ClutterFrameTicker.prototype = {
// when we need to stop, so use 1000 seconds as "infinity"
this._timeline = new Clutter.Timeline({ duration: 1000*1000 });
this._startTime = -1;
this._currentTime = -1;
this._timeline.connect('new-frame', Lang.bind(this,
function(timeline, frame) {
this._onNewFrame(frame);
}));
let perf_log = Shell.PerfLog.get_default();
perf_log.define_event("tweener.framePrepareStart",
"Start of a new animation frame",
"");
perf_log.define_event("tweener.framePrepareDone",
"Finished preparing frame",
"");
},
_onNewFrame : function(frame) {
@ -233,22 +232,27 @@ ClutterFrameTicker.prototype = {
this._startTime = this._timeline.get_elapsed_time();
// currentTime is in milliseconds
this._currentTime = (this._timeline.get_elapsed_time() - this._startTime) / slowDownFactor;
let perf_log = Shell.PerfLog.get_default();
perf_log.event("tweener.framePrepareStart");
this.emit('prepare-frame');
perf_log.event("tweener.framePrepareDone");
},
getTime : function() {
return this._currentTime;
return this._timeline.get_elapsed_time();
},
start : function() {
if (St.get_slow_down_factor() > 0)
Tweener.setTimeScale(1 / St.get_slow_down_factor());
this._timeline.start();
global.begin_work();
},
stop : function() {
this._timeline.stop();
this._startTime = -1;
this._currentTime = -1;
global.end_work();
}
};

View File

@ -1,367 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;
const 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;
const COLLAPSED_WIDTH = 24;
const EXPANDED_WIDTH = 200;
const STATE_EXPANDED = 0;
const STATE_COLLAPSING = 1;
const STATE_COLLAPSED = 2;
const STATE_EXPANDING = 3;
const STATE_POPPING_OUT = 4;
const STATE_POPPED_OUT = 5;
const STATE_POPPING_IN = 6;
function Widget() {
}
Widget.prototype = {
// _init():
//
// Your widget constructor. Your constructor function should look
// like:
//
// function MyWidgetType() {
// this._init.apply(this, arguments);
// }
//
// and your _init method should start by doing:
//
// Widget.Widget.prototype._init.apply(this, arguments);
//
// The _init method must define a field named "actor" containing
// the Clutter.Actor to show in expanded mode. This actor will be
// clipped to Widget.EXPANDED_WIDTH. Most widgets will also define
// a field named "title" containing the title string to show above
// the widget in the sidebar.
//
// If you want to have a separate collapsed view, you can define a
// field "collapsedActor" containing the Clutter.Actor to show in
// that mode. (It may be the same actor.) This actor will be
// clipped to Widget.COLLAPSED_WIDTH, and will normally end up
// having the same height as the main actor.
//
// If you do not set a collapsedActor, then you must set a title,
// since that is what will be displayed in collapsed mode, and
// in this case (and only in this case), the widget will support
// pop-out, meaning that if the user hovers over its title while
// the sidebar is collapsed, the widget's expanded view will pop
// out of the sidebar until either the cursor moves out of it,
// or else the widget calls this.activated() on itself.
_init: function (initialState) {
this.state = initialState;
},
// destroy():
//
// Optional. Will be called when the widget is removed from the
// sidebar. (Note that you don't need to destroy the actors,
// since they will be destroyed for you.)
// collapse():
//
// Optional. Called during the sidebar collapse process, at the
// point when the expanded sidebar has slid offscreen, but the
// collapsed sidebar has not yet slid onscreen.
// expand():
//
// Optional. Called during the sidebar expand process, at the
// point when the collapsed sidebar has slid offscreen, but the
// expanded sidebar has not yet slid onscreen.
// activated():
//
// Emits the "activated" signal for you, which will cause pop-out
// to end.
activated: function() {
this.emit('activated');
}
// state:
//
// A field set on your widget by the sidebar. Will contain one of
// the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED).
};
Signals.addSignalMethods(Widget.prototype);
function ClockWidget() {
this._init.apply(this, arguments);
}
ClockWidget.prototype = {
__proto__ : Widget.prototype,
_init: function() {
Widget.prototype._init.apply(this, arguments);
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
text: "",
// Give an explicit height to ensure
// it's the same in both modes
height: COLLAPSED_WIDTH });
this.collapsedActor = new Clutter.CairoTexture({ width: COLLAPSED_WIDTH,
height: COLLAPSED_WIDTH,
surface_width: COLLAPSED_WIDTH,
surface_height: COLLAPSED_WIDTH });
this._update();
},
destroy: function() {
if (this.timer)
Mainloop.source_remove(this.timer);
},
expand: function() {
this._update();
},
collapse: function() {
this._update();
},
_update: function() {
let time = new Date();
let msec_remaining = 60000 - (1000 * time.getSeconds() +
time.getMilliseconds());
if (msec_remaining < 500) {
time.setMinutes(time.getMinutes() + 1);
msec_remaining += 60000;
}
if (this.state == STATE_COLLAPSED || this.state == STATE_COLLAPSING)
this._updateCairo(time);
else
this._updateText(time);
if (this.timer)
Mainloop.source_remove(this.timer);
this.timer = Mainloop.timeout_add(msec_remaining, Lang.bind(this, this._update));
return false;
},
_updateText: function(time) {
// Translators: This is a time format.
this.actor.set_text(time.toLocaleFormat(_("%H:%M")));
},
_updateCairo: function(time) {
Shell.draw_clock(this.collapsedActor,
time.getHours() % 12,
time.getMinutes());
}
};
const ITEM_ICON_SIZE = 48;
const ITEM_PADDING = 1;
const ITEM_SPACING = 4;
const ITEM_BG_COLOR = new Clutter.Color();
ITEM_BG_COLOR.from_pixel(0x00000000);
const ITEM_NAME_COLOR = new Clutter.Color();
ITEM_NAME_COLOR.from_pixel(0x000000ff);
function LauncherWidget() {
this._init.apply(this, arguments);
}
LauncherWidget.prototype = {
__proto__ : Widget.prototype,
addItem : function(info) {
let item = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL,
width: EXPANDED_WIDTH,
height: ITEM_ICON_SIZE,
padding: ITEM_PADDING,
spacing: ITEM_SPACING,
reactive: true });
item._info = info;
item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE);
item.append(new Clutter.Text({ color: ITEM_NAME_COLOR,
font_name: "Sans 14px",
ellipsize: Pango.EllipsizeMode.END,
text: info.name }),
Big.BoxPackFlags.NONE);
this.actor.append(item, Big.BoxPackFlags.NONE);
item.connect('button-press-event', Lang.bind(this, this._buttonPress));
item.connect('button-release-event', Lang.bind(this, this._buttonRelease));
item.connect('leave-event', Lang.bind(this, this._leave));
item.connect('enter-event', Lang.bind(this, this._enter));
if (!this.collapsedActor)
return;
item = new Big.Box({ width: COLLAPSED_WIDTH,
height: COLLAPSED_WIDTH,
padding: ITEM_PADDING,
reactive: true });
item._info = info;
item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING),
Big.BoxPackFlags.NONE);
this.collapsedActor.append(item, Big.BoxPackFlags.NONE);
item.connect('button-press-event', Lang.bind(this, this._buttonPress));
item.connect('button-release-event', Lang.bind(this, this._buttonRelease));
item.connect('leave-event', Lang.bind(this, this._leave));
item.connect('enter-event', Lang.bind(this, this._enter));
},
clear : function() {
let children, i;
children = this.actor.get_children();
for (i = 0; i < children.length; i++)
children[i].destroy();
if (this.collapsedActor) {
children = this.collapsedActor.get_children();
for (i = 0; i < children.length; i++)
children[i].destroy();
}
},
_buttonPress : function(item) {
Clutter.grab_pointer(item);
item._buttonDown = true;
item._inItem = true;
this._updateItemState(item);
return true;
},
_leave : function(item, evt) {
if (evt.get_source() == item && item._buttonDown) {
item._inItem = false;
this._updateItemState(item);
}
return false;
},
_enter : function(item, evt) {
if (evt.get_source() == item && item._buttonDown) {
item._inItem = true;
this._updateItemState(item);
}
return false;
},
_buttonRelease : function(item) {
Clutter.ungrab_pointer(item);
item._buttonDown = false;
this._updateItemState(item);
if (item._inItem) {
item._info.launch();
this.activated();
}
return true;
},
_updateItemState : function(item) {
if (item._buttonDown && item._inItem) {
item.padding_top = item.padding_left = 2 * ITEM_PADDING;
item.padding_bottom = item.padding_right = 0;
} else
item.padding = ITEM_PADDING;
}
};
function AppsWidgetInfo(appInfo) {
this._init(appInfo);
}
AppsWidgetInfo.prototype = {
_init : function(appInfo) {
this._info = appInfo;
this.name = appInfo.get_name();
},
createIcon : function(size) {
return this._info.create_icon_texture(size);
},
launch : function() {
this._info.launch();
}
}
function AppsWidget() {
this._init.apply(this, arguments);
}
AppsWidget.prototype = {
__proto__ : LauncherWidget.prototype,
_init : function() {
Widget.prototype._init.apply(this, arguments);
this.title = _("Applications");
this.actor = new Big.Box({ spacing: 2 });
this.collapsedActor = new Big.Box({ spacing: 2});
let appSystem = Shell.AppSystem.get_default();
let apps = appSystem.get_favorites();
for (let i = 0; i < apps.length; i++) {
let app = appSystem.lookup_cached_app(apps[i]);
if (!app)
continue;
this.addItem(new AppsWidgetInfo(app));
}
}
};
function RecentDocsWidget() {
this._init.apply(this, arguments);
}
RecentDocsWidget.prototype = {
__proto__ : LauncherWidget.prototype,
_init : function() {
Widget.prototype._init.apply(this, arguments);
this.title = _("Recent Documents");
this.actor = new Big.Box({ spacing: 2 });
this._recentManager = Gtk.RecentManager.get_default();
this._recentManager.connect('changed', Lang.bind(this, this._recentChanged));
this._recentChanged();
},
_recentChanged: function() {
let i;
this.clear();
let items = [];
let docs = this._recentManager.get_items();
for (i = 0; i < docs.length; i++) {
let docInfo = new DocInfo.DocInfo (docs[i]);
if (docInfo.exists())
items.push(docInfo);
}
items.sort(function (a,b) { return b.timestamp - a.timestamp; });
for (i = 0; i < Math.min(items.length, 5); i++)
this.addItem(items[i]);
}
};

View File

@ -1,381 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const Widget = imports.ui.widget;
const WIDGETBOX_BG_COLOR = new Clutter.Color();
WIDGETBOX_BG_COLOR.from_pixel(0xf0f0f0ff);
const BLACK = new Clutter.Color();
BLACK.from_pixel(0x000000ff);
const WIDGETBOX_PADDING = 2;
const ANIMATION_TIME = 0.5;
const POP_IN_LAG = 250; /* milliseconds */
function WidgetBox(widget, expanded) {
this._init(widget, expanded);
}
WidgetBox.prototype = {
_init: function(widget, expanded) {
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
if (widget instanceof Widget.Widget) {
this._widget = widget;
this._widget.state = this.state;
} else {
let ctor = this._ctorFromName(widget);
this._widget = new ctor(this.state);
}
if (!this._widget.actor)
throw new Error("widget has no actor");
else if (!this._widget.title && !this._widget.collapsedActor)
throw new Error("widget has neither title nor collapsedActor");
this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED;
// The structure of a WidgetBox:
//
// The top level is a Clutter.Group, which exists to make
// pop-out work correctly; when another widget pops out, its
// width will increase, which will in turn cause the sidebar's
// width to increase, which will cause the sidebar to increase
// the width of each of its children (the WidgetBoxes). But we
// don't want the non-popped-out widgets to expand, so we make
// the top-level actor be a Clutter.Group, which will accept
// the new width from the Sidebar, but not impose it on its
// own child.
//
// Inside the toplevel group is a horizontal Big.Box
// containing 2 Clutter.Groups; one for the collapsed state
// (cgroup) and one for the expanded state (egroup). Each
// group contains a single vertical Big.Box (cbox and ebox
// respectively), which have the appropriate fixed width. The
// cbox contains either the collapsed widget actor or else the
// rotated title. The ebox contains the horizontal title (if
// any), separator line, and the expanded widget actor. (If
// the widget doesn't have a collapsed actor, and therefore
// supports pop-out, then it will also have a vertical line
// between the two groups, which will only be shown during
// pop-out.)
//
// In the expanded view, cgroup is hidden and egroup is shown.
// When animating to the collapsed view, first the ebox is
// slid offscreen by giving it increasingly negative x
// coordinates within egroup. Then once it's fully offscreen,
// we hide egroup, show cgroup, and slide cbox back in in the
// same way.
//
// The pop-out view works similarly to the second half of the
// collapsed-to-expanded transition, except that the
// horizontal title gets hidden to avoid duplication.
this.actor = new Clutter.Group();
this._hbox = new Big.Box({ background_color: WIDGETBOX_BG_COLOR,
padding_top: WIDGETBOX_PADDING,
padding_bottom: WIDGETBOX_PADDING,
padding_right: WIDGETBOX_PADDING,
// Left padding is here to make up for
// the X offset used for the sidebar
// to hide its rounded corners
padding_left: 2 * WIDGETBOX_PADDING,
spacing: WIDGETBOX_PADDING,
corner_radius: WIDGETBOX_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
reactive: true });
this.actor.add_actor(this._hbox);
this._cgroup = new Clutter.Group({ clip_to_allocation: true });
this._hbox.append(this._cgroup, Big.BoxPackFlags.NONE);
this._cbox = new Big.Box({ width: Widget.COLLAPSED_WIDTH,
clip_to_allocation: true });
this._cgroup.add_actor(this._cbox);
if (this._widget.collapsedActor) {
if (this._widget.collapsedActor == this._widget.actor)
this._singleActor = true;
else {
this._cbox.append(this._widget.collapsedActor,
Big.BoxPackFlags.NONE);
}
} else {
let vtitle = new Clutter.Text({ font_name: "Sans 16px",
text: this._widget.title,
rotation_angle_z: -90.0 });
let signalId = vtitle.connect('notify::allocation',
function () {
vtitle.disconnect(signalId);
vtitle.set_anchor_point(vtitle.natural_width, 0);
vtitle.set_size(vtitle.natural_height,
vtitle.natural_width);
});
this._vtitle = vtitle;
this._cbox.append(this._vtitle, Big.BoxPackFlags.NONE);
this._vline = new Clutter.Rectangle({ color: BLACK, width: 1 });
this._hbox.append(this._vline, Big.BoxPackFlags.NONE);
this._vline.hide();
// Set up pop-out
this._eventHandler = this._hbox.connect('captured-event',
Lang.bind(this, this._popEventHandler));
this._activationHandler = this._widget.connect('activated',
Lang.bind(this, this._activationHandler));
}
this._egroup = new Clutter.Group({ clip_to_allocation: true });
this._hbox.append(this._egroup, Big.BoxPackFlags.NONE);
this._ebox = new Big.Box({ spacing: WIDGETBOX_PADDING,
width: Widget.EXPANDED_WIDTH,
clip_to_allocation: true });
this._egroup.add_actor(this._ebox);
if (this._widget.title) {
this._htitle = new Clutter.Text({ font_name: "Sans 16px",
text: this._widget.title });
this._ebox.append(this._htitle, Big.BoxPackFlags.NONE);
this._hline = new Clutter.Rectangle({ color: BLACK, height: 1 });
this._ebox.append(this._hline, Big.BoxPackFlags.NONE);
}
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
if (expanded)
this._setWidgetExpanded();
else
this._setWidgetCollapsed();
},
// Given a name like "imports.ui.widget.ClockWidget", turn that
// into a constructor function
_ctorFromName: function(name) {
// Make sure it's a valid import
if (!name.match(/^imports(\.[a-zA-Z0-9_]+)+$/))
throw new Error("widget name must start with 'imports.'");
if (name.match(/^imports\.gi\./))
throw new Error("cannot import widget from GIR");
let ctor = eval(name);
// Make sure it's really a constructor
if (!ctor || typeof(ctor) != "function")
throw new Error("widget name is not a constructor");
// Make sure it's a widget
let proto = ctor.prototype;
while (proto && proto != Widget.Widget.prototype)
proto = proto.__proto__;
if (!proto)
throw new Error("widget does not inherit from Widget prototype");
return ctor;
},
expand: function() {
Tweener.addTween(this._cbox, { x: -Widget.COLLAPSED_WIDTH,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._expandPart1Complete,
onCompleteScope: this });
this.state = this._widget.state = Widget.STATE_EXPANDING;
},
_setWidgetExpanded: function() {
this._cgroup.hide();
this._egroup.show();
if (this._singleActor) {
this._widget.actor.unparent();
this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE);
}
if (this._htitle) {
this._htitle.show();
this._hline.show();
}
},
_expandPart1Complete: function() {
this._cbox.x = 0;
this._setWidgetExpanded();
if (this._widget.expand) {
try {
this._widget.expand();
} catch (e) {
logError(e, 'Widget failed to expand');
}
}
this._ebox.x = -Widget.EXPANDED_WIDTH;
Tweener.addTween(this._ebox, { x: 0,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._expandComplete,
onCompleteScope: this });
},
_expandComplete: function() {
this.state = this._widget.state = Widget.STATE_EXPANDED;
},
collapse: function() {
Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._collapsePart1Complete,
onCompleteScope: this });
this.state = this._widget.state = Widget.STATE_COLLAPSING;
},
_setWidgetCollapsed: function() {
this._egroup.hide();
this._cgroup.show();
if (this._singleActor) {
this._widget.actor.unparent();
this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE);
}
if (this._htitle) {
this._htitle.hide();
this._hline.hide();
}
if (this._vtitle)
this._cbox.height = this._ebox.height;
},
_collapsePart1Complete: function() {
this._ebox.x = 0;
this._setWidgetCollapsed();
if (this._widget.collapse) {
try {
this._widget.collapse();
} catch (e) {
logError(e, 'Widget failed to collapse');
}
}
this._cbox.x = -Widget.COLLAPSED_WIDTH;
Tweener.addTween(this._cbox, { x: 0,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._collapseComplete,
onCompleteScope: this });
},
_collapseComplete: function() {
this.state = this._widget.state = Widget.STATE_COLLAPSED;
},
_popEventHandler: function(actor, event) {
let type = event.type();
if (type == Clutter.EventType.ENTER) {
this._clearPopInTimeout();
if (this.state == Widget.STATE_COLLAPSED ||
this.state == Widget.STATE_COLLAPSING) {
this._popOut();
return false;
}
} else if (type == Clutter.EventType.LEAVE &&
(this.state == Widget.STATE_POPPED_OUT ||
this.state == Widget.STATE_POPPING_OUT)) {
// If moving into another actor within this._hbox, let the
// event be propagated
let into = event.get_related();
while (into) {
if (into == this._hbox)
return false;
into = into.get_parent();
}
// Else, moving out of this._hbox
this._setPopInTimeout();
return false;
}
return false;
},
_activationHandler: function() {
if (this.state == Widget.STATE_POPPED_OUT)
this._popIn();
},
_popOut: function() {
if (this.state != Widget.STATE_COLLAPSED &&
this.state != Widget.STATE_COLLAPSING)
return;
this._vline.show();
this._egroup.show();
this._ebox.x = -Widget.EXPANDED_WIDTH;
Tweener.addTween(this._ebox, { x: 0,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._popOutComplete,
onCompleteScope: this });
this.state = this._widget.state = Widget.STATE_POPPING_OUT;
Main.chrome.addInputRegionActor(this._hbox);
},
_popOutComplete: function() {
this.state = this._widget.state = Widget.STATE_POPPED_OUT;
},
_setPopInTimeout: function() {
this._clearPopInTimeout();
this._popInTimeout = Mainloop.timeout_add(POP_IN_LAG, Lang.bind(this, function () { this._popIn(); return false; }));
},
_clearPopInTimeout: function() {
if (this._popInTimeout) {
Mainloop.source_remove(this._popInTimeout);
delete this._popInTimeout;
}
},
_popIn: function() {
this._clearPopInTimeout();
if (this.state != Widget.STATE_POPPED_OUT &&
this.state != Widget.STATE_POPPING_OUT)
return;
Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH,
time: ANIMATION_TIME / 2,
transition: "easeOutQuad",
onComplete: this._popInComplete,
onCompleteScope: this });
},
_popInComplete: function() {
this.state = this._widget.state = Widget.STATE_COLLAPSED;
this._vline.hide();
this._egroup.hide();
this._ebox.x = 0;
Main.chrome.removeInputRegionActor(this._hbox);
},
destroy: function() {
if (this._widget.destroy)
this._widget.destroy();
}
};

View File

@ -0,0 +1,109 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
function WindowAttentionHandler() {
this._init();
}
WindowAttentionHandler.prototype = {
_init : function() {
this._startupIds = {};
this._sources = {};
let display = global.screen.get_display();
display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
let tracker = Shell.WindowTracker.get_default();
tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
},
_onStartupSequenceChanged : function(tracker) {
let sequences = tracker.get_startup_sequences();
this._startupIds = {};
for(let i = 0; i < sequences.length; i++) {
this._startupIds[sequences[i].get_id()] = true;
}
},
_getTitle : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return app.get_name();
else
return window.title;
},
_getBanner : function(app, window) {
if (this._startupIds[window.get_startup_id()])
return _("%s has finished starting").format(app.get_name());
else
return _("'%s' is ready").format(window.title);
},
_onWindowDemandsAttention : function(display, window) {
// We don't want to show the notification when the window is already focused,
// because this is rather pointless.
// Some apps (like GIMP) do things like setting the urgency hint on the
// toolbar windows which would result into a notification even though GIMP itself is
// focused.
// We are just ignoring the hint on skip_taskbar windows for now.
// (Which is the same behaviour as with metacity + panel)
if (!window || window.has_focus() || window.is_skip_taskbar())
return;
let tracker = Shell.WindowTracker.get_default();
let app = tracker.get_window_app(window);
let appId = app.get_id();
let source = this._sources[appId];
if (source == null) {
source = new Source(app, window);
this._sources[appId] = source;
Main.messageTray.add(source);
source.connect('clicked', Lang.bind(this, function() { source.destroy(); }));
source.connect('destroy', Lang.bind(this, function() { delete this._sources[appId]; }));
}
let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window));
source.notify(notification);
window.connect('notify::title', Lang.bind(this, function(win) {
notification.update(this._getTitle(app, win), this._getBanner(app, win));
}));
window.connect('notify::demands-attention', Lang.bind(this, function() { source.destroy(); }));
window.connect('focus', Lang.bind(this, function() { source.destroy(); }));
window.connect('unmanaged', Lang.bind(this, function() { source.destroy(); }));
}
};
function Source(app, window) {
this._init(app, window);
}
Source.prototype = {
__proto__ : MessageTray.Source.prototype,
_init: function(app, window) {
MessageTray.Source.prototype._init.call(this, app.get_name());
this._window = window;
this._app = app;
this._setSummaryIcon(this.createNotificationIcon());
},
createNotificationIcon : function() {
return this._app.create_icon_texture(this.ICON_SIZE);
},
clicked : function() {
Main.activateWindow(this._window);
MessageTray.Source.prototype.clicked.call(this);
}
};

View File

@ -1,16 +1,80 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const AltTab = imports.ui.altTab;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const WINDOW_ANIMATION_TIME = 0.25;
const DIM_TIME = 0.500;
const UNDIM_TIME = 0.250;
var dimShader = undefined;
function getDimShader() {
if (dimShader === null)
return null;
if (!dimShader) {
let [success, source, length] = GLib.file_get_contents(global.datadir +
'/shaders/dim-window.glsl');
try {
let shader = new Clutter.Shader();
shader.set_fragment_source(source, -1);
shader.compile();
dimShader = shader;
} catch (e) {
log(e.message);
dimShader = null;
}
}
return dimShader;
}
function WindowDimmer(actor) {
this._init(actor);
}
WindowDimmer.prototype = {
_init: function(actor) {
this.actor = actor;
},
set dimFraction(fraction) {
this._dimFraction = fraction;
let shader = getDimShader();
if (!Meta.prefs_get_attach_modal_dialogs() || !shader) {
this.actor.set_shader(null);
return;
}
if (fraction > 0.01) {
this.actor.set_shader(shader);
this.actor.set_shader_param_float('height', this.actor.get_height());
this.actor.set_shader_param_float('fraction', fraction);
} else
this.actor.set_shader(null);
},
get dimFraction() {
return this._dimFraction;
},
_dimFraction: 0.0
};
function getWindowDimmer(texture) {
if (!texture._windowDimmer)
texture._windowDimmer = new WindowDimmer(texture);
return texture._windowDimmer;
}
function WindowManager() {
this._init();
@ -18,36 +82,65 @@ function WindowManager() {
WindowManager.prototype = {
_init : function() {
let shellwm = global.window_manager;
this._shellwm = global.window_manager;
this._keyBindingHandlers = [];
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
this._mapping = [];
this._destroying = [];
this._switchData = null;
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._dimmedWindows = [];
shellwm.takeover_keybinding('switch_windows');
shellwm.connect('keybinding::switch_windows', Lang.bind(this, this._startAppSwitcher));
this._switchData = null;
this._shellwm.connect('kill-switch-workspace', Lang.bind(this, this._switchWorkspaceDone));
this._shellwm.connect('kill-window-effects', Lang.bind(this, function (shellwm, actor) {
this._minimizeWindowDone(shellwm, actor);
this._maximizeWindowDone(shellwm, actor);
this._unmaximizeWindowDone(shellwm, actor);
this._mapWindowDone(shellwm, actor);
this._destroyWindowDone(shellwm, actor);
}));
this._shellwm.connect('switch-workspace', Lang.bind(this, this._switchWorkspace));
this._shellwm.connect('minimize', Lang.bind(this, this._minimizeWindow));
this._shellwm.connect('maximize', Lang.bind(this, this._maximizeWindow));
this._shellwm.connect('unmaximize', Lang.bind(this, this._unmaximizeWindow));
this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
this._workspaceSwitcherPopup = null;
this.setKeybindingHandler('switch_to_workspace_left', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_right', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_up', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_to_workspace_down', Lang.bind(this, this._showWorkspaceSwitcher));
this.setKeybindingHandler('switch_windows', Lang.bind(this, this._startAppSwitcher));
Main.overview.connect('showing', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++)
this._undimParentWindow(this._dimmedWindows[i], true);
}));
Main.overview.connect('hiding', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++)
this._dimParentWindow(this._dimmedWindows[i], true);
}));
},
setKeybindingHandler: function(keybinding, handler){
if (this._keyBindingHandlers[keybinding])
this._shellwm.disconnect(this._keyBindingHandlers[keybinding]);
else
this._shellwm.takeover_keybinding(keybinding);
this._keyBindingHandlers[keybinding] =
this._shellwm.connect('keybinding::' + keybinding, handler);
},
_shouldAnimate : function(actor) {
if (Main.overview.visible)
return false;
if (actor && (actor.get_window_type() != Meta.CompWindowType.NORMAL))
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
return false;
return true;
},
@ -74,11 +167,19 @@ WindowManager.prototype = {
* maybe TODO: get icon geometry passed through and move the window towards it?
*/
this._minimizing.push(actor);
let primary = global.get_primary_monitor();
let xDest = primary.x;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
xDest += primary.width;
Tweener.addTween(actor,
{ scale_x: 0.0,
scale_y: 0.0,
x: xDest,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
@ -121,23 +222,122 @@ WindowManager.prototype = {
_unmaximizeWindowDone : function(shellwm, actor) {
},
_parentHasOtherAttachedDialog: function(parent, self) {
var count = 0;
parent.foreach_transient(function(win) {
if (win.get_window_type() == Meta.WindowType.MODAL_DIALOG && win != self)
count++;
return false;
});
return count != 0;
},
_markParentWindowAsDimmable: function(actor, animate) {
if (Meta.prefs_get_attach_modal_dialogs()) {
this._dimmedWindows.push(actor);
if (this._shouldAnimate())
this._dimParentWindow(actor, animate);
}
},
_unmarkParentWindowAsDimmable: function(actor, animate) {
if (!Main.overview.visible)
this._undimParentWindow(actor, true);
this._dimmedWindows = this._dimmedWindows.filter(function(win) {
return win != actor;
});
},
_dimParentWindow: function(actor, animate) {
let meta = actor.get_meta_window();
let parent = meta.get_transient_for();
if (!parent)
return;
let parentActor = parent.get_compositor_private();
if (!parentActor || this._parentHasOtherAttachedDialog(parent, meta))
return;
let texture = parentActor.get_texture();
if (animate)
Tweener.addTween(getWindowDimmer(texture),
{ dimFraction: 1.0,
time: DIM_TIME,
transition: 'linear'
});
else
getWindowDimmer(texture).dimFraction = 1.0;
},
_undimParentWindow: function(actor, animate) {
let meta = actor.get_meta_window();
let parent = meta.get_transient_for();
if (!parent)
return;
let parentActor = parent.get_compositor_private();
if (!parentActor || this._parentHasOtherAttachedDialog(parent, meta))
return;
let texture = parentActor.get_texture();
if (animate)
Tweener.addTween(getWindowDimmer(texture),
{ dimFraction: 0.0,
time: UNDIM_TIME,
transition: 'linear'
});
else
getWindowDimmer(texture).dimFraction = 0.0;
},
_mapWindow : function(shellwm, actor) {
actor._windowType = actor.meta_window.get_window_type();
actor._notifyWindowTypeSignalId = actor.meta_window.connect('notify::window-type', Lang.bind(this, function () {
let type = actor.meta_window.get_window_type();
if (type == actor._windowType)
return;
if (type == Meta.WindowType.MODAL_DIALOG)
this._markParentWindowAsDimmable(actor, true);
else if (actor._windowType == Meta.WindowType.MODAL_DIALOG)
this._unmarkParentWindowAsDimmable(actor, true);
actor._windowType = type;
}));
if (actor.meta_window.get_window_type() == Meta.WindowType.MODAL_DIALOG
&& Meta.prefs_get_attach_modal_dialogs()
&& actor.get_meta_window().get_transient_for()) {
this._markParentWindowAsDimmable(actor, true);
if (this._shouldAnimate()) {
actor.set_scale(1.0, 0.0);
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._mapWindowOverwrite,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
return;
}
shellwm.completed_map(actor);
return;
}
if (!this._shouldAnimate(actor)) {
shellwm.completed_map(actor);
return;
}
actor.move_anchor_point_from_gravity(Clutter.Gravity.CENTER);
actor.set_scale(0.0, 0.0);
actor.opacity = 0;
actor.show();
/* scale window up from 0x0 to normal size */
/* Fade window in */
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_x: 1.0,
scale_y: 1.0,
{ opacity: 255,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
@ -150,8 +350,7 @@ WindowManager.prototype = {
_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);
actor.opacity = 255;
shellwm.completed_map(actor);
}
},
@ -163,10 +362,51 @@ WindowManager.prototype = {
},
_destroyWindow : function(shellwm, actor) {
let parent = actor.meta_window.get_transient_for();
if (actor._notifyWindowTypeSignalId) {
actor.meta_window.disconnect(actor._notifyWindowTypeSignalId);
actor._notifyWindowTypeSignalId = 0;
}
while (actor.meta_window.get_window_type() == Meta.WindowType.MODAL_DIALOG
&& parent) {
this._unmarkParentWindowAsDimmable(actor, true);
if (!Meta.prefs_get_attach_modal_dialogs()
|| !this._shouldAnimate())
break;
actor.set_scale(1.0, 1.0);
actor.show();
this._destroying.push(actor);
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor);
this._destroyWindowDone(shellwm, actor);
}));
Tweener.addTween(actor,
{ scale_y: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowDone,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
return;
}
shellwm.completed_destroy(actor);
},
_destroyWindowDone : function(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
let parent = actor.get_meta_window().get_transient_for();
if (parent && actor._parentDestroyId) {
parent.disconnect(actor._parentDestroyId);
actor._parentDestroyId = 0;
}
shellwm.completed_destroy(actor);
}
},
_switchWorkspace : function(shellwm, from, to, direction) {
@ -175,7 +415,7 @@ WindowManager.prototype = {
return;
}
let windows = shellwm.get_switch_workspace_actors();
let windows = global.get_windows();
/* @direction is the direction that the "camera" moves, so the
* screen contents have to move one screen's worth in the
@ -236,7 +476,7 @@ WindowManager.prototype = {
{ x: xDest,
y: yDest,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
transition: 'easeOutQuad',
onComplete: this._switchWorkspaceDone,
onCompleteScope: this,
onCompleteParams: [shellwm]
@ -245,7 +485,7 @@ WindowManager.prototype = {
{ x: 0,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad"
transition: 'easeOutQuad'
});
},
@ -272,9 +512,55 @@ WindowManager.prototype = {
},
_startAppSwitcher : function(shellwm, binding, window, backwards) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide();
let tabPopup = new AltTab.AltTabPopup();
if (!tabPopup.show(backwards ? -1 : 1))
if (!tabPopup.show(backwards))
tabPopup.destroy();
},
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
/* We don't support this kind of layout */
if (binding == 'switch_to_workspace_up' || binding == 'switch_to_workspace_down')
return;
if (global.screen.n_workspaces == 1)
return;
if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
if (binding == 'switch_to_workspace_left') {
this.actionMoveWorkspaceLeft();
}
if (binding == 'switch_to_workspace_right') {
this.actionMoveWorkspaceRight();
}
},
actionMoveWorkspaceLeft: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
if (activeWorkspaceIndex > 0) {
global.screen.get_workspace_by_index(activeWorkspaceIndex - 1).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex - 1);
} else if (!Main.overview.visible) {
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.LEFT, activeWorkspaceIndex);
}
},
actionMoveWorkspaceRight: function() {
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
if (activeWorkspaceIndex < global.screen.n_workspaces - 1) {
global.screen.get_workspace_by_index(activeWorkspaceIndex + 1).activate(global.get_current_time());
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex + 1);
} else if (!Main.overview.visible) {
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.RIGHT, activeWorkspaceIndex);
}
}
};

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