Compare commits

...

278 Commits

Author SHA1 Message Date
94d01bed12 build: Split out "private" sources variable that can be easily appended
Move the action muxing copy stuff in there.
2011-12-20 13:41:08 -05:00
9daf358122 action muxer: drop direct GDBusActionGroup use
We now have GRemoteActionGroup interface with the needed API,
implemented by GDBusActionGroup.

With the new API we could theoretically turn GActionMuxer itself into a
GRemoteActionGroup and expose the _full API to the shell so that the
timestamps could be passed from there.
2011-12-17 13:23:26 -05:00
b4b3f5a669 GActionMuxer: pass platform data
Pass the current timestamp as platform data when activating
an action. This is implemented slightly hacky, since we use
clutter_get_current_event_time() to get at the timestamp, but
the alternative is to expose g_action_muxer_activate_action_full
to js, which would be quite a bit more involved.
2011-12-16 23:39:14 -05:00
5290a9dd08 Add per-window actions
GTK+ also exports window-specific actions, by putting the object path
for the exported action group in the _DBUS_OBJECT_PATH X property.
We add this action group to the app's muxer with a 'win' prefix,
since that is what the exported menu expects. Whenever the focus
window changes, we update the window-specific actions of its
application, and emit notify::action-group to cause the app
menu to be updated.
2011-12-15 01:25:35 -05:00
ab4a7c5237 Another update for GLib API changes
GDBusActionGroup api has changed again, adapt to that.
Also, use a GActionMuxer to add the 'app.' prefix to actions,
instead of manually stripping it out of the action names.
In the future, the muxer will also contain per-window actions
with a 'win.' prefix.
2011-12-15 00:29:31 -05:00
95e5c5cfb1 Application Menu: watch for menu property changes
By the time the window is first mapped and the app menu button is
synced, we may not have finished reading the menu. In that case,
connect to notify::menu and update accordingly.
2011-12-08 21:55:51 +01:00
757fb5796e Application Menu: update for latest GMenu changes
GMenuProxy has been replaced by GDBusMenuModel, and the object path
has been moved (now needs to be retrieved from the AppMenu GApplication
property).
Update the test to prefix each action with "app." as documented,
and use a GtkApplicationWindow instead of a plain GtkWindow.
2011-12-08 21:53:03 +01:00
75e9fa9cfb test-gapplication: update for latest gapplication changes
g_application_set_action_group is deprecated, we should use
GActionMap. Also, GSimpleActions can now be constructed as normal
GObjects.
2011-12-02 22:15:14 +01:00
8997aa45b1 popupMenu: Remove app. from app actions 2011-12-01 12:33:07 -05:00
f884dbbfb2 Application Menu: add support for showing GApplication actions
Use the new GApplication support in ShellApp to create the application
menu. Supports plain (no state), boolean and double actions.
Includes a test application (as no other application uses GApplication
for actions)

https://bugzilla.gnome.org/show_bug.cgi?id=621203
2011-12-01 10:21:38 -05:00
d0c36bb732 ShellApp: port to new GDBusActionGroup and GMenuProxy API
GDBusActionGroup and GMenuProxy are new objects in GIO 2.32 that
help with accessing menus and actions of remote applications.
This patch makes it possible for the shell to associate an
application with a dbus name and from that a GMenu, that will
be shown as the application menu.

https://bugzilla.gnome.org/show_bug.cgi?id=621203
2011-11-25 18:20:38 -05:00
17c46c2452 Port everything to class framework
The last patch in the sequence. Every place that was previously
setting prototype has been ported to Lang.Class, to make code more
concise and allow for better toString().

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
0996174b3d Port GDM and Caribou to GDBus
During the mass port to GDBus, this classes were left out (probably
because they didn't exist at the time). Now it's time to update
them.

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
d6b6f814d3 Port all classes with inheritance to class framework
All classes that have at least one other derived class (and thus
benefit from the framework) have been now ported. These includes
NMDevice, SearchProvider, AltTab.SwitcherList, and some other
stuff around.

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
987099ea55 Port ModalDialog to the class framework
Similar to the previous commits, time to port shell modal dialogs
to the class framework.

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
b356aa8e3b Port message tray sources and notifications to class framework
Third step in the class framework port, now it's the turn of
MessageTray.Source and MessageTray.Notification, as well as
the various implementations around the shell.

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
566bdb50c2 Port PanelMenu to new class framework
Second patch in the class framework, now it's the turn of
PanelMenu (buttons, menus and status indicators).

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
2b57603271 Port PopupMenu to new Lang.Class framework
The Lang module in gjs has recently gained a small yet powerful
Class framework, that should help improve the readability of code
when using complex inheritance.
This commit starts porting shell code, by rewriting all classes in
popupMenu.js (and all derived classes) to Lang.Class.

https://bugzilla.gnome.org/show_bug.cgi?id=664436
2011-11-24 09:50:04 +01:00
c3528f5b6b lookingGlass: Fix global key press handler
No idea why connecting a key-press-event to a non-reactive actor
used to work, but some Clutter update broke it. Obvious fix is
to make the actor reactive.

https://bugzilla.gnome.org/show_bug.cgi?id=664582
2011-11-22 22:33:05 +01:00
4c7cc94cdc build: Add test/unit/jsParse.js to Makefile
Commit 3941961f8b added the file without referencing it in the Makefile,
which breaks distcheck.
2011-11-22 15:34:22 +01:00
5ff2285707 Bump version to 3.3.2
- Require Mutter 3.3.2 for keybindings additions
 - Update NEWS
2011-11-21 19:38:55 -05:00
d714dfd82e shell-wm: Remove takeover_keybinding()
Introspection support is now good enough to set a custom keybinding
handler directly from JS.

https://bugzilla.gnome.org/show_bug.cgi?id=663584
2011-11-22 00:42:28 +01:00
b1064cbe50 WorkspaceThumnail: fix typo
An if is missing, causing the subsequent expression to evaluate to
nothing, and the invocation it should be protect to be unconditional.
2011-11-21 21:59:09 +01:00
8d3e5ea507 Make notification icon buttons elegant.
The huge icons had little whitespace and don't scale pixel precise.
2011-11-21 15:39:36 +01:00
001b6afc7e Updated Greek translation 2011-11-21 09:14:13 +02:00
55d6c5ea8f polkit: Find the best user to authenticate as
We prefer to ask the user for his own password. If PolicyKit
is not configured to accept that, try the root password. If
PolicyKit does not accept that either, ask for password of
the first user that PolicyKit _will_ accept. The last case
is a bit broken, but should rarely occur in real-life
configurations.

https://bugzilla.gnome.org/show_bug.cgi?id=651547
2011-11-18 17:28:58 -05:00
fa2ff8158f Updated Spanish translation 2011-11-16 14:23:30 +01:00
97e7ea0b5d shellDBus: Ignore extension properties that we don't care about 2011-11-15 16:48:20 -05:00
65dec2b72a shellDBus: Add missing initialization 2011-11-15 16:48:20 -05:00
5fd3ca8d09 Updated Finnish translation 2011-11-15 22:21:46 +02:00
dc9a8d505d Drop a leftover mention of GConf from configure
There is no GConf usage anymore, so drop it for good.
2011-11-15 09:24:48 -05:00
fc8d13f4bd GDBus: restore non-fatality of name acquisition error
commit 5350302b09 dropped the possibility
to make a dbus name acquisition failure non-fatal.
Btw, it has also overriden the name in the error message.

Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Signed-off-by: Colin Walters <walters@verbum.org>

https://bugzilla.gnome.org/show_bug.cgi?id=663941
2011-11-15 09:19:19 -05:00
d1aa7de5d0 Drop last remnants of dbus-glib from configure
GDMUSER has been unused since before 3.2.
2011-11-15 09:17:50 -05:00
e279ef1c7c user-menu: Disable combo box if no accounts are enabled
If no telepathy accounts have been set up or enabled, the IM status
chooser won't have any effect. To avoid confusing behavior, make
the status selector insensitive in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=662800
2011-11-15 13:54:29 +01:00
b88657ab83 combo-box-menu-item: Propagate pseudo classes to the combo menu
ComboBoxMenuItems use ClutterClones to reconstruct the active item
in the associated ComboMenu, so pseudo class changes due to state
changes of the ComboBoxMenuItem don't have the intended effect
(since the actual style information is taken from the associated
ComboBoxMenu item).
As a fix, propagate relevant pseudo class changes to the active
ComboBoxMenu item.

https://bugzilla.gnome.org/show_bug.cgi?id=662799
2011-11-15 13:54:29 +01:00
d20e646ed6 combo-box-menu-item: Propagate style changes to the combo menu
ComboBoxMenuItems use ClutterClones to reconstruct the active item
in the associated ComboMenu to not impose a particular MenuItem type
in the menu. However, this results in style changes (for instance
those triggered by icon-theme or text-scaling-factor changes) of
the ComboBoxMenuItem not having a visual effect until the ComboBoxMenu
is shown.
As a fix, force a style update on the ComboBoxMenu when the item's
style changes.

https://bugzilla.gnome.org/show_bug.cgi?id=662799
2011-11-15 13:46:08 +01:00
8678b87120 a11y: Adapt to re-addition of 'visual-bell'
The option was merge with 'visual-bell-type' with the GSettings
port, but the change turned out too disruptive for the universal
access menu / settings panel, so gsettings-desktop-schemas commit
a5819b2a4e9 re-added the separate option.
2011-11-14 15:45:51 +01:00
960571a589 Updated Galician translations 2011-11-13 22:27:56 +01:00
d856338f86 bluetooth: Fix undefined variable issue
https://bugzilla.gnome.org/show_bug.cgi?id=663891
2011-11-13 15:23:38 -05:00
2b6b2d93a9 shellDBus: Fix missing user of old DBus API
https://bugzilla.gnome.org/show_bug.cgi?id=663902
2011-11-12 17:54:47 -05:00
363bd04166 browser-plugin: Move "entry points" comment
https://bugzilla.gnome.org/show_bug.cgi?id=663823
2011-11-12 13:38:36 -05:00
9bc1a68fe4 browser-plugin: Use g_strndup to get a string property
WebKit-based browsers like Chromium and Epiphany may insert extra junk at the
end of NPStrings, so we cannot depend on the strlen matching.

https://bugzilla.gnome.org/show_bug.cgi?id=663823
2011-11-12 13:38:36 -05:00
2c2729f7be browser-plugin: Set that we need XEmbed
This makes the plugin work under WebKit-based browsers such as Chromium and
Epiphany. See http://code.google.com/p/chromium/issues/detail?id=38229 and
WindowedCreatePlugin() in
http://src.chromium.org/viewvc/chrome/trunk/src/webkit/plugins/npapi/webplugin_delegate_impl_gtk.cc?revision=86823&content-type=text%2Fplain
for more information.

https://bugzilla.gnome.org/show_bug.cgi?id=663823
2011-11-12 13:38:36 -05:00
9011959356 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-11-12 19:05:01 +08:00
c79b8bbe7e [l10n] Updated Estonian translation 2011-11-12 12:47:58 +02:00
da59eebf8e Updated British English translation 2011-11-12 07:49:25 +00:00
7854024326 user-menu: Fix fallout from GDBus port
- replace some left-over references to GnomeSession.Presence.setStatus()
 - the correct replacement for GnomeSession.Presence.getStatus()
   is *not* GnomeSession.Presence.connectSignal('StatusChanged')
2011-11-12 00:00:15 +01:00
a9ab8784c4 Adapt to mutter moving to GSettings
https://bugzilla.gnome.org/show_bug.cgi?id=663429
2011-11-11 20:32:43 +01:00
de5b00fd52 Updated Norwegian bokmål translation 2011-11-11 18:58:33 +01:00
6547f75b12 Port client side code to GDBus
This continues the series of patches for GDBus porting, affecting
all code that accesses remote DBus objects. This includes modemManager,
automount, autorun (for the hotplug sniffer), calendar, network (for
nm-applet only), power, scripting (for perf monitor interface)

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-11 11:15:38 -05:00
827bf506a7 notificationDaemon, magnifierDBus: port to GDBus
Move /org/freedesktop/Notifications and /org/gnome/Magnifier to the
GDBus connection, so they're matched with the appropriate DBus name.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-11 11:15:38 -05:00
adc187c32e screensaver, gnomesession: port to GDBus based bindings
Port org.gnome.ScreenSaver and org.gnome.SessionManager glue code
to use GDBus, and move /org/gnome/Shell/EndSessionDialog to the
GDBus connection, so it is backed by the org.gnome.Shell name.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-11 11:15:38 -05:00
5350302b09 Port to new GDBus bindings in gjs
Rewrite code acquiring dbus names so that it uses GDBus, and rewrite
ShellDBus so that it is exposed on the GDBus connection. Ports of
the other objects will follow.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-11 11:15:38 -05:00
167ca75388 Replace deprecated gtk_widget_size_request 2011-11-11 09:50:18 +01:00
46cea67258 app: Fix crash on search
Not all desktop files tracked by the shell have
Exec lines.  This could be because they're actually
run by another process, for instance, and the desktop
file is merely there to provide metadata.  For example,
nautilus-pastebin provides a desktop file without an
Exec line.

The shell currently crashes if one of these partial
desktop files is installed and the user attempts to
search from the overview.

commit 37726a4cb6 fixed
a similar crasher.

This commit fixes the next one lower in the code.

https://bugzilla.gnome.org/show_bug.cgi?id=663815
2011-11-10 17:45:18 -05:00
463e0919d4 Remove all stray imports to imports.dbus
Some modules were importing DBus without actually using it.

https://bugzilla.gnome.org/show_bug.cgi?id=648651
2011-11-09 13:56:42 -05:00
98906c1da3 Updated Japanese translation 2011-11-09 21:24:15 +09:00
fry
b71e66c335 window-manager: Fix variable name
In _shouldAnimate() _animationBlockCount was referred to as
_animationsBlocked, fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=662394
2011-11-08 01:57:20 +01:00
2b6c5bb416 main: Fix shell_dbus_acquire_names()
Commit 39727d1156 refactored dbus acquisition, but due to wrong use
of va_args we would only ever acquire the first bus name passed.

https://bugzilla.gnome.org/show_bug.cgi?id=658078
2011-11-08 01:01:10 +01:00
628e59894b Doc fixes
https://bugzilla.gnome.org/show_bug.cgi?id=663277
2011-11-07 15:24:59 -05:00
703d2ead33 workspaceThumbnail: Allow users to create workspaces at any position
Allow a user to create a new workspace by dragging a window or a launcher in
the middle of two existing ones.

https://bugzilla.gnome.org/show_bug.cgi?id=646409
2011-11-07 14:36:06 -05:00
43f53a708f NetworkMenu: fix regression in access-point-removed
When changing _findNetwork with _findExistingNetwork, I changed
the return value to avoid searching twice for the access point,
and changed some names. I forgot to update all points where those
names were used.

https://bugzilla.gnome.org/show_bug.cgi?id=663278
2011-11-06 16:55:30 -05:00
07e7331e7b gdm: Add a translator comment for 'Not Listed?'
https://bugzilla.gnome.org/show_bug.cgi?id=659946
2011-11-06 11:38:04 -05:00
c516af3130 Updated Spanish translation 2011-11-06 13:35:00 +01:00
39727d1156 main: factor out dbus names acquisition
This way it will be a lot shorter to add
a new name acquisition in the future

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

Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
2011-11-06 05:43:37 -05:00
85cd189a69 shellDBus: Lock down Eval() to be a development tool only
https://bugzilla.gnome.org/show_bug.cgi?id=662891
2011-11-05 17:00:53 -04:00
a8e35422f2 [l10n] Updated German translation 2011-11-05 21:11:04 +01:00
3941961f8b lookingGlass: Add tab-completion
https://bugzilla.gnome.org/show_bug.cgi?id=661054
2011-11-05 13:05:11 -04:00
d9c6485cbf data: Fix the description for enabled-extensions
The description for enabled-extensions referenced an old and removed key,
"disabled-extensions". Update the description to talk about the DBus methods
that GNOME Shell provides and talk about how the list is now an explicit
whitelist that needs to be there.

https://bugzilla.gnome.org/show_bug.cgi?id=663175
2011-11-05 09:22:49 -04:00
c52ccc76a3 build: Fix dependencies for debian-based distros
https://bugzilla.gnome.org/show_bug.cgi?id=659770
2011-11-05 13:52:36 +01:00
be1c4f26b5 magnifier: Use enum from gsettings-desktop-schemas
gsettings-desktop-schemas installs a public header file for enum
types in schemas - use those instead of mirroring the types in JS.

https://bugzilla.gnome.org/show_bug.cgi?id=662238
2011-11-04 23:28:53 +01:00
a6ee6739e0 ctrlAltTab: fix popup's allocation when primary.x != 0
As in commit 3944df1bd2 but for ctrlAltTab's
popup.

https://bugzilla.gnome.org/show_bug.cgi?id=662502
2011-11-04 18:45:16 +00:00
54a8ad8bc6 Updated Spanish translation 2011-11-04 13:42:20 +01:00
2541bfcdf2 Updated Galician translations 2011-11-04 12:57:07 +01:00
d7d5da0301 NetworkMenu: fix logic for updating wifi icon
Previously, we connected to notify::strength only if there was
already a signal connected, and the AP changed (thus, by induction,
we never connected). As a result, the icon became stale and different
from that shown inside the menu (which is correctly updated).

https://bugzilla.gnome.org/show_bug.cgi?id=650007
2011-11-04 10:19:20 +01:00
d2bd9efc25 keyboard: fix exception: global.current_event_time is not a function 2011-11-04 01:40:30 +00:00
779b18bf48 messageTray: don't steal focus when popping under the pointer
We must look for the actor under the pointer in the whole message tray and not
just in the notification. This will avoid us to capture focus when a
notification comes up with the pointer on the whole tray area.

https://bugzilla.gnome.org/show_bug.cgi?id=661358
2011-11-04 01:40:30 +00:00
618a53b34f build: Fix when bluetooth is disabled 2011-11-03 21:27:50 -04:00
f4eaadb948 Pass bluetooth directory to g-ir-scanner
Rather than relying on the .la file that jhbuild deletes, we
explicitly tell g-ir-scanner to look in this subdirectory.
2011-11-03 18:26:03 -04:00
ea061b0f46 configure: Turn off -Werror by default
We will eventually land jhbuild work to grep for warnings; for now
breaking the build is just too painful.
2011-11-03 14:58:10 -04:00
3652e42699 messageTray: Add option to (un)mute conversations
Add "Mute"/"Unmute" option to the right click menu for chats to allow muting conversations
without blocking the sender or disabling all non-urgent notifications. Muting a conversation
prevents the pop up of notifications on new messages from the muted source, while these
messages are still available from the summary notification in the message tray.

https://bugzilla.gnome.org/show_bug.cgi?id=659962
2011-11-03 12:18:34 -04:00
398489f661 popup-menu: Add minimal handling of open/close to Sections
SubMenuMenuItems close automatically with their parent, however
closing fails when the parent item is a MenuSection, as those
currently ignore any open()/close() requests.
At some minimal handling by emitting the 'open-state-changed' signal,
so children like SubMenuMenuItems work as expected.

https://bugzilla.gnome.org/show_bug.cgi?id=661029
2011-11-03 15:36:57 +01:00
70fc13500d Network Menu: fix pulling out the first element from the More... submenu.
PopupMenu.firstMenuItem returns a PopupMenuItem, not an apObj. We
need to retrive the latter using the _apObj property.

Also, somehow the property from the number of elements in a menu
was changed from .length to .numMenuItems, and this broke the
destruction of the menu upon emptying it.

https://bugzilla.gnome.org/show_bug.cgi?id=659277
2011-11-03 13:12:03 +01:00
18541c447e messageTray: Reduce the scroll view fade
https://bugzilla.gnome.org/show_bug.cgi?id=662226
2011-10-31 13:45:57 -04:00
3294a6e1a7 theme: Lighten up the sent message color, clean up
Properly apply "received" style and drop unused border-radius styles
now that the messages have no background color

https://bugzilla.gnome.org/show_bug.cgi?id=658096
2011-10-31 12:41:48 -04:00
38563c38e8 Updated Czech translation 2011-10-30 14:33:55 +01:00
a465c5f996 theme: Add a selected-color to the polkit and network auth dialogs
https://bugzilla.gnome.org/show_bug.cgi?id=662969
2011-10-29 19:16:02 -04:00
1760ba1279 st-texture-cache: Fix colored symbolic icons
Commit b7bf712b97 broke colored symbolic icons by never including
the requested colors in the texture load request.

https://bugzilla.gnome.org/show_bug.cgi?id=662998
2011-10-29 19:33:30 +02:00
3d3c9546a2 NetworkMenu: don't query DBus properties of removed objects
Calling nm_access_point_get_ssid() in the handler of the
access-point-removed signal can result in DBus request, which will
then fail because the object was already removed at the server side.
Instead, use a difference function to retrieve the access point
object (the network), that compares directly by object identity.

https://bugzilla.gnome.org/show_bug.cgi?id=651378
2011-10-28 22:18:21 +02:00
203c5db5eb extensionSystem: Remove duplciated version check
This piece of accidentally duplicated code made sure that the OUT_OF_DATE
status was never set.

https://bugzilla.gnome.org/show_bug.cgi?id=662967
2011-10-28 16:12:52 -04:00
cf44234323 extensionSystem: Fix rebasing of extensions
We need to remove the extension from the order after it's disabled

https://bugzilla.gnome.org/show_bug.cgi?id=662704
2011-10-27 17:21:54 -04:00
cc94076ffb extensionSystem: Fix deferred loading of extensions
We need to show the list of installed extensions on EGO, so we can't defer
loading by not creating the extension meta.

https://bugzilla.gnome.org/show_bug.cgi?id=662704
2011-10-27 17:21:49 -04:00
8d137eae5b Updated Esperanto translation 2011-10-26 19:08:47 +02:00
51fa9ae513 Updated Swedish translation 2011-10-26 11:55:58 +02:00
9951c92459 Updated Slovenian translation 2011-10-25 21:17:43 +02:00
ee77e5d582 Updated Slovenian translation 2011-10-25 21:00:45 +02:00
d74721f229 main: Mute the browser plugin 2011-10-25 13:15:05 -04:00
1aa97b19f7 Stop using APIs deprecated in Clutter master
https://bugzilla.gnome.org/show_bug.cgi?id=662627
2011-10-24 17:18:26 -04:00
95de48e986 ShellApp: Junk last_used_time
Instead of saving the last_used_time per-app, grab the maximum time for all
windows. The logic is less hard to keep track of, and it solves some edge
case issues where windows that no longer exist update the user time, even
if none of the other windows have been used recently.

https://bugzilla.gnome.org/show_bug.cgi?id=660650
2011-10-24 16:22:32 -04:00
a147d0428d Updated Persian translation 2011-10-24 21:12:21 +03:30
90b3f7b7f6 Updated Turkish translation 2011-10-24 20:38:49 +03:00
c80acfda08 shell: Remove shell-arrow
It was unused and used deprecated Clutter APIs.
2011-10-24 12:35:01 -04:00
8a39145e3c Replace deprecated GDK functions
https://bugzilla.gnome.org/show_bug.cgi?id=662245
2011-10-24 18:31:22 +02:00
b62f5ef07d telepathy-client: Replace shell_util_new_from_string
The function has been removed in commit 786cfbd397, but one user
was overlooked when replacing it.

https://bugzilla.gnome.org/show_bug.cgi?id=661231
2011-10-24 16:37:15 +02:00
bd5c6c5cd6 Updated Norwegian bokmål translation 2011-10-24 09:36:56 +02:00
f874a57439 Updated Spanish translation 2011-10-23 20:30:39 +02:00
6a4525e554 Updated Spanish translation 2011-10-23 13:55:23 +02:00
d553a5bdc0 Updated Telugu Translation 2011-10-23 12:14:31 +05:30
80076965a7 Updated Lithuanian translation 2011-10-22 22:57:07 +03:00
84e8d38d4c Updated Hebrew translation. 2011-10-22 11:53:15 +02:00
33f3f9d997 Updated Hebrew translation. 2011-10-22 11:16:40 +02:00
be72b1d066 st-texture-cache: Unref each texture when we destroy the async load data
We ref the textures when we add them to the list, so we should unref
them when we destroy the list.
2011-10-21 17:43:11 -04:00
dc5d2b83ef user-menu: Hide "Switch user" on single user machines
Ignoring remote logins, the "Switch user" action is meaningless for
single user setups. Do not show it in that case.

https://bugzilla.gnome.org/show_bug.cgi?id=657011
2011-10-21 22:41:04 +02:00
3dabe645c2 Updated Bulgarian translation 2011-10-21 23:36:04 +03:00
e9ede362dc Add context to ambiguous strings in end session dialogs
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=658664
2011-10-21 22:29:13 +02:00
01357aca35 lookingGlass: make it look consistent with the rest of the Shell
https://bugzilla.gnome.org/show_bug.cgi?id=650900
2011-10-21 14:54:13 -04:00
c944dd6768 theme: Fix indentation
https://bugzilla.gnome.org/show_bug.cgi?id=650900
2011-10-21 14:54:05 -04:00
ff01ed5e4b lookingGlass: add Ctrl+PageUp/PageDown key shortcuts for switching tabs
The view selector in the overview does it too, so why not here?

https://bugzilla.gnome.org/show_bug.cgi?id=652223
2011-10-21 14:51:55 -04:00
d23c374326 Revert "Add Ctrl+PageUp/PageDown key shortcuts for switching tabs"
This reverts commit a69ebc8a68.

This was accidentally the old change.
2011-10-21 14:50:49 -04:00
a69ebc8a68 Add Ctrl+PageUp/PageDown key shortcuts for switching tabs
https://bugzilla.gnome.org/show_bug.cgi?id=652223
2011-10-21 09:22:15 -04:00
f4d8a35b9d altTab: Don't refuse to work when a pointer grab is in place
Allow push_modal to optionally only work with a keyboard only grab and
use that in altTab as a fallback to allow switching windows while a pointer grab
is in effect (like during DND operations).

https://bugzilla.gnome.org/show_bug.cgi?id=660457
2011-10-21 09:12:17 +02:00
2b140f8fb7 Updated Telugu Translation 2011-10-21 10:47:02 +05:30
ab603bdbbf Updated Telugu Translation 2011-10-21 10:47:02 +05:30
44e2f7f555 gnome-shell-extension-tool: Add facilities to enable/disable extensions
https://bugzilla.gnome.org/show_bug.cgi?id=661815
2011-10-20 17:38:48 -04:00
fd1b3b4fee extensionSystem: Rebase the extension order list to help prevent conflicts
When two extensions monkey-patch the same area, enable() and disable() may
behave badly and completely wreck things. To solve this, when disabling
an extension, "rebase" the extension list so that monkey patches should be
added and removed in order.

https://bugzilla.gnome.org/show_bug.cgi?id=661815
2011-10-20 17:38:48 -04:00
4ae2a0b2a5 extensionSystem: Only load importers for enabled extensions
Rather than loading and enabling all extensions at Shell init time, save some
time and gain some basic security by not loading extensions if they're
not enabled.

https://bugzilla.gnome.org/show_bug.cgi?id=661815
2011-10-20 17:38:48 -04:00
0cb415b3bd user-menu: Add missing semi-colons 2011-10-20 22:55:05 +02:00
c1fa9a82e6 docs: Allow building API documentation
As extensions.gnome.org starts to shape up, we should allow to
build the API documentation for St/Shell.

https://bugzilla.gnome.org/show_bug.cgi?id=661045
2011-10-20 22:48:44 +02:00
dde124ab5a user-menu: Minor style fix
Use cameCase for properties/methods defined in JS and under_score
for properties/methods imported from C.
2011-10-20 22:48:44 +02:00
668920cec4 Small coding style fixes 2011-10-20 22:42:30 +02:00
9b38c5b304 Minor documentation fixes 2011-10-20 16:26:07 -04:00
e63c2da433 gnome-shell-extension-tool: Use xdg-open
gnome-open is deprecated
2011-10-20 15:39:14 -04:00
38c768fdb3 gnome-shell-extension-tool: Fix error after creating extension
Commit 7a8a00c705 cleaned up the code to move all
files to a dictionary, which accidentally left an undefined "extensionjs_path"
error. Fix that error.

https://bugzilla.gnome.org/show_bug.cgi?id=661623
2011-10-20 15:38:02 -04:00
0dd4584157 st-texture-cache: Rearrange code to prevent some work and a memory leak
For some reason, the texture cache decides to make a request and then look up
an icon in the icon theme. If it's valid, it just returns, fine, but if it
doesn't add the icon, it tries to undo the request, leaking an
AsyncTextureLoadData that isn't freed in the process.

https://bugzilla.gnome.org/show_bug.cgi?id=660968
2011-10-20 15:26:41 -04:00
b7bf712b97 st-texture-cache: Merge strategies
Rather than have five or six structs allocated duplicating data,
just keep one and simplify the code considerably.

Again, part of my ongoing quest to merge St and Mx.

https://bugzilla.gnome.org/show_bug.cgi?id=660968
2011-10-20 15:19:00 -04:00
615723d8df IMStatusChooserItem: clean up signal handlers on destroy()
Extensions (like alternative-status-menu) expect that calling
destroy() on a menu item will not leave signal handlers around.

https://bugzilla.gnome.org/show_bug.cgi?id=660520
2011-10-20 15:06:52 +02:00
de352a309d global: drop incorrect memset
shell_global_get_memory_info tries to zero initialize the output
parameter with memset, but it passes the wrong size (because of
a missing *).  There's no reason to do the memset, though. In the
normal case all members of the struct gets initialized before the
function returns anyway.

This commit drops the memset call in favor of one explicit 0 assignment
that only gets executed on on atypical platforms.

https://bugzilla.gnome.org/show_bug.cgi?id=662236
2011-10-19 17:13:20 -04:00
c573e7f9a1 global: add missing break statement
Just a drive by fix.

https://bugzilla.gnome.org/show_bug.cgi?id=662235
2011-10-19 17:13:20 -04:00
d59fd1a75d Updated Norwegian bokmål translation 2011-10-19 22:42:59 +02:00
18d69d7032 util: don't depend on the nautilus GSettings schema
Without the desktop, even Nautilus hardcodes "Home" in all places
nowadays (except for the desktop itself). I think a run-time dependency
on nautilus being installed (GSettings will abort if the schema is not
found) is not worth it to keep compatibility with the desktop.

(Also, nautilus itself could probably hardcode "Home" for the desktop as
well and remove the preference).

https://bugzilla.gnome.org/show_bug.cgi?id=659895
2011-10-19 15:37:08 -04:00
5d25716cee st-texture-cache: Use ANSI C-style comments
https://bugzilla.gnome.org/show_bug.cgi?id=660968
2011-10-19 12:40:44 -04:00
840e79c18c Updated Vietnamese translation 2011-10-19 19:39:39 +11:00
ddf562e306 po/vi: import from Damned Lies 2011-10-19 19:39:38 +11:00
20a6ce7003 build: Switch to glib master 2011-10-19 00:26:06 +02:00
8c43298af0 configure: Bump glib requirement
Commit 338ba10ca2 uses unstable API, so adjust the required min version.
2011-10-18 23:51:39 +02:00
4bb48e56d2 Drop deprecated g_thread_init call
GThread will automatically initialize at program start now.

https://bugzilla.gnome.org/show_bug.cgi?id=662011
2011-10-18 16:13:55 -04:00
338ba10ca2 shell-recorder-src: Statically init mutexes instead of using the deprecated API
https://bugzilla.gnome.org/show_bug.cgi?id=662011
2011-10-18 16:13:50 -04:00
36eb745ecc PlacesManager: fix .gtk-bookmarks monitor scope
The GFileMonitor on ~/.gtk-bookmarks was block-scoped in the
PlacesManager._init() function, which caused it to be destroyed as soon
as the constructor was done. This caused changes in bookmarks to never
be notified to possible watchers (such as the places-menu extension).
To fix this, the 'monitor' variable has been promoted to an object
instance member.

https://bugzilla.gnome.org/show_bug.cgi?id=661921
2011-10-18 14:03:36 -04:00
b07e45e214 lookingGlass: Add an easier way to see extension errors
Use the extensions tab to show errors belonging to each extension.

https://bugzilla.gnome.org/show_bug.cgi?id=660546
2011-10-18 13:13:48 -04:00
bba5198e63 Updated Spanish translation 2011-10-18 16:13:19 +02:00
9e2bab008a Updated Norwegian bokmål translation 2011-10-18 07:48:09 +02:00
5ea032bbf7 Bump version to 3.2.1
Update NEWS
2011-10-18 00:23:51 -04:00
897fadfb40 Require Mutter 3.2.1
This is needed for meta_display_unmanage_screen()
2011-10-18 00:19:32 -04:00
b05f71eb9b messageTray: Add banner body when setting the image for a notification
We always place the banner in the body if the notification has additional
content.

https://bugzilla.gnome.org/show_bug.cgi?id=659158
2011-10-18 00:16:25 -04:00
4ce0e80956 user-menu: Be more cautious about saving status
When requesting a presence change, the actual presence set by
mission control does not necessarily match the requested presence
(if an active account does not support the requested presence),
which may result in the wrong presence being restored.
As a fix, be more cautious about saving status by assuming that
users do not request presence changes between an automatic presence
change request and the actual change.

https://bugzilla.gnome.org/show_bug.cgi?id=661485
2011-10-18 04:25:57 +02:00
577ccc4d56 Unmanage the screen before reexecing
This ensures a 'clean shutdown' of mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=660848
2011-10-17 21:55:13 -04:00
39d12351ba gdm: move focus to first item in list
This allows the user to just hit when the user
list first comes up (in many cases).

https://bugzilla.gnome.org/show_bug.cgi?id=657996
2011-10-17 20:49:04 -04:00
e37bc6d7f0 Updated Galician translations 2011-10-18 00:05:07 +02:00
9593ff3582 notificationDaemon: only display a large image if an icon is also specified
Historically, when applications set "image-data" they expect it to show up
as an icon. So we display it as such if an icon is not specified with an
"app_icon" argument to Notify(). We also use "image-path" for an icon if
an icon is not specified.

We only display a large image specified with "image-data" or "image-path"
if an icon is also specified.

https://bugzilla.gnome.org/show_bug.cgi?id=659158
2011-10-17 17:53:16 -04:00
ad8dfd7b04 Updated Hungarian translation 2011-10-17 23:44:33 +02:00
ca5ab20f67 gdm: don't clear bullets while authenticating
Users don't expect the bullets they just typed into an entry
field to disappear as soon as they hit enter.

Instead, they want the dialog to become insensitive during the
authentication process, so that it's clear that what they typed
in is being processed.

https://bugzilla.gnome.org/show_bug.cgi?id=657894
2011-10-17 17:37:06 -04:00
0eab448221 css: Style the capslock warning in password entries
https://bugzilla.gnome.org/show_bug.cgi?id=660806
2011-10-17 22:43:47 +02:00
a26a77f9db st-entry: Display a capslock warning in password entries
Implement the GtkEntry behavior of showing a warning icon when
capslock is turned on while entering hidden text.

https://bugzilla.gnome.org/show_bug.cgi?id=660806
2011-10-17 22:43:47 +02:00
c3df6bb8bd [l10n] Updated German translation 2011-10-17 22:07:46 +02:00
ce3a26cf37 Updated Polish translation 2011-10-17 22:04:00 +02:00
04482c23c4 Updated POTFILES.in 2011-10-17 22:02:37 +02:00
ff20fe856e keyboard: show the keyboard immediately when the user toggles it on
Enabling the keyboard currently doesn't give much notification. Make
it so that the keyboard shows right away when it first gets turned on.

https://bugzilla.gnome.org/show_bug.cgi?id=659743
2011-10-17 14:55:17 -04:00
12e3921f81 messageTray: only set stage input mode when necessary
The message tray focus grabbing code sets the stage input
mode to Shell.StageInputMode.FOCUSED when the overview is
not visible. This ensures the stage window's input
region gets reshaped to include the notification chrome,
and so that input events get delivered appropriately to
the notification that grabbed focus.

The message tray code never tries to restore the stage input
mode later. Instead, the code relies on the stage input
mode (and input region) getting reset to
shell.StageInputMode.NORMAL automatically when focus moves
back from the shell chrome to a window in the user's session.

It's not really correct to set the stage input mode based
on the overview's visibility, though. At the login screen,
even though no overview is visible, the stage input mode is
Shell.StageInputMode.FULLSCREEN which is sufficient
for the notification's needs,  Furthermore,
Shell.StageInputMode.FOCUSED is insufficient for the login
dialog's needs since the login dialog isn't considered
part of the shell's chrome and won't get included in the
stage input region.

This commit changes the message tray code to only set the
stage input mode if the current stage input mode isn't good enough,
rather than assuming the input mode isn't good enough just because
the overview is hidden.

https://bugzilla.gnome.org/show_bug.cgi?id=660919
2011-10-17 13:24:12 -04:00
928fbee15b altTab: fix app ordering in certain edge cases
Because we were sorting the Alt+Tab list by user_time rather than
stacking order / MRU, it was possible for the currently-focused window
to sometimes not be the first app in the list. Fix this by using
meta_display_get_tab_list() to get the proper MRU ordering of windows
on the current workspace, and then convert that to an ordered list of
apps.

https://bugzilla.gnome.org/show_bug.cgi?id=645026
2011-10-17 12:54:03 -04:00
a103c028f9 gdm: add prelight to Not Listed? button
The prelight makes it clearer that the button is
clickable, and makes it more consistent with other
clickable parts of the dialog.

https://bugzilla.gnome.org/show_bug.cgi?id=659763
2011-10-17 11:55:46 -04:00
775347d865 Updated Japanese translation 2011-10-18 00:54:05 +09:00
6d0be86a4e dash: Add minor optimization to _adjustIconSize()
In case _adjustIconSize() is called while the the dash icons are
animating, some extra work is required to yield the expected result.
Skip those extra steps when the icons are not actually animating.

https://bugzilla.gnome.org/show_bug.cgi?id=649248
2011-10-17 16:07:52 +02:00
a4b69db8af dash: Rework _adjustIconSize()
The current code uses the dash's height and current icon size to
calculate the new icon size. However, the height does not correctly
relate to the icon size while the icons are animating, in which
case the resulting icon size may be wrong.
Rework the function to be independent from the actual icon sizes,
so that a correct size is calculated even when called during an
animation.

https://bugzilla.gnome.org/show_bug.cgi?id=649248
2011-10-17 16:07:52 +02:00
790b9d3371 dash: Ignore hiding items in _adjustIconSize()
Rather than relying on the caller to hide the remove target and
removed items before calling _adjustIconSize(), move that logic
into _adjustIconSize() itself.

https://bugzilla.gnome.org/show_bug.cgi?id=649248
2011-10-17 16:07:52 +02:00
adef2009a5 Revert "dash: Ignore hiding items in _adjustIconSize()"
Ooops, a patch got lost in rebase.

This reverts commit b07f9932db.
2011-10-17 16:01:19 +02:00
1721db6d8d Revert "dash: Add minor optimization to _adjustIconSize()"
Ooops, a patch got lost in rebase ...

This reverts commit 6d95e8b988.
2011-10-17 16:00:52 +02:00
6d95e8b988 dash: Add minor optimization to _adjustIconSize()
In case _adjustIconSize() is called while the the dash icons are
animating, some extra work is required to yield the expected result.
Skip those extra steps when the icons are not actually animating.

https://bugzilla.gnome.org/show_bug.cgi?id=649248
2011-10-17 15:58:25 +02:00
b07f9932db dash: Ignore hiding items in _adjustIconSize()
Rather than relying on the caller to hide the remove target and
removed items before calling _adjustIconSize(), move that logic
into _adjustIconSize() itself.

https://bugzilla.gnome.org/show_bug.cgi?id=649248
2011-10-17 15:58:16 +02:00
9439da81c4 Add context menus to some entries
Use ShellEntry.addContextMenu() to add context menus to most
existing entries, with the exception of:

 - the login dialog - it may act be used to enter either the
                      username (e.g. no password entry) or the
                      password, and copy/paste does not make sense
                      (nowhere to copy from, nowhere to paste to)
 - notifications    - while adding a context menu is useful here as
                      well, it will require changes to the tray's
                      focus grab handling, so leave those entries
                      out for now

https://bugzilla.gnome.org/show_bug.cgi?id=659275
2011-10-17 15:29:32 +02:00
6257e64d03 shell-entry: Add API to support entry context menus
Add addContextMenu() to support context menus on right-click/long-press.
Depending on the parameters passed, the context menu only contains
"Copy"/"Paste" actions or an additional "Show/Hide Text" toggle action
for password entries.

https://bugzilla.gnome.org/show_bug.cgi?id=659275
2011-10-17 15:29:32 +02:00
ba110f2d2e network-agent: Remove "Show password" switch
While the ability to show the password can be useful at times,
the existing implementation is problematic:

  1) The use of a switch is wrong (as even noted in a code
     comment).

  2) It is inconsistent with any other password dialog (login screen,
     polkit).

In lack of a properly designed solution (for all password dialogs),
the designers agreed to remove the switch for now.

https://bugzilla.gnome.org/show_bug.cgi?id=658948
2011-10-17 15:29:32 +02:00
6bdf621d05 Fixed some strings in Brazilian Portuguese translation 2011-10-17 10:38:23 -02:00
1c4db98c95 added Kurdish translation 2011-10-17 14:28:49 +02:00
dadac957e4 updated Kurdish translation 2011-10-17 13:38:39 +02:00
cf3976d496 l10n: updated Italian translation 2011-10-17 10:31:24 +02:00
82ed80c9c3 extensionSystem: Load user extensions after system ones
https://bugzilla.gnome.org/show_bug.cgi?id=661815
2011-10-16 14:54:17 -04:00
67222525ad Updated Korean translation 2011-10-17 03:00:56 +09:00
fff0861773 Updated French translation 2011-10-16 12:50:22 +02:00
13ffe41498 Updated Persian translations 2011-10-15 16:05:29 +03:30
96e0528a7b Updated Bulgarian translation 2011-10-15 10:43:14 +03:00
3df30fbd57 Updated Bulgarian translation 2011-10-15 10:00:14 +03:00
b57d8b336b Updated British English translation 2011-10-14 19:12:28 +01:00
3169b2c440 keyboard: fix the keyboard hiding when an extended key is selected
Add a corner case for when the extended key is clicked in order to stop the keyboard
from prematurely closing.

https://bugzilla.gnome.org/show_bug.cgi?id=661707
2011-10-13 16:12:16 -04:00
6bc34e0f32 shell-app: Plug a small memory leak 2011-10-13 22:09:39 +02:00
cecb1a41fb st-texture-cache: Fix a minor crash when computing our border-radius
If we add a 0-sized actor with a border-radius, we will crash as we try to
allocate a 0-sized texture in Cogl. Bail out early instead of doing that.

https://bugzilla.gnome.org/show_bug.cgi?id=661617
2011-10-13 14:15:18 -04:00
b9069df85c search: fix keyboard hiding when user starts a new search
The keyboard hides prematurely when the user is typing into
an empty search box because the click is a captured event that
triggers a loss of entry focus. By adding a keyboard check to
this event, the problem is solved.

https://bugzilla.gnome.org/show_bug.cgi?id=661340
2011-10-13 14:12:21 -04:00
aee3c6f041 shell-app: Remove MATCH_MULTIPLE_{PREFIX,SUFFIX}
We originally OR'ed search terms and favored results which matched
multiple times to get more relevant results. When changing search
to AND search terms, the semantics of "multiple matches" were
changed to refer to a single term matching multiple criteria (name,
executable), which seemed like a good idea at the time.

However in practice this just results in applications whose
user-visible name matches the executable name on disk being
favored over applications using a more generic name, which
isn't too useful (in particular when taking usage frequency
into account).

https://bugzilla.gnome.org/show_bug.cgi?id=623372
2011-10-13 17:46:45 +02:00
c427bba9f1 shell-app: Improve prefix matches
Currently we use a very strict definition of "prefix", where the
search term has to match at the very beginning of the searched
criteria (application name, executable name). Use a more liberal
definition by including matches where the preceding character is
a space (application name) or hyphen (executable name) as well;
as many applications use a prefix, this should improve the quality
of results.

https://bugzilla.gnome.org/show_bug.cgi?id=623372
2011-10-13 17:46:45 +02:00
da83ad561b app-system: Consider usage frequency in search results
Application search results are internally categorized in four sets,
multiple and single prefix matches and multiple and single substring
matches. Each set is currently sorted alphabetically by application
name when concatenating the sets to the final result.
Change the last step to sort each set by usage frequency instead,
which is more likely to favor the most relevant match than
"arbitrary" alphabetic order.

https://bugzilla.gnome.org/show_bug.cgi?id=623372
2011-10-13 17:46:45 +02:00
85520e34ab popup-menu: Allow adjusting where in the source the arrow points to
Currently BoxPointer/Menus always point to the center of the
associated source actor. This is generally what we want, but
add some API to adjust that behavior for the cases where it
isn't.

https://bugzilla.gnome.org/show_bug.cgi?id=659274
2011-10-13 15:03:32 +02:00
d0edd970e1 gdm: clean up spacing
There's a lot of dead vertical space right now from
the session list, even if there are no sessions.

This commit mops that up.

https://bugzilla.gnome.org/show_bug.cgi?id=661479
2011-10-11 17:27:42 -04:00
8529ca70af gdm: don't show fingerprint message right away
Right now we show "(or swipe finger)" at the user login prompt
any time we detect a fingerprint reader.

Checking for the presense of a fingerprint reader isn't really
sufficient for knowing if it is appropriate or not to show the
message, though. Often, a user's fingerprint won't be enrolled
in the system even if the machine has a fingerprint reader.

In this scenario, we end up in a situation where the code will
fade out the message right after fading it in, or worse, fade
out the message while fading it in.

The former case looks flickery and bad, and the latter case
causes the login dialog to lock up since it never completes its
"show prompt" animation and we don't procede with the login
process until after that animation.

If a user is enrolled in the system, the fingerprint pam module
tries to tell the user to swipe their finger.  We never show the
user that message because it's redundant with our own "(or swipe
finger)" message and because it uses techy words like "UPEK" and
"TouchStrip".

This commit changes the code to defer showing "(or swipe
finger)" until the fingerprint pam module forwards us its own
message. This makes it less likely we'll show the message when
fingerprint login won't work, and also removes the fingerprint
animation from the critical path "show prompt" animation.

https://bugzilla.gnome.org/show_bug.cgi?id=660492
2011-10-11 17:25:44 -04:00
1a8d78212f layoutManager: Ignore 1px overlap in _isAboveOrBelowPrimary()
Nvidia's twin view option does not align monitors properly, but with
a one pixel overlap. It looks safe to ignore an overlap this small
to make this case work.

https://bugzilla.gnome.org/show_bug.cgi?id=661387
2011-10-11 16:20:12 +02:00
4270a2806d Updated Hungarian translation 2011-10-11 16:12:28 +02:00
4333bdc709 *.[ch]: add emacs modeline to C files that were missing it
(excluding files that are synced from another module)

https://bugzilla.gnome.org/show_bug.cgi?id=660358
2011-10-11 08:05:17 -04:00
75b824d032 *.js: Make emacs modelines consistent
js2-mode is no longer developed and we recommend js-mode these days,
so switch the modelines to specify that, and make them consistent
across all files.

https://bugzilla.gnome.org/show_bug.cgi?id=660358
2011-10-11 08:05:12 -04:00
7bc2573d85 window-clone: Use ClutterClickAction
Right-click menus in the dash can be dismissed by clicking anywhere
outside the menu. However, if a window clone is located beneath the
pointer when doing so, the window is activated and the overview
closed.
The cause of this unexpected behavior is that window previews are
activated on button-release, which is delivered to the preview after
the menu releases its grab on button-press. Use a ClutterClickAction
instead and let Clutter do the right thing, i.e. only trigger a
'clicked' signal when a button-release event is matched by a
corresponding button-press event.

https://bugzilla.gnome.org/show_bug.cgi?id=661151
2011-10-11 12:56:34 +02:00
67b7b7a950 shell-util: Fix a bogus annotation
Creating a new instance is not (transfer none), unless I'm missing
somehting here...

https://bugzilla.gnome.org/show_bug.cgi?id=661231
2011-10-11 00:07:31 -04:00
786cfbd397 shell-util: Remove shell_util_icon_from_string
GJS doesn't need to be able to represent interfaces for you to be able to
access an interface method, so Gio.icon_new_for_string works fine.

https://bugzilla.gnome.org/show_bug.cgi?id=661231
2011-10-11 00:07:31 -04:00
9df8b583cf Updated Telugu Translations 2011-10-10 16:53:43 +05:30
8e32290dc9 Change default of saved-im-presence to Offline
Unset is not a valid presence type so the Shell shouldn't try setting it when
starting for the first time.

https://bugzilla.gnome.org/show_bug.cgi?id=661272
2011-10-09 15:23:59 -04:00
23478f3336 Updated Lithuanian translation 2011-10-09 00:40:32 +03:00
2e244ecb63 Updated Latvian translation. 2011-10-08 22:48:44 +03:00
e307680206 [l10n] Updated German translation 2011-10-08 20:38:19 +02:00
6bb1a3e2c4 Updated Russian translation 2011-10-08 11:34:28 +04:00
8a1ac6b13f Updated Dutch translation by Wouter Bolsterlee 2011-10-08 02:04:37 +02:00
61b8af2252 Add translator comment for button label 2011-10-08 01:50:20 +02:00
c99afed012 messageTray: Fix accidental typo 2011-10-07 16:34:04 -04:00
2947b92148 user-menu: Restore previous session presence at startup
Save the session presence in GSettings and restore it on startup.

https://bugzilla.gnome.org/show_bug.cgi?id=659021
2011-10-07 07:24:21 +02:00
39c5d23a87 user-menu: Restore previous IM presence on startup
Move the saved user-set presence to GSettings, so it is preserved
between logins.

https://bugzilla.gnome.org/show_bug.cgi?id=659021
2011-10-07 07:24:21 +02:00
d839670f54 Updated Spanish translation 2011-10-06 23:39:36 +02:00
0d1b7e15d1 Updated Swedish translation 2011-10-06 08:09:28 +02:00
ac678f63ee Updated Galician translations 2011-10-06 02:52:18 +02:00
d862c0879b telepathyClient: Check for a no-op before pushing an alias change message
tp-glib can sometimes emit a notify::alias signal when the alias doesn't
actually change. Bail out early instead of pushing an alias change message.

https://bugzilla.gnome.org/show_bug.cgi?id=660774
2011-10-05 15:34:40 -04:00
23a4d4c69e texture-cache: Don't share requests for uncachable textures
Make create_texture_and_ensure_request() aware of the caching
policy to avoid returning the same texture for different
images.

https://bugzilla.gnome.org/show_bug.cgi?id=660585
2011-10-05 21:30:27 +02:00
472b20d933 ShellContactSystem: Make address search actually work
The code was not dealing properly with what folks returns
for im and email addresses.

https://bugzilla.gnome.org/show_bug.cgi?id=660925
2011-10-05 20:26:39 +02:00
492dd718fb ShellContactSystem: make search terms conjunctive
Require that all terms match. This is the expected behaviour
and matches what gnome-contacts does. Keep the prefix/infix
weights in place for now.

https://bugzilla.gnome.org/show_bug.cgi?id=660912
2011-10-05 20:26:38 +02:00
0d5618fdd1 contact-display: Try harder to display a meaningful name
We now match individuals on other properties than alias, so take
this into account when representing a contact in search results
to avoid having them show up as "Unknown".

https://bugzilla.gnome.org/show_bug.cgi?id=660580
2011-10-05 20:26:38 +02:00
503508af41 contact-system: Add helper method to get a (display) email
Folks uses collection/set objects from libgee to store email addresses
associated with an individual. Unfortunately to extract addresses, parts
of libgee which are unusable from (introspected) bindings have to be
used[0], so add a helper method.

[0] in particular gee_iterator_get(), which is annotated as
    "return: (transfer full): gpointer"

https://bugzilla.gnome.org/show_bug.cgi?id=660580
2011-10-05 20:26:38 +02:00
4ec5e55122 Move shell contacts search closer to gnome-contacts
Match folks' name and nick fields, in addition to alias,
and look at email addresses in addition to im addresses.
This is more in line with what gnome-contacts does.

To match this new usage, rename the ALIAS_..._WEIGHT and
IM_..._WEIGHT constants to NAME_ and ADDR_, respectively.

https://bugzilla.gnome.org/show_bug.cgi?id=660580
2011-10-05 20:26:38 +02:00
8daca865ca Updated Slovenian translation 2011-10-05 19:59:01 +02:00
f9b37a21e8 StThemeNodeDrawing: Remove useless LoadCornerData
Done as part of my quest to merge Mx and St:

https://github.com/magcius/mx/tree/st-rebase

https://bugzilla.gnome.org/show_bug.cgi?id=660968
2011-10-05 12:24:28 -04:00
c398f319fc [l10n]Updated Catalan translation 2011-10-04 23:30:47 +02:00
1e049f88b8 Updated Polish translation 2011-10-04 23:25:07 +02:00
4831d9c3a3 lookingGlass: Fix referencing undefined variables 2011-10-04 16:50:58 -04:00
f13f5bc1bb Use '' for non-translated strings
Pay attention to the style guidelines.

https://bugzilla.gnome.org/show_bug.cgi?id=660600
2011-10-04 16:47:53 -04:00
4e114107ed keyboard: Add a missed translation
The word "tray" should be translated to other languages.

https://bugzilla.gnome.org/show_bug.cgi?id=660600
2011-10-04 16:47:53 -04:00
0ccb280008 st-theme-node-drawing: Fix centering when the image needs to be scaled
The translate coordinates are calculated as the offset after the scale, so it
needs to be applied after the scale as well. This fixes random centering issues
in the UI.

https://bugzilla.gnome.org/show_bug.cgi?id=660674
2011-10-04 15:46:01 -04:00
28c3e0693e workspaces-view: Remove window dnd between workspaces
When workspace "previews" in the overview were just tiny gray
rectangles, it made sense to provide a way to move windows
directly between workspaces (by switching workspaces when dragging
a window to the corresponding screen edge). As the overview has
evolved however, the workspace switcher provides a good and
intuitive drop target already, so the alternative provided by the
screen edges is no longer necessary. As it also conflicts with
moving windows between monitors when using a vertical layout,
just remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=660838
2011-10-04 20:30:20 +02:00
c321c8a02f Updated Polish translation 2011-10-04 20:09:02 +02:00
2407ec7b47 Revert "lookingGlass: Add an easier way to see extension errors"
This reverts commit 1e6b824ede.
2011-10-04 13:15:10 -04:00
70eeb75716 lookingGlass: Show extension state in gnome-shell
We translate and create an actor to show the extension state, but we never
actually add it anywhere. Fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=660494
2011-10-04 13:14:54 -04:00
751d250471 autorun: fix a typo in a variable name
The variable |type| doesn't exist here; what we want to do is using the
first member of the contentTypes array instead.
Probably a leftover of some refactoring of the code I did while working
on this.

This patch fixes starting of the default application for a given content
type if the control-center panel is set to run it when a device is
plugged.

https://bugzilla.gnome.org/show_bug.cgi?id=660821
2011-10-03 16:34:59 -04:00
c28217db80 Updated Esperanto translation 2011-10-03 20:40:41 +02:00
0968e556fa WindowDimmer: Make effect private
There is no need for making this public as it is only accessed from within
WindowDimmer.
2011-10-03 18:22:58 +02:00
130f2cf808 WindowDimmer: Don't try to use a ShaderEffect when GLSL is not available
This obviously won't work anyway but will just spam stderr with warnings,
so don't do it.
2011-10-03 18:22:47 +02:00
4eec7413c7 Revert "lookingGlass: Show extension state in gnome-shell"
This reverts commit 32dc24c59b, as it caused
a string break.

https://bugzilla.gnome.org/show_bug.cgi?id=660494
2011-10-02 12:05:21 -04:00
efc3246d26 Updated Bulgarian translation 2011-10-02 13:52:37 +03:00
9930dbc0ff Updated Galician translations 2011-10-02 00:24:03 +02:00
754f87dac3 Updated Swedish translation 2011-10-01 21:57:10 +02:00
51139bd096 Updated Irish translation 2011-10-01 13:26:46 -06:00
6e0119d620 Updated Irish translation 2011-10-01 13:16:56 -06:00
a3528bf973 layout: Fix the actor tracking parameter parsing
It's not appropriate to inherit from the parent property if we pass "false"
as a value, especially when all current parameters are booleans.

https://bugzilla.gnome.org/show_bug.cgi?id=660608
2011-10-01 14:41:53 -04:00
77c36af588 [l10n]Updated Catalan (Valencian) translation 2011-10-01 16:04:25 +02:00
69c0a52a33 [l10n]Updated Catalan translation 2011-10-01 16:04:18 +02:00
a7442cd0a5 Updated Vietnamese translation 2011-10-01 10:31:24 +10:00
d47a013931 vi.po: import from Damned Lies 2011-10-01 10:29:31 +10:00
745f9c0e6e Added asturian language 2011-09-30 21:04:02 +02:00
414f49fd80 Updated asturian translation 2011-09-30 21:02:57 +02:00
e49a595f54 st-texture-cache: Don't cache GIcons which cannot be serialized
For GIcons we use g_icon_to_string() in the key, but the function
will return NULL if the icon cannot be serialized. As a result,
all non-serializable GIcons of the same size end up with the same
cache key - an example for this are contacts with avatars, which
currently all end up with the same image.
To fix, opt out of caching for GIcons which cannot be serialized.

https://bugzilla.gnome.org/show_bug.cgi?id=660585
2011-09-30 20:14:25 +02:00
77485c2a04 [l10n] Updated German translation 2011-09-30 20:07:51 +02:00
e9b28634e5 Updated Slovenian translation 2011-09-30 19:13:24 +02:00
b43dcb8876 layout: Fix setting fullscreen for screen sized windows
We have to set the flag for all monitors in that case.
2011-09-30 18:46:14 +02:00
f0c1eeece8 Updated Spanish translation 2011-09-30 18:27:07 +02:00
1e6b824ede lookingGlass: Add an easier way to see extension errors
Use the extensions tab to show errors belonging to each extension.

https://bugzilla.gnome.org/show_bug.cgi?id=660546
2011-09-30 12:19:30 -04:00
1e2d16273c layoutManager: Treat screen_sized OR windows as fullscreen
https://bugzilla.gnome.org/show_bug.cgi?id=660166
2011-09-29 21:38:05 +02:00
32dc24c59b lookingGlass: Show extension state in gnome-shell
We translate and create an actor to show the extension state, but we never
actually add it anywhere. Fix that.

https://bugzilla.gnome.org/show_bug.cgi?id=660494
2011-09-29 13:15:27 -04:00
7a8a189c48 boxpointer: Don't constrain box pointer to primary monitor
A boxPointer should be able to be attached to any actor, not just ones on the
primary monitor. Assume that the sourceActor doesn't straddle monitors, and
constrain the boxPointer to the monitor the sourceActor is on.

https://bugzilla.gnome.org/show_bug.cgi?id=659861
2011-09-29 13:15:01 -04:00
6aa411fecc keyboard: ignore D-Bus requests when the OSK isn't enabled
Fixes spurious warnings about "this.actor is null" when processing
org.gnome.Caribou.Keyboard messages when the keyboard isn't enabled.

https://bugzilla.gnome.org/show_bug.cgi?id=659940
2011-09-29 10:28:49 -04:00
9c76318df8 main: remove a stray second keyboard.init() call
Originally the keyboard was initialized in the user-session-specific
code, but it was later moved to the generic code. Except that it was
accidentally copied rather than moved.

https://bugzilla.gnome.org/show_bug.cgi?id=659940
2011-09-29 10:28:46 -04:00
6510904711 windowAttentionHandler: Remove "%s has finished starting"
The message is verbose and confusing. Use the traditional "'%s' is ready"
for all cases.

https://bugzilla.gnome.org/show_bug.cgi?id=660310
2011-09-29 09:59:09 -04:00
a9817f4832 automountManager: Don't mount already-mounted volumes
Don't pester the user with autorun popups if a volume is already mounted.

https://bugzilla.gnome.org/show_bug.cgi?id=660397
2011-09-28 16:51:02 -04:00
9067689839 power-status: Use correct DBus signatures
Devices are represented as susdut, not susbut (i.e. the percentage
is a double rather than a boolean) - apparently the wrong signature
works, but correct it anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=660122
2011-09-28 19:56:23 +02:00
4e9e91fdce recorder: Use CoglHandle instead of CoglHandle*
The latter has always been wrong and should have been fixed a
while ago, but somehow we overlooked shell-recorder.

https://bugzilla.gnome.org/show_bug.cgi?id=659822
2011-09-28 19:56:23 +02:00
73cc91ba60 update zh_CN translation 2011-09-28 01:01:12 +08:00
0ab0d0860f Uploaded Ukranian 2011-09-27 14:56:16 +03:00
337b399a75 Updated Serbian translation 2011-09-27 02:47:53 +02:00
46f21e81e3 updated Tamil translation 2011-09-27 05:14:59 +05:30
218 changed files with 20844 additions and 11073 deletions

13
.gitignore vendored
View File

@ -21,6 +21,19 @@ data/gnome-shell.desktop.in
data/gschemas.compiled
data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid
docs/reference/*/*.args
docs/reference/*/*.bak
docs/reference/*/*.hierarchy
docs/reference/*/*.interfaces
docs/reference/*/*.prerequisites
docs/reference/*/*.sgml
docs/reference/*/*.signals
docs/reference/*/*.stamp
docs/reference/*/*.txt
docs/reference/*/*.types
docs/reference/*/html/
docs/reference/*/xml/
gtk-doc.make
js/misc/config.js
intltool-extract.in
intltool-merge.in

View File

@ -1,7 +1,7 @@
# Point to our macro directory and pick up user flags from the environment
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS = data js src browser-plugin tests po man
SUBDIRS = data js src browser-plugin tests po man docs
EXTRA_DIST = \
.project \
@ -19,3 +19,5 @@ DIST_EXCLUDE = \
distcheck-hook:
@echo "Checking disted files against files in git"
@$(srcdir)/tools/check-for-missing.py $(srcdir) $(distdir) $(DIST_EXCLUDE)
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

129
NEWS
View File

@ -1,3 +1,132 @@
3.3.2
=====
* Port D-Bus usage in the shell to GDBus [Giovanni, Marc-Antoine, Florian,
Jasper, Matthias; #648651, #658078, #663902, #663941]
* Message tray
- Add right-click option to chats to mute the conversation [Ana; #659962]
- Don't steal the focus when popping up under the pointer [Rui; #661358]
* Looking Glass
- Add alt-Tab completion [Jason; #661054]
- Show errors from extensions in the extensions tab [Jasper; #660546]
- Allow switching tabs with <Control>PageUp/PageDown
- Theme consistently with the rest of the shell [Jason; 650900]
* Extension system
- Don't try to load disabled extensions at all [Jasper; #661815, #662704]
- Enable and disable plugins in a consistent order [Jasper; #661815, #662704]
- Add options to enable/disable extensions to gnome-shell-extension-tool
[Jasper; #661815]
* Adapt to Mutter change to GSettings [Florian, Matthias; #663429]
* Allow creating a new workspace by dragging a window or launcher in the
middle of two existing ones [Jasper; #646409]
* Allow using Alt-Tab while during drag-and-drop and other operations
that grab the pointer [Adel; #660457]
* Do a better job of finding the right user to authenticate
as when showing a PolKit dialog [Matthias; #651547]
* Control the D-Bus Eval() method by the developer-tools GSetting which
is used for looking glass and screen recorder. [Jasper; #662891]
* Fix browser plugin to work under WebKit-based browser [Jasper; #663823]
* Fix certain stacking issues with alt-Tab [Jasper; #660650]
* Fixes for GLib deprecations [Jasper; #662011]p
* Fixes for GTK+ deprecations [Florian, Rico; #662245]p
* Fixes for Clutter deprecations [Jasper; #662627]
* Visual improvements and UI tweaks [Florian, Jakub, Jasper;
#662800, #658096, #662226]
* Hard-code "Home" as the name for the home dir, rather than looking
it up via GSettings; avoids schema dependency [Cosimo; #559895]
* Don't show "Switch User" on single user machines [Florian; #657011]
* Generate documentation for St toolkit [Florian]
* Improve marking of strings for translation [Matthias, Piotr; #658664]
* Networking menu bug fixes [Giovanni; #650007, #651378, #659277, #663278]
* Code cleanups and leak fixes to StTextureCache
[Jasper, Florian; #660968, #662998]
* Code cleanups [Adel, Florian, Jasper; #662238, #663584]
* Build fixes [Adel, Colin, Florian, Ming Han]
* Misc bug fixes [Adel, Florian, "Fry", Jasper, Giovanni, Ray, Rui, Stefan;
#660520, #661029, #661231, #661623, #661921, #662235, #662236, #662502,
#662394, #662799, #662969, #663175, #663277, #663815, #663891, #662967]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Matthias Clasen, Piotr Drąg, Adel Gadllah,
Rui Matos, Florian Müllner, Marc-Antoine Perennou, Ana Risteska,
Jason Siefken, Jakub Steiner, Ray Strode, Jasper St. Pierre, Ming Han Teh,
Rico Tzschichholz, Colin Walters, Stefan Zwanenburg
Translation:
Alexander Shopov [bg], Marek Černocký [cs], Mario Blättermann [de],
Kostas Papadimas [el], Bruce Cowan [en_GB], Kristjan Schmidt [eo],
Jorge González, Daniel Mustieles, Benjamín Valero Espinosa [es],
Mattias Põldaru [et], Arash Mousavi [fa], Ville-Pekka Vainio [fi],
Fran Diéguez [gl], Yaron Shahrabani [he], Hideki Yamane [ja],
Algimantas Margevičius [lt], Kjartan Maraas [nb], Daniel Nylander [se],
Matej Urbančič [sl], Praveen Illa [te], Muhammet Kara [tr],
Nguyễn Thái Ngọc Duy [vi], Cheng-Chia Tseng [zh_HK, zh_TW]
3.2.1
=====
* Restore the IM state on startup - if you were available in when you logged
out, then you'll be set available again when you log in.
[Florian; #65902, #661485]
* Improve searching for contacts in the overview: search more fields,
show a more meaningful name, require that all search terms match.
[Florian, Matthias; #660580]
* Improve search for applications in the overview: take frequency into
account and tweak match algorithm [Florian; #623372]
* Remove the "Show Password" switch from network password prompts, and
move the functionality to a right-click menu [Florian; #658948]
* Add context menus with Cut/Paste options to most entries [Florian; #659275]
* On screen keyboard:
- Show the keyboard immediately when it's turned enabled [Dan; #659743]
- Fix problem where keyboard would hide when starting to type
in the search entry [Nohemi; #661340]
- Fix problem with keyboard hiding when selected accented characters
[Nohemi; 661707]
* Login mode:
- Allow hitting Enter to select the first user [Ray; #657996]
- Fix flicker of a fingerprint prompt that could show up [Ray; #660492]
- Fix password bullets vanishing during login [Ray; #657894]
- Misc bug fixes and visual tweaks [Ray; #659763, #660919, #661479]
* Display a caps-lock warning in password entries [Florian; #660806]
* Show the state of installed extensions in Looking Glass [Jasper; #660494]
* Load user extensions after system ones [Jasper; #661815]
* Fix problem with many applications showing extra-large icons in
notifications [Marina; #659158]
* Fix a problem where alt-Tab had trouble tracking the current
application with certain applications such as Emacs. [Dan; #645026]
* Fix confusion between different users avatar images [Florian; #660585]
* Remove behavior where you could switch workspaces by bumping
a dragged window in the overview against a screen edge; it was
leftover and just confusing. [Florian; #660838]
* Fix long-standing bug where the Dash in the overview could end up mis-sized
and run off the screen [Florian; #649248]
* Fix automatic launching of applications when media is inserted
[Cosimo; #660821]
* Fix handling of vertically stacked monitors with NVIDIA drivers
[Florian; #661387]
* Translation marking fixes [Jasper, Wouter; #660600]
* Code cleanups and warning fixes [Adel, Dan, Florian, Jasper;
#659822, #659940, #660122, #660358, #660968, #661231]
* Small memory leak fixes [Florian, Jasper; #661231]
* Misc bug fixes [Adel, Florian, Jasper; #659274, #659861, #660166, #660310,
#660397, #660608, #660606, #660674, #660774. #660848, #661151, #661617]
Contributors:
Wouter Bolsterlee, Cosimo Cecchi, Matthias Clasen, Nohemi Fernandez,
Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode, Dan Winship,
Marina Zhurakhinskaya
Translations:
Tiffany Antopolski [eo], Xandru Armesto [ast], Alexander Shopov,
Ivaylo Valkov [bg], Gil Forcada [ca], Carles Ferrando [ca@valencia],
Mario Blättermann, Paul Seyfert [de], Bruce Cowan [en_GB],
Jorge González, Daniel Mustieles [es], Arash Mousavi [fa], Bruno Brouard [fr],
Seán de Búrca [ga], Fran Diéguez [gl], Gabor Kelemen [hu], Luca Ferretti [it],
Takayuki Kusano [ja], Changwoo Ryu [ko], Erdal Ronahi [ku],
Algimantas Margevičius [lt], Rudolfs Mazurs [lv], Wouter Bolsterlee [nl],
Piotr Drąg [pl], Adorilson Bezerra [pt_BR], Yuri Myasoedov [ru],
Matej Urbančič [sl], Daniel Nylander [sv], Miroslav Nikolić [sr, sr@latin],
Tirumurti Vasudevan [ta], Krishnababu Krothapalli [te], Daniel Korostil [uk],
Nguyễn Thái Ngọc Duy [vi], YunQiang Su [zh_CN]
3.2.0
=====
* Prevent the fallback on-screen keyboard from showing up while

View File

@ -47,8 +47,6 @@ typedef struct {
GDBusProxy *proxy;
} PluginData;
/* =============== public entry points =================== */
static NPNetscapeFuncs funcs;
static inline gchar *
@ -71,10 +69,7 @@ get_string_property (NPP instance,
goto out;
result_str = NPVARIANT_TO_STRING (result);
if (strlen (result_str.UTF8Characters) != result_str.UTF8Length)
goto out;
result_copy = g_strdup (result_str.UTF8Characters);
result_copy = g_strndup (result_str.UTF8Characters, result_str.UTF8Length);
out:
funcs.releasevariantvalue (&result);
@ -150,6 +145,8 @@ check_origin_and_protocol (NPP instance)
return ret;
}
/* =============== public entry points =================== */
NPError
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
{
@ -816,6 +813,11 @@ NPP_GetValue(NPP instance,
*(NPObject**)value = funcs.createobject (instance, &plugin_class);
break;
case NPPVpluginNeedsXEmbed:
*(bool *)value = TRUE;
break;
default:
;
}

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.2.0],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.3.2],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -36,10 +36,6 @@ AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",
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
@ -67,10 +63,10 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.7.5
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.29.18
MUTTER_MIN_VERSION=3.0.0
MUTTER_MIN_VERSION=3.3.2
FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.0.0
GIO_MIN_VERSION=2.29.10
GIO_MIN_VERSION=2.31.0
LIBECAL_MIN_VERSION=2.32.0
LIBEDATASERVER_MIN_VERSION=1.2.0
LIBEDATASERVERUI_MIN_VERSION=2.91.6
@ -80,13 +76,13 @@ POLKIT_MIN_VERSION=0.100
STARTUP_NOTIFICATION_MIN_VERSION=0.11
# Collect more than 20 libraries for a prize!
PKG_CHECK_MODULES(GNOME_SHELL, gio-2.0 >= $GIO_MIN_VERSION
gio-unix-2.0 dbus-glib-1 libxml-2.0
PKG_CHECK_MODULES(GNOME_SHELL, gio-unix-2.0 >= $GIO_MIN_VERSION
libxml-2.0
gtk+-3.0 >= $GTK_MIN_VERSION
folks >= $FOLKS_MIN_VERSION
libmutter >= $MUTTER_MIN_VERSION
gjs-internals-1.0 >= $GJS_MIN_VERSION
libgnome-menu-3.0 $recorder_modules gconf-2.0
libgnome-menu-3.0 $recorder_modules
gdk-x11-3.0 libsoup-2.4
clutter-x11-1.0 >= $CLUTTER_MIN_VERSION
clutter-glx-1.0 >= $CLUTTER_MIN_VERSION
@ -121,7 +117,6 @@ CFLAGS=$saved_CFLAGS
LIBS=$saved_LIBS
PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 gnome-desktop-3.0 >= 2.90.0 x11)
PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
PKG_CHECK_MODULES(TRAY, gtk+-3.0)
PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
PKG_CHECK_MODULES(DESKTOP_SCHEMAS, gsettings-desktop-schemas >= 0.1.7)
@ -131,6 +126,7 @@ PKG_CHECK_EXISTS([gnome-bluetooth-1.0 >= 3.1.0],
[BLUETOOTH_DIR=`$PKG_CONFIG --variable=applet_libdir gnome-bluetooth-1.0`
BLUETOOTH_LIBS=`$PKG_CONFIG --variable=applet_libs gnome-bluetooth-1.0`
AC_SUBST([BLUETOOTH_LIBS],["$BLUETOOTH_LIBS"])
AC_SUBST([BLUETOOTH_DIR],["$BLUETOOTH_DIR"])
AC_DEFINE_UNQUOTED([BLUETOOTH_DIR],["$BLUETOOTH_DIR"],[Path to installed GnomeBluetooth typelib and library])
AC_DEFINE([HAVE_BLUETOOTH],[1],[Define if you have libgnome-bluetooth-applet])
AC_SUBST([HAVE_BLUETOOTH],[1])
@ -179,11 +175,13 @@ AC_SUBST(GIRDIR)
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
AC_SUBST(TYPELIBDIR)
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
enable_compile_warnings=maximum)
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
@ -241,6 +239,12 @@ AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
AC_CONFIG_FILES([
Makefile
data/Makefile
docs/Makefile
docs/reference/Makefile
docs/reference/shell/Makefile
docs/reference/shell/shell-docs.sgml
docs/reference/st/Makefile
docs/reference/st/st-docs.sgml
js/Makefile
js/misc/config.js
src/Makefile

View File

@ -60,23 +60,14 @@ gschemas.compiled: $(gsettings_SCHEMAS:.xml=.valid)
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
shadersdir = $(pkgdatadir)/shaders
shaders_DATA = \
shaders/dim-window.glsl
install-data-local:
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(srcdir)/$(gconfschema_DATA)
EXTRA_DIST = \
gnome-shell.desktop.in.in \
$(menu_DATA) \
$(gconfschema_DATA) \
$(shaders_DATA) \
org.gnome.shell.gschema.xml.in

View File

@ -1,100 +0,0 @@
<gconfschemafile>
<schemalist>
<!-- Metacity overrides -->
<schema>
<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>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/windows/button_layout</key>
<applyto>/desktop/gnome/shell/windows/button_layout</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>: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/windows/edge_tiling</key>
<applyto>/desktop/gnome/shell/windows/edge_tiling</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>enable edge tiling when dropping windows on screen edges</short>
<long>
If enabled, dropping windows on vertical screen edges maximizes them
vertically and resizes them horizontally to cover half of the
available area. Dropping windows on the top screen edge maximizes them
completely.
This key overrides /apps/metacity/general/edge_tiling when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/theme</key>
<applyto>/desktop/gnome/shell/windows/theme</applyto>
<owner>gnome-shell</owner>
<type>string</type>
<default>Adwaita</default>
<locale name="C">
<short>Current theme</short>
<long>
The theme determines the appearance of window borders,
titlebar, and so forth.
This key overrides /apps/metacity/general/theme when
running GNOME Shell.
</long>
</locale>
</schema>
<schema>
<key>/schemas/desktop/gnome/shell/windows/workspaces_only_on_primary</key>
<applyto>/desktop/gnome/shell/windows/workspaces_only_on_primary</applyto>
<owner>gnome-shell</owner>
<type>bool</type>
<default>true</default>
<locale name="C">
<short>Workspaces only on primary monitor</short>
<long>
This key overrides /apps/mutter/general/workspaces_only_on_primary when
running GNOME Shell.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -16,8 +16,9 @@
<_summary>Uuids of extensions to enable</_summary>
<_description>
GNOME Shell extensions have a uuid property; this key lists extensions
which should be loaded. disabled-extensions overrides this setting for
extensions that appear in both lists.
which should be loaded. Any extension that wants to be loaded needs
to be in this list. You can also manipulate this list with the
EnableExtension and DisableExtension DBus methods on org.gnome.Shell.
</_description>
</key>
<key name="enable-app-monitoring" type="b">
@ -50,6 +51,14 @@
<default>[]</default>
<_summary>History for the looking glass dialog</_summary>
</key>
<key name="saved-im-presence" type="i">
<default>1</default>
<_summary></_summary>
</key>
<key name="saved-session-presence" type="i">
<default>0</default>
<_summary></_summary>
</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"/>
@ -133,4 +142,40 @@
</_description>
</key>
</schema>
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/">
<key name="attach-modal-dialogs" type="b">
<default>true</default>
<summary>Attach modal dialog to the parent window</summary>
<description>
This key overrides the key in org.gnome.mutter when running
GNOME Shell.
</description>
</key>
<key name="button-layout" type="s">
<default>":close"</default>
<summary>Arrangement of buttons on the titlebar</summary>
<description>
This key overrides the key in org.gnome.desktop.wm.preferences when
running GNOME Shell.
</description>
</key>
<key name="edge-tiling" type="b">
<default>true</default>
<summary>Enable edge tiling when dropping windows on screen edges</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
<key name="workspaces-only-on-primary" type="b">
<default>true</default>
<summary>Workspaces only on primary monitor</summary>
<description>
This key overrides the key in org.gnome.mutter when running GNOME Shell.
</description>
</key>
</schema>
</schemalist>

View File

@ -98,8 +98,12 @@
color: #666666;
}
.login-dialog-not-listed-button:hover .login-dialog-not-listed-label {
color: white;
}
.login-dialog-prompt-layout {
padding-bottom: 64px;
padding-bottom: 32px;
}
.login-dialog-prompt-label {
color: white;
@ -117,6 +121,16 @@
width: 15em;
}
.login-dialog-prompt-entry .capslock-warning {
icon-size: 16px;
warning-color: #999;
}
.login-dialog-prompt-entry:insensitive {
color: rgba(0,0,0,0.7);
border: 2px solid #565656;
}
.login-dialog-session-list {
color: #ffffff;
font-size: 10.5pt;

View File

@ -36,18 +36,18 @@ stage {
StScrollBar
{
padding: 0px;
padding: 0px;
}
StScrollView.vfade
{
-st-vfade-offset: 68px;
-st-vfade-offset: 68px;
}
StScrollView StScrollBar
{
min-width: 16px;
min-height: 16px;
min-width: 16px;
min-height: 16px;
}
@ -509,8 +509,9 @@ StTooltip StLabel {
width: 60px;
}
.dash-placeholder {
.placeholder {
background-image: url("dash-placeholder.svg");
height: 24px;
}
#viewSelector {
@ -742,24 +743,24 @@ StTooltip StLabel {
}
.contact-icon {
border-radius: 4px;
border-radius: 4px;
}
.contact-details {
padding: 6px 8px 11px 8px;
padding: 6px 8px 11px 8px;
}
.contact-details-alias {
font-size: 16px;
padding-bottom: 11px;
font-size: 16px;
padding-bottom: 11px;
}
.contact-details-status {
font-size: 11pt;
font-size: 11pt;
}
.contact-details-status-icon {
padding-right: 2px;
padding-right: 2px;
}
.contact:hover {
@ -800,37 +801,45 @@ StTooltip StLabel {
#LookingGlassDialog
{
background-color: rgba(0,0,0,0.85);
spacing: 4px;
padding: 4px;
border: 2px solid grey;
border-radius: 4px;
background-color: rgba(0,0,0,0.80);
spacing: 4px;
padding: 4px;
border: 2px solid grey;
border-radius: 4px;
color: #88ff66;
color: #ffffff;
}
#LookingGlassDialog > #Toolbar
{
border: 1px solid grey;
border-radius: 4px;
border: 1px solid grey;
border-radius: 4px;
}
#LookingGlassDialog .labels {
spacing: 4px;
spacing: 4px;
}
#LookingGlassDialog .notebook-tab {
padding: 2px;
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100;
padding-left: .3em;
padding-right: .3em;
}
#LookingGlassDialog .notebook-tab:hover {
color: #00ff00;
color: white;
text-shadow: black 0px 2px 2px;
}
#LookingGlassDialog .notebook-tab:selected {
border: 1px solid #88ff66;
border-radius: 4px;
padding: 5px;
border-image: url("panel-button-border.svg") 10 10 0 2;
background-image: url("panel-button-highlight-wide.svg");
color: white;
text-shadow: black 0px 2px 2px;
}
#LookingGlassDialog .lg-inspector-title {
@ -840,52 +849,58 @@ StTooltip StLabel {
.lg-dialog StLabel
{
color: #88ff66;
color: #ffffff;
}
.lg-dialog StEntry
{
color: #88ff66;
selection-background-color: #88ff66;
selected-color: black;
color: #ffffff;
selection-background-color: #bbbbbb;
selected-color: #333333;
}
.lg-completions-text
{
font-size: .9em;
font-style: italic;
}
.lg-obj-inspector-title
{
spacing: 4px;
spacing: 4px;
}
.lg-obj-inspector-button
{
border: 1px solid #88ff66;
padding: 4px;
border-radius: 4px;
border: 1px solid gray;
padding: 4px;
border-radius: 4px;
}
.lg-obj-inspector-button:hover
{
border: 1px solid #00ff00;
border: 1px solid #ffffff;
}
.lg-dialog .shell-link
{
color: #88ff66;
color: #999999;
}
.lg-dialog .shell-link:hover
{
color: #00ff00;
color: #dddddd;
}
#LookingGlassDialog StBoxLayout#EvalBox
{
padding: 4px;
spacing: 4px;
padding: 4px;
spacing: 4px;
}
#LookingGlassDialog StBoxLayout#ResultsArea
{
spacing: 4px;
spacing: 4px;
}
#lookingGlassExtensions {
@ -907,16 +922,16 @@ StTooltip StLabel {
font-weight: bold;
}
.lg-extension-actions {
.lg-extension-meta {
spacing: 6px;
}
#LookingGlassPropertyInspector {
background: rgba(0, 0, 0, 0.9);
background: rgba(0, 0, 0, 0.8);
border: 2px solid grey;
border-radius: 4px;
padding: 6px;
color: #88ff66;
color: #ffffff;
}
/* Calendar popup */
@ -1209,6 +1224,7 @@ StTooltip StLabel {
#notification-scrollview {
max-height: 10em;
-st-vfade-offset: 24px;
}
#notification-scrollview > .top-shadow, #notification-scrollview > .bottom-shadow {
@ -1251,7 +1267,8 @@ StTooltip StLabel {
}
.notification-icon-button > StIcon {
icon-size: 36px;
icon-size: 16px;
padding: 8px;
}
.hotplug-transient-box {
@ -1321,9 +1338,8 @@ StTooltip StLabel {
padding: 8px 0;
}
.chat-sent {
.chat-received {
padding-left: 4px;
border-radius: 4px;
}
.chat-received:rtl {
@ -1333,8 +1349,7 @@ StTooltip StLabel {
.chat-sent {
padding-left: 18pt;
border-radius: 4px;
color: #7E7E7E;
color: #959595;
}
.chat-sent:rtl {
@ -1344,7 +1359,6 @@ StTooltip StLabel {
.chat-meta-message {
padding-left: 4px;
border-radius: 4px;
font-size: 9pt;
color: #bbbbbb;
}
@ -1899,6 +1913,7 @@ StTooltip StLabel {
background-gradient-end: white;
background-gradient-direction: vertical;
color: black;
selected-color: white;
border-radius: 5px;
border: 2px solid #555753;
}
@ -1907,6 +1922,12 @@ StTooltip StLabel {
border: 2px solid #3465a4;
}
.polkit-dialog-password-entry .capslock-warning {
icon-size: 16px;
warning-color: #999;
padding: 0 4px;
}
.polkit-dialog-error-label {
font-size: 10pt;
color: #ffff00;
@ -1925,14 +1946,6 @@ StTooltip StLabel {
padding-bottom: 8px;
}
.network-dialog-show-password-checkbox {
padding-top: 5px;
padding-bottom: 5px;
font-size: 10pt;
color: white;
spacing: 10px;
}
.network-dialog-secret-table {
spacing-rows: 15px;
}

1
docs/Makefile.am Normal file
View File

@ -0,0 +1 @@
SUBDIRS = reference

View File

@ -0,0 +1 @@
SUBDIRS = shell st

View File

@ -0,0 +1,105 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=shell
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code, relative to $(srcdir).
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
DOC_SOURCE_DIR=../../../src
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/*.h
CFILE_GLOB=$(top_srcdir)/src/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES=calendar-server gvc hotplug-sniffer st tray
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(GNOME_SHELL_CFLAGS)
GTKDOC_LIBS=$(GNOME_SHELL_LIBS) $(top_builddir)/src/libgnome-shell.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
DISTCLEANFILES = $(DOC_MODULES).types
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,73 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>Shell Reference Manual</title>
<releaseinfo>
for Shell @VERSION@.
<!--The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/shell/index.html">http://[SERVER]/shell/</ulink>.-->
</releaseinfo>
</bookinfo>
<chapter>
<title>Actors</title>
<xi:include href="xml/shell-generic-container.xml"/>
<xi:include href="xml/shell-slicer.xml"/>
<xi:include href="xml/shell-stack.xml"/>
</chapter>
<chapter>
<title>Application tracking</title>
<xi:include href="xml/shell-app.xml"/>
<xi:include href="xml/shell-app-usage.xml"/>
<xi:include href="xml/shell-window-tracker.xml"/>
</chapter>
<chapter>
<title>Search</title>
<xi:include href="xml/shell-app-system.xml"/>
<xi:include href="xml/shell-contact-system.xml"/>
<xi:include href="xml/shell-doc-system.xml"/>
</chapter>
<chapter>
<title>Tray Icons</title>
<xi:include href="xml/shell-embedded-window.xml"/>
<xi:include href="xml/shell-gtk-embed.xml"/>
<xi:include href="xml/shell-tray-icon.xml"/>
<xi:include href="xml/shell-tray-manager.xml"/>
</chapter>
<chapter>
<title>Recorder</title>
<xi:include href="xml/shell-recorder.xml"/>
<xi:include href="xml/shell-recorder-src.xml"/>
</chapter>
<chapter>
<title>Integration helpers and utilities</title>
<xi:include href="xml/shell-global.xml"/>
<xi:include href="xml/shell-wm.xml"/>
<xi:include href="xml/shell-xfixes-cursor.xml"/>
<xi:include href="xml/shell-util.xml"/>
<xi:include href="xml/shell-mount-operation.xml"/>
<xi:include href="xml/shell-mobile-providers.xml"/>
<xi:include href="xml/shell-network-agent.xml"/>
<xi:include href="xml/shell-polkit-authentication-agent.xml"/>
<xi:include href="xml/shell-tp-client.xml"/>
</chapter>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -0,0 +1,105 @@
## Process this file with automake to produce Makefile.in
# We require automake 1.6 at least.
AUTOMAKE_OPTIONS = 1.6
# This is a blank Makefile.am for using gtk-doc.
# Copy this to your project's API docs directory and modify the variables to
# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
# of using the various options.
# The name of the module, e.g. 'glib'.
DOC_MODULE=st
# Uncomment for versioned docs and specify the version of the module, e.g. '2'.
#DOC_MODULE_VERSION=2
# The top-level SGML file. You can change this if you want to.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# Directories containing the source code, relative to $(srcdir).
# gtk-doc will search all .c and .h files beneath these paths
# for inline comments documenting functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk ../../../gdk
DOC_SOURCE_DIR=../../../src/st
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=
# Extra options to supply to gtkdoc-scan.
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
SCAN_OPTIONS=--rebuild-types --rebuild-sections
# Extra options to supply to gtkdoc-mkdb.
# e.g. MKDB_OPTIONS=--xml-mode --output-format=xml
MKDB_OPTIONS=--xml-mode --output-format=xml
# Extra options to supply to gtkdoc-mktmpl
# e.g. MKTMPL_OPTIONS=--only-section-tmpl
MKTMPL_OPTIONS=
# Extra options to supply to gtkdoc-mkhtml
MKHTML_OPTIONS=
# Extra options to supply to gtkdoc-fixref. Not normally needed.
# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/st/*.h
CFILE_GLOB=$(top_srcdir)/src/st/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
EXTRA_HFILES=
# Header files or dirs to ignore when scanning. Use base file/dir names
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h private_code
IGNORE_HFILES=st-private.h st-theme-node-private.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
HTML_IMAGES=
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files=
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
# These files must be listed here *and* in content_files
# e.g. expand_content_files=running.sgml
expand_content_files=
# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
# Only needed if you are using gtkdoc-scangobj to dynamically query widget
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=
GTKDOC_LIBS=$(top_builddir)/src/libst-1.0.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make
# Other files to distribute
# e.g. EXTRA_DIST += version.xml.in
EXTRA_DIST +=
# Files not to distribute
# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
DISTCLEANFILES = $(DOC_MODULE).types $(DOC_MODULE)-sections.txt
# Comment this out if you want 'make check' to test you doc status
# and run some sanity checks
if ENABLE_GTK_DOC
TESTS_ENVIRONMENT = cd $(srcdir) && \
DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
#TESTS = $(GTKDOC_CHECK)
endif
-include $(top_srcdir)/git.mk

View File

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
[
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<book id="index">
<bookinfo>
<title>St Reference Manual</title>
<releaseinfo>
for St @VERSION@.
<!--The latest version of this documentation can be found on-line at
<ulink role="online-location" url="http://[SERVER]/st/index.html">http://[SERVER]/st/</ulink>.-->
</releaseinfo>
</bookinfo>
<part>
<title>API reference</title>
<chapter id="base">
<title>Abstract classes and Interfaces</title>
<xi:include href="xml/st-widget.xml"/>
<xi:include href="xml/st-widget-accessible.xml"/>
<xi:include href="xml/st-container.xml"/>
<xi:include href="xml/st-scrollable.xml"/>
</chapter>
<chapter id="widgets">
<title>Widgets</title>
<xi:include href="xml/st-button.xml"/>
<xi:include href="xml/st-drawing-area.xml"/>
<xi:include href="xml/st-entry.xml"/>
<xi:include href="xml/st-icon.xml"/>
<xi:include href="xml/st-label.xml"/>
<xi:include href="xml/st-tooltip.xml"/>
</chapter>
<chapter id="containers">
<title>Containers</title>
<xi:include href="xml/st-bin.xml"/>
<xi:include href="xml/st-box-layout.xml"/>
<xi:include href="xml/st-group.xml"/>
<xi:include href="xml/st-overflow-box.xml"/>
<xi:include href="xml/st-scroll-view.xml"/>
<xi:include href="xml/st-table.xml"/>
</chapter>
<chapter id="styling">
<title>Styling</title>
<xi:include href="xml/st-theme.xml"/>
<xi:include href="xml/st-theme-context.xml"/>
<xi:include href="xml/st-theme-node.xml"/>
<xi:include href="xml/st-theme-node-transition.xml"/>
<xi:include href="xml/st-texture-cache.xml"/>
</chapter>
</part>
<chapter id="object-tree">
<title>Object Hierarchy</title>
<xi:include href="xml/tree_index.sgml"/>
</chapter>
<index id="api-index-full">
<title>API Index</title>
<xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
</index>
<index id="deprecated-api-index" role="deprecated">
<title>Index of deprecated API</title>
<xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
</index>
<xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
</book>

View File

@ -13,6 +13,7 @@ nobase_dist_js_DATA = \
misc/format.js \
misc/gnomeSession.js \
misc/history.js \
misc/jsParse.js \
misc/modemManager.js \
misc/params.js \
misc/screenSaver.js \
@ -46,6 +47,7 @@ nobase_dist_js_DATA = \
ui/messageTray.js \
ui/modalDialog.js \
ui/networkAgent.js \
ui/shellEntry.js \
ui/shellMountOperation.js \
ui/notificationDaemon.js \
ui/overview.js \

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
@ -21,11 +21,9 @@
const Lang = imports.lang;
const Signals = imports.signals;
function Task() {
this._init.apply(this, arguments);
}
const Task = new Lang.Class({
Name: 'Task',
Task.prototype = {
_init: function(scope, handler) {
if (scope)
this.scope = scope;
@ -41,22 +39,17 @@ Task.prototype = {
return null;
},
};
});
Signals.addSignalMethods(Task.prototype);
function Hold() {
this._init.apply(this, arguments);
}
Hold.prototype = {
__proto__: Task.prototype,
const Hold = new Lang.Class({
Name: 'Hold',
Extends: Task,
_init: function() {
Task.prototype._init.call(this,
this,
function () {
return this;
});
this.parent(this, function () {
return this;
});
this._acquisitions = 1;
},
@ -88,18 +81,15 @@ Hold.prototype = {
isAcquired: function() {
return this._acquisitions > 0;
}
}
});
Signals.addSignalMethods(Hold.prototype);
function Batch() {
this._init.apply(this, arguments);
}
Batch.prototype = {
__proto__: Task.prototype,
const Batch = new Lang.Class({
Name: 'Batch',
Extends: Task,
_init: function(scope, tasks) {
Task.prototype._init.call(this);
this.parent();
this.tasks = [];
@ -166,20 +156,12 @@ Batch.prototype = {
cancel: function() {
this.tasks = this.tasks.splice(0, this._currentTaskIndex + 1);
}
};
});
Signals.addSignalMethods(Batch.prototype);
function ConcurrentBatch() {
this._init.apply(this, arguments);
}
ConcurrentBatch.prototype = {
__proto__: Batch.prototype,
_init: function(scope, tasks) {
Batch.prototype._init.call(this, scope, tasks);
},
const ConcurrentBatch = new Lang.Class({
Name: 'ConcurrentBatch',
Extends: Batch,
process: function() {
let hold = this.runTask();
@ -193,19 +175,12 @@ ConcurrentBatch.prototype = {
// concurrently.
this.nextTask();
}
};
});
Signals.addSignalMethods(ConcurrentBatch.prototype);
function ConsecutiveBatch() {
this._init.apply(this, arguments);
}
ConsecutiveBatch.prototype = {
__proto__: Batch.prototype,
_init: function(scope, tasks) {
Batch.prototype._init.call(this, scope, tasks);
},
const ConsecutiveBatch = new Lang.Class({
Name: 'ConsecutiveBatch',
Extends: Batch,
process: function() {
let hold = this.runTask();
@ -224,5 +199,5 @@ ConsecutiveBatch.prototype = {
this.nextTask();
}
}
};
});
Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@ -1,32 +1,22 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const ConsoleKitManagerIface = {
name: 'org.freedesktop.ConsoleKit.Manager',
methods: [{ name: 'CanRestart',
inSignature: '',
outSignature: 'b' },
{ name: 'CanStop',
inSignature: '',
outSignature: 'b' },
{ name: 'Restart',
inSignature: '',
outSignature: '' },
{ name: 'Stop',
inSignature: '',
outSignature: '' }]
};
const ConsoleKitManagerIface = <interface name='org.freedesktop.ConsoleKit.Manager'>
<method name='CanRestart'>
<arg type='b' direction='out'/>
</method>
<method name='CanStop'>
<arg type='b' direction='out'/>
</method>
<method name='Restart' />
<method name='Stop' />
</interface>;
const ConsoleKitProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitManagerIface);
function ConsoleKitManager() {
this._init();
return new ConsoleKitProxy(Gio.DBus.system,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
};
ConsoleKitManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
}
};
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);

View File

@ -1,26 +1,20 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const FprintManagerIface = {
name: 'net.reactivated.Fprint.Manager',
methods: [{ name: 'GetDefaultDevice',
inSignature: '',
outSignature: 'o' }]
};
const FprintManagerIface = <interface name='net.reactivated.Fprint.Manager'>
<method name='GetDefaultDevice'>
<arg type='o' direction='out' />
</method>
</interface>;
const FprintManagerProxy = Gio.DBusProxy.makeProxyWrapper(FprintManagerIface);
function FprintManager() {
this._init();
return new FprintManagerProxy(Gio.DBus.system,
'net.reactivated.Fprint',
'/net/reactivated/Fprint/Manager');
};
FprintManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'net.reactivated.Fprint',
'/net/reactivated/Fprint/Manager');
}
};
DBus.proxifyPrototype(FprintManager.prototype, FprintManagerIface);

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
@ -33,7 +33,6 @@ const St = imports.gi.St;
const GdmGreeter = imports.gi.GdmGreeter;
const Batch = imports.gdm.batch;
const DBus = imports.dbus;
const Fprint = imports.gdm.fingerprint;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
@ -141,11 +140,9 @@ function _smoothlyResizeActor(actor, width, height) {
return hold;
}
function UserListItem(user, reason) {
this._init(user, reason);
}
const UserListItem = new Lang.Class({
Name: 'UserListItem',
UserListItem.prototype = {
_init: function(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
@ -274,15 +271,12 @@ UserListItem.prototype = {
});
return hold;
}
};
});
Signals.addSignalMethods(UserListItem.prototype);
function UserList() {
this._init.apply(this, arguments);
}
const UserList = new Lang.Class({
Name: 'UserList',
UserList.prototype = {
_init: function() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor.set_policy(Gtk.PolicyType.NEVER,
@ -297,6 +291,20 @@ UserList.prototype = {
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
this._items = {};
this.actor.connect('key-focus-in', Lang.bind(this, this._moveFocusToItems));
},
_moveFocusToItems: function() {
let hasItems = Object.keys(this._items).length > 0;
if (!hasItems)
return;
if (global.stage.get_key_focus() != this.actor)
return;
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
},
_showItem: function(item) {
@ -502,6 +510,8 @@ UserList.prototype = {
item.showFocusAnimation(0);
}));
this._moveFocusToItems();
this.emit('item-added', item);
},
@ -522,14 +532,12 @@ UserList.prototype = {
item.actor.destroy();
delete this._items[userName];
}
};
});
Signals.addSignalMethods(UserList.prototype);
function SessionListItem(id, name) {
this._init(id, name);
}
const SessionListItem = new Lang.Class({
Name: 'SessionListItem',
SessionListItem.prototype = {
_init: function(id, name) {
this.id = id;
@ -584,14 +592,12 @@ SessionListItem.prototype = {
_onClicked: function() {
this.emit('activate');
}
};
});
Signals.addSignalMethods(SessionListItem.prototype);
function SessionList() {
this._init();
}
const SessionList = new Lang.Class({
Name: 'SessionList',
SessionList.prototype = {
_init: function() {
this.actor = new St.Bin();
@ -694,10 +700,13 @@ SessionList.prototype = {
let ids = GdmGreeter.get_session_ids();
ids.sort();
if (ids.length <= 1)
if (ids.length <= 1) {
this._box.hide();
else
this._button.hide();
} else {
this._button.show();
this._box.show();
}
for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription] = GdmGreeter.get_session_name_and_description(ids[i]);
@ -719,24 +728,15 @@ SessionList.prototype = {
}));
}
}
};
});
Signals.addSignalMethods(SessionList.prototype);
function LoginDialog() {
if (_loginDialog == null) {
this._init();
_loginDialog = this;
}
return _loginDialog;
}
LoginDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const LoginDialog = new Lang.Class({
Name: 'LoginDialog',
Extends: ModalDialog.ModalDialog,
_init: function() {
ModalDialog.ModalDialog.prototype._init.call(this, { shellReactive: true,
styleClass: 'login-dialog' });
this.parent({ shellReactive: true, styleClass: 'login-dialog' });
this.connect('destroy',
Lang.bind(this, this._onDestroy));
this.connect('opened',
@ -825,7 +825,7 @@ LoginDialog.prototype = {
x_fill: true,
y_fill: false,
x_align: St.Align.START });
// translators: this message is shown below the password entry field
// Translators: this message is shown below the password entry field
// to indicate the user can swipe their finger instead
this._promptFingerprintMessage = new St.Label({ text: _("(or swipe finger)"),
style_class: 'login-dialog-prompt-fingerprint-message' });
@ -845,6 +845,9 @@ LoginDialog.prototype = {
x_align: St.Align.START });
this._promptBox.hide();
// translators: this message is shown below the user list on the
// login screen. It can be activated to reveal an entry for
// manually entering the username.
let notListedLabel = new St.Label({ text: _("Not listed?"),
style_class: 'login-dialog-not-listed-label' });
this._notListedButton = new St.Button({ style_class: 'login-dialog-not-listed-button',
@ -886,7 +889,7 @@ LoginDialog.prototype = {
if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
return;
this._fprintManager.GetDefaultDeviceRemote(DBus.CALL_FLAG_START, Lang.bind(this,
this._fprintManager.GetDefaultDeviceRemote(Gio.DBusCallFlags.NONE, Lang.bind(this,
function(device, error) {
if (!error && device)
this._haveFingerprintReader = true;
@ -922,6 +925,7 @@ LoginDialog.prototype = {
function() {
this._sessionList.close();
this._promptFingerprintMessage.hide();
this._userList.actor.show();
this._userList.actor.opacity = 255;
return this._userList.showItems();
@ -943,7 +947,18 @@ LoginDialog.prototype = {
},
_onInfo: function(client, serviceName, info) {
// we don't want fingerprint messages with the word UPEK in them
// We don't display fingerprint messages, because they
// have words like UPEK in them. Instead we use the messages
// as a cue to display our own message.
if (serviceName == _FINGERPRINT_SERVICE_NAME &&
this._haveFingerprintReader &&
(!this._promptFingerprintMessage.visible ||
this._promptFingerprintMessage.opacity != 255)) {
_fadeInActor(this._promptFingerprintMessage);
return;
}
if (serviceName != _PASSWORD_SERVICE_NAME)
return;
Main.notifyError(info);
@ -971,10 +986,10 @@ LoginDialog.prototype = {
},
function() {
if (!this._haveFingerprintReader)
return null;
return _fadeInActor(this._promptFingerprintMessage);
// Show it with 0 opacity so we preallocate space for it
// in the event we need to fade in the message
this._promptFingerprintMessage.opacity = 0;
this._promptFingerprintMessage.show();
},
function() {
@ -1046,6 +1061,8 @@ LoginDialog.prototype = {
function() {
this._promptFingerprintMessage.hide();
this._promptEntry.reactive = true;
this._promptEntry.remove_style_pseudo_class('insensitive');
this._promptEntry.set_text('');
}];
@ -1061,7 +1078,8 @@ LoginDialog.prototype = {
function() {
let _text = this._promptEntry.get_text();
this._promptEntry.set_text('');
this._promptEntry.reactive = false;
this._promptEntry.add_style_pseudo_class('insensitive');
this._greeterClient.call_answer_query(serviceName, _text);
}];
@ -1362,8 +1380,8 @@ LoginDialog.prototype = {
},
close: function() {
ModalDialog.ModalDialog.prototype.close.call(this);
this.parent();
Main.ctrlAltTabManager.removeGroup(this._group);
}
};
});

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
@ -25,15 +25,12 @@ const ConsoleKit = imports.gdm.consoleKit;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
function PowerMenuButton() {
this._init();
}
PowerMenuButton.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const PowerMenuButton = new Lang.Class({
Name: 'PowerMenuButton',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'system-shutdown', null);
this.parent('system-shutdown', null);
this._consoleKitManager = new ConsoleKit.ConsoleKitManager();
this._upClient = new UPowerGlib.Client();
@ -143,4 +140,4 @@ PowerMenuButton.prototype = {
if (this._haveShutdown)
this._consoleKitManager.StopRemote();
}
};
});

View File

@ -1,4 +1,5 @@
/* mode: js2; indent-tabs-mode: nil; tab-size: 4 */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* The name of this package (not localized) */
const PACKAGE_NAME = '@PACKAGE_NAME@';
/* The version of this package */

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const St = imports.gi.St;
const Shell = imports.gi.Shell;
@ -8,11 +8,9 @@ const Search = imports.ui.search;
const THUMBNAIL_ICON_MARGIN = 2;
function DocInfo(recentInfo) {
this._init(recentInfo);
}
const DocInfo = new Lang.Class({
Name: 'DocInfo',
DocInfo.prototype = {
_init : function(recentInfo) {
this.recentInfo = recentInfo;
// We actually used get_modified() instead of get_visited()
@ -49,7 +47,7 @@ DocInfo.prototype = {
}
return mtype;
}
};
});
var docManagerInstance = null;
@ -62,11 +60,9 @@ function getDocManager() {
/**
* DocManager wraps the DocSystem, primarily to expose DocInfo objects.
*/
function DocManager() {
this._init();
}
const DocManager = new Lang.Class({
Name: 'DocManager',
DocManager.prototype = {
_init: function() {
this._docSystem = Shell.DocSystem.get_default();
this._infosByTimestamp = [];
@ -135,6 +131,6 @@ DocManager.prototype = {
return this._infosByUri[url];
})), terms);
}
};
});
Signals.addSignalMethods(DocManager.prototype);

View File

@ -1,3 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* This function is intended to extend the String object and provide

View File

@ -1,20 +1,18 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Signals = imports.signals;
const PresenceIface = {
name: 'org.gnome.SessionManager.Presence',
methods: [{ name: 'SetStatus',
inSignature: 'u',
outSignature: '' }],
properties: [{ name: 'status',
signature: 'u',
access: 'readwrite' }],
signals: [{ name: 'StatusChanged',
inSignature: 'u' }]
};
const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
<method name="SetStatus">
<arg type="u" direction="in"/>
</method>
<property name="status" type="u" access="readwrite"/>
<signal name="StatusChanged">
<arg type="u" direction="out"/>
</signal>
</interface>;
const PresenceStatus = {
AVAILABLE: 0,
@ -23,104 +21,41 @@ const PresenceStatus = {
IDLE: 3
};
function Presence() {
this._init();
var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
function Presence(initCallback, cancellable) {
return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
'/org/gnome/SessionManager/Presence', initCallback, cancellable);
}
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);
// Note inhibitors are immutable objects, so they don't
// change at runtime (changes always come in the form
// of new inhibitors)
const InhibitorIface = {
name: 'org.gnome.SessionManager.Inhibitor',
properties: [{ name: 'app_id',
signature: 's',
access: 'readonly' },
{ name: 'client_id',
signature: 's',
access: 'readonly' },
{ name: 'reason',
signature: 's',
access: 'readonly' },
{ name: 'flags',
signature: 'u',
access: 'readonly' },
{ name: 'toplevel_xid',
signature: 'u',
access: 'readonly' },
{ name: 'cookie',
signature: 'u',
access: 'readonly' }],
};
const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
<property name="app_id" type="s" access="read" />
<property name="client_id" type="s" access="read" />
<property name="reason" type="s" access="read" />
<property name="flags" type="u" access="read" />
<property name="toplevel_xid" type="u" access="read" />
<property name="cookie" type="u" access="read" />
</interface>;
function Inhibitor(objectPath) {
this._init(objectPath);
var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
function Inhibitor(objectPath, initCallback, cancellable) {
return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
}
Inhibitor.prototype = {
_init: function(objectPath) {
DBus.session.proxifyObject(this,
"org.gnome.SessionManager",
objectPath);
this.isLoaded = false;
this._loadingPropertiesCount = InhibitorIface.properties.length;
for (let i = 0; i < InhibitorIface.properties.length; i++) {
let propertyName = InhibitorIface.properties[i].name;
this.GetRemote(propertyName, Lang.bind(this,
function(value, exception) {
if (exception)
return;
this[propertyName] = value;
this._loadingPropertiesCount--;
if (this._loadingPropertiesCount == 0) {
this.isLoaded = true;
this.emit("is-loaded");
}
}));
}
},
};
DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
Signals.addSignalMethods(Inhibitor.prototype);
// Not the full interface, only the methods we use
const SessionManagerIface = {
name: 'org.gnome.SessionManager',
methods: [
{ name: 'Logout', inSignature: 'u', outSignature: '' },
{ name: 'Shutdown', inSignature: '', outSignature: '' },
{ name: 'CanShutdown', inSignature: '', outSignature: 'b' }
]
};
const SessionManagerIface = <interface name="org.gnome.SessionManager">
<method name="Logout">
<arg type="u" direction="in" />
</method>
<method name="Shutdown" />
<method name="CanShutdown">
<arg type="b" direction="out" />
</method>
</interface>;
function SessionManager() {
this._init();
var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
function SessionManager(initCallback, cancellable) {
return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
}
SessionManager.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
}
};
DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
@ -7,11 +7,9 @@ const Params = imports.misc.params;
const DEFAULT_LIMIT = 512;
function HistoryManager(params) {
this._init(params);
}
const HistoryManager = new Lang.Class({
Name: 'HistoryManager',
HistoryManager.prototype = {
_init: function(params) {
params = Params.parse(params, { gsettingsKey: null,
limit: DEFAULT_LIMIT,
@ -111,5 +109,5 @@ HistoryManager.prototype = {
if (this._key)
global.settings.set_strv(this._key, this._history);
}
};
});
Signals.addSignalMethods(HistoryManager.prototype);

246
js/misc/jsParse.js Normal file
View File

@ -0,0 +1,246 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
// commandHeader is prefixed on any expression before it is eval'ed. It will most likely
// consist of global constants that might not carry over from the calling environment.
//
// This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr, base;
let attrHead = '';
if (globalCompletionList == null) {
globalCompletionList = [];
}
let offset = getExpressionOffset(text, text.length - 1);
if (offset >= 0) {
text = text.slice(offset);
// Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/);
if (matches) {
[expr, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
}
// Look for the empty expression or partially entered words
// not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/);
if (text == '' || matches) {
[expr, attrHead] = matches;
methods = globalCompletionList.filter(function(attr) {
return attr.slice(0, attrHead.length) == attrHead;
});
}
}
return [methods, attrHead];
}
//
// A few functions for parsing strings of javascript code.
//
// Identify characters that delimit an expression. That is,
// if we encounter anything that isn't a letter, '.', ')', or ']',
// we should stop parsing.
function isStopChar(c) {
return !c.match(/[\w\.\)\]]/);
}
// Given the ending position of a quoted string, find where it starts
function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
return i;
}
}
return -1;
}
// Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
return i;
}
}
return -1;
}
// If expr.charAt(offset) is ')' or ']',
// return the position of the corresponding '(' or '[' bracket.
// This function does not check for syntactic correctness. e.g.,
// findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset);
let openBrace = ({')': '(', ']': '['})[closeBrace];
function findTheBrace(expr, offset) {
if (offset < 0) {
return -1;
}
if (expr.charAt(offset) == openBrace) {
return offset;
}
if (expr.charAt(offset).match(/['"]/)) {
return findTheBrace(expr, findMatchingQuote(expr, offset) - 1);
}
if (expr.charAt(offset) == '/') {
return findTheBrace(expr, findMatchingSlash(expr, offset) - 1);
}
if (expr.charAt(offset) == closeBrace) {
return findTheBrace(expr, findTheBrace(expr, offset - 1) - 1);
}
return findTheBrace(expr, offset - 1);
}
return findTheBrace(expr, offset - 1);
}
// Walk expr backwards from offset looking for the beginning of an
// expression suitable for passing to eval.
// There is no guarantee of correct javascript syntax between the return
// value and offset. This function is meant to take a string like
// "foo(Obj.We.Are.Completing" and allow you to extract "Obj.We.Are.Completing"
function getExpressionOffset(expr, offset) {
while (offset >= 0) {
let currChar = expr.charAt(offset);
if (isStopChar(currChar)){
return offset + 1;
}
if (currChar.match(/[\)\]]/)) {
offset = findMatchingBrace(expr, offset);
}
--offset;
}
return offset + 1;
}
// Things with non-word characters or that start with a number
// are not accessible via .foo notation and so aren't returned
function isValidPropertyName(w) {
return !(w.match(/\W/) || w.match(/^\d/));
}
// To get all properties (enumerable and not), we need to walk
// the prototype chain ourselves
function getAllProps(obj) {
if (obj === null || obj === undefined) {
return [];
}
return Object.getOwnPropertyNames(obj).concat( getAllProps(Object.getPrototypeOf(obj)) );
}
// Given a string _expr_, returns all methods
// that can be accessed via '.' notation.
// e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _.
function getPropertyNamesFromExpression(expr, commandHeader) {
if (commandHeader == null) {
commandHeader = '';
}
let obj = {};
if (!isUnsafeExpression(expr)) {
try {
obj = eval(commandHeader + expr);
} catch (e) {
return [];
}
} else {
return [];
}
let propsUnique = {};
if (typeof obj === 'object'){
let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.'
allProps = allProps.filter( isValidPropertyName );
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
allProps.map(function(p){ propsUnique[p] = null; });
}
return Object.keys(propsUnique).sort();
}
// Given a list of words, returns the longest prefix they all have in common
function getCommonPrefix(words) {
let word = words[0];
for (let i = 0; i < word.length; i++) {
for (let w = 1; w < words.length; w++) {
if (words[w].charAt(i) != word.charAt(i))
return word.slice(0, i);
}
}
return word;
}
// Returns true if there is reason to think that eval(str)
// will modify the global scope
function isUnsafeExpression(str) {
// Remove any blocks that are quoted or are in a regex
function removeLiterals(str) {
if (str.length == 0) {
return '';
}
let currChar = str.charAt(str.length - 1);
if (currChar == '"' || currChar == '\'') {
return removeLiterals(str.slice(0, findMatchingQuote(str, str.length - 1)));
} else if (currChar == '/') {
return removeLiterals(str.slice(0, findMatchingSlash(str, str.length - 1)));
}
return removeLiterals(str.slice(0, str.length - 1)) + currChar;
}
// Check for any sort of assignment
// The strategy used is dumb: remove any quotes
// or regexs and comparison operators and see if there is an '=' character.
// If there is, it might be an unsafe assignment.
let prunedStr = removeLiterals(str);
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/=/)) {
return true;
} else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well
return true;
}
return false;
}
// Returns a list of global keywords derived from str
function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(function(s) {
let base, keyword;
let match = s.match(/const\s+(\w+)\s*=/);
if (match) {
[base, keyword] = match;
ret.push(keyword);
}
});
return ret;
}

View File

@ -1,6 +1,6 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@ -8,33 +8,43 @@ const Signals = imports.signals;
// The following are not the complete interfaces, just the methods we need
// (or may need in the future)
const ModemGsmNetworkInterface = {
name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
methods: [
{ name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
],
properties: [
{ name: 'AccessTechnology', signature: 'u', access: 'read' }
],
signals: [
{ name: 'SignalQuality', inSignature: 'u' },
{ name: 'RegistrationInfo', inSignature: 'uss' }
]
};
const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
<method name="GetRegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</method>
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<property name="AccessTechnology" type="u" access="read" />
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
<signal name="RegistrationInfo">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="s" direction="out" />
</signal>
</interface>;
const ModemCdmaInterface = {
name: 'org.freedesktop.ModemManager.Modem.Cdma',
methods: [
{ name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
{ name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
],
signals: [
{ name: 'SignalQuality', inSignature: 'u' }
]
};
const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
<method name="GetSignalQuality">
<arg type="u" direction="out" />
</method>
<method name="GetServingSystem">
<arg type="u" direction="out" />
<arg type="s" direction="out" />
<arg type="u" direction="out" />
</method>
<signal name="SignalQuality">
<arg type="u" direction="out" />
</signal>
</interface>;
const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
let _providersTable;
function _getProvidersTable() {
@ -44,23 +54,21 @@ function _getProvidersTable() {
return _providersTable = providers;
}
function ModemGsm() {
this._init.apply(this, arguments);
}
const ModemGsm = new Lang.Class({
Name: 'ModemGsm',
ModemGsm.prototype = {
_init: function(path) {
this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
// Code is duplicated because the function have different signatures
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
this.signal_quality = quality;
this.emit('notify::signal-quality');
}));
this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
this.operator_name = this._findOperatorName(name, code);
this.emit('notify::operator-name');
}));
@ -146,21 +154,19 @@ ModemGsm.prototype = {
return name3 || name2 || null;
}
}
});
Signals.addSignalMethods(ModemGsm.prototype);
function ModemCdma() {
this._init.apply(this, arguments);
}
const ModemCdma = new Lang.Class({
Name: 'ModemCdma',
ModemCdma.prototype = {
_init: function(path) {
this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
this.signal_quality = 0;
this.operator_name = null;
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
this.signal_quality = quality;
this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
this.signal_quality = params[0];
this.emit('notify::signal-quality');
// receiving this signal means the device got activated
@ -221,5 +227,5 @@ ModemCdma.prototype = {
return null;
}
};
});
Signals.addSignalMethods(ModemCdma.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
// parse:
// @params: caller-provided parameter object, or %null

View File

@ -1,53 +1,48 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const ScreenSaverIface = {
name: 'org.gnome.ScreenSaver',
methods: [{ name: 'GetActive',
inSignature: '',
outSignature: 'b' },
{ name: 'Lock',
inSignature: '' },
{ name: 'SetActive',
inSignature: 'b' }],
signals: [{ name: 'ActiveChanged',
inSignature: 'b' }]
};
const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
<method name="GetActive">
<arg type="b" direction="out" />
</method>
<method name="Lock" />
<method name="SetActive">
<arg type="b" direction="in" />
</method>
<signal name="ActiveChanged">
<arg type="b" direction="out" />
</signal>
</interface>;
const ScreenSaverInfo = Gio.DBusInterfaceInfo.new_for_xml(ScreenSaverIface);
function ScreenSaverProxy() {
this._init();
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: ScreenSaverInfo.name,
g_interface_info: ScreenSaverInfo,
g_name: 'org.gnome.ScreenSaver',
g_object_path: '/org/gnome/ScreenSaver',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
self.init(null);
self.screenSaverActive = false;
self.connectSignal('ActiveChanged', function(proxy, senderName, [isActive]) {
self.screenSaverActive = isActive;
});
self.connect('notify::g-name-owner', function() {
if (self.g_name_owner) {
self.GetActiveRemote(function(result, excp) {
if (result) {
let [isActive] = result;
self.screenSaverActive = isActive;
}
});
} else
self.screenSaverActive = false;
});
return self;
}
ScreenSaverProxy.prototype = {
_init: function() {
DBus.session.proxifyObject(this,
'org.gnome.ScreenSaver',
'/org/gnome/ScreenSaver');
DBus.session.watch_name('org.gnome.ScreenSaver',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onSSAppeared),
Lang.bind(this, this._onSSVanished));
this.screenSaverActive = false;
this.connect('ActiveChanged',
Lang.bind(this, this._onActiveChanged));
},
_onSSAppeared: function(owner) {
this.GetActiveRemote(Lang.bind(this, function(isActive) {
this.screenSaverActive = isActive;
}))
},
_onSSVanished: function(oldOwner) {
this.screenSaverActive = false;
},
_onActiveChanged: function(object, isActive) {
this.screenSaverActive = isActive;
}
};
DBus.proxifyPrototype(ScreenSaverProxy.prototype, ScreenSaverIface);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
@ -43,11 +43,9 @@ function primaryModifier(mask) {
return primary;
}
function AltTabPopup() {
this._init();
}
const AltTabPopup = new Lang.Class({
Name: 'AltTabPopup',
AltTabPopup.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'altTabPopup',
reactive: true,
@ -134,15 +132,48 @@ AltTabPopup.prototype = {
}
},
show : function(backward, binding, mask) {
_getAppLists: function() {
let tracker = Shell.WindowTracker.get_default();
let appSys = Shell.AppSystem.get_default();
let apps = appSys.get_running ();
let allApps = appSys.get_running ();
if (!apps.length)
let screen = global.screen;
let display = screen.get_display();
let windows = display.get_tab_list(Meta.TabList.NORMAL, screen,
screen.get_active_workspace());
// windows is only the windows on the current workspace. For
// each one, if it corresponds to an app we know, move that
// app from allApps to apps.
let apps = [];
for (let i = 0; i < windows.length && allApps.length != 0; i++) {
let app = tracker.get_window_app(windows[i]);
let index = allApps.indexOf(app);
if (index != -1) {
apps.push(app);
allApps.splice(index, 1);
}
}
// Now @apps is a list of apps on the current workspace, in
// standard Alt+Tab order (MRU except for minimized windows),
// and allApps is a list of apps that only appear on other
// workspaces, sorted by user_time, which is good enough.
return [apps, allApps];
},
show : function(backward, binding, mask) {
let [localApps, otherApps] = this._getAppLists();
if (localApps.length == 0 && otherApps.length == 0)
return false;
if (!Main.pushModal(this.actor))
return false;
if (!Main.pushModal(this.actor)) {
// Probably someone else has a pointer grab, try again with keyboard only
if (!Main.pushModal(this.actor, global.get_current_time(), Meta.ModalOptions.POINTER_ALREADY_GRABBED)) {
return false;
}
}
this._haveModal = true;
this._modifierMask = primaryModifier(mask);
@ -152,7 +183,7 @@ AltTabPopup.prototype = {
this.actor.connect('button-press-event', Lang.bind(this, this._clickedOutside));
this.actor.connect('scroll-event', Lang.bind(this, this._onScroll));
this._appSwitcher = new AppSwitcher(apps, this);
this._appSwitcher = new AppSwitcher(localApps, otherApps, this);
this.actor.add_actor(this._appSwitcher.actor);
this._appSwitcher.connect('item-activated', Lang.bind(this, this._appActivated));
this._appSwitcher.connect('item-entered', Lang.bind(this, this._appEntered));
@ -166,7 +197,7 @@ AltTabPopup.prototype = {
this.actor.get_allocation_box();
// Make the initial selection
if (binding == 'switch_group') {
if (binding == 'switch-group') {
if (backward) {
this._select(0, this._appIcons[0].cachedWindows.length - 1);
} else {
@ -175,9 +206,9 @@ AltTabPopup.prototype = {
else
this._select(0, 0);
}
} else if (binding == 'switch_group_backward') {
} else if (binding == 'switch-group-backward') {
this._select(0, this._appIcons[0].cachedWindows.length - 1);
} else if (binding == 'switch_windows_backward') {
} else if (binding == 'switch-windows-backward') {
this._select(this._appIcons.length - 1);
} else if (this._appIcons.length == 1) {
this._select(0);
@ -507,13 +538,11 @@ AltTabPopup.prototype = {
onComplete: Lang.bind(this, function () { this.thumbnailsVisible = true; })
});
}
};
});
function SwitcherList(squareItems) {
this._init(squareItems);
}
const SwitcherList = new Lang.Class({
Name: 'SwitcherList',
SwitcherList.prototype = {
_init : function(squareItems) {
this.actor = new Shell.GenericContainer({ style_class: 'switcher-list' });
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -818,15 +847,13 @@ SwitcherList.prototype = {
// Clip the area for scrolling
this._clipBin.set_clip(0, -topPadding, (this.actor.allocation.x2 - this.actor.allocation.x1) - leftPadding - rightPadding, this.actor.height + bottomPadding);
}
};
});
Signals.addSignalMethods(SwitcherList.prototype);
function AppIcon(app) {
this._init(app);
}
const AppIcon = new Lang.Class({
Name: 'AppIcon',
AppIcon.prototype = {
_init: function(app) {
this.app = app;
this.actor = new St.BoxLayout({ style_class: 'alt-tab-app',
@ -844,35 +871,31 @@ AppIcon.prototype = {
this._iconBin.set_size(size, size);
this._iconBin.child = this.icon;
}
};
});
function AppSwitcher(apps, altTabPopup) {
this._init(apps, altTabPopup);
}
const AppSwitcher = new Lang.Class({
Name: 'AppSwitcher',
Extends: SwitcherList,
AppSwitcher.prototype = {
__proto__ : SwitcherList.prototype,
_init : function(localApps, otherApps, altTabPopup) {
this.parent(true);
_init : function(apps, altTabPopup) {
SwitcherList.prototype._init.call(this, true);
// Construct the AppIcons, sort by time, add to the popup
// Construct the AppIcons, add to the popup
let activeWorkspace = global.screen.get_active_workspace();
let workspaceIcons = [];
let otherIcons = [];
for (let i = 0; i < apps.length; i++) {
let appIcon = new AppIcon(apps[i]);
for (let i = 0; i < localApps.length; i++) {
let appIcon = new AppIcon(localApps[i]);
// Cache the window list now; we don't handle dynamic changes here,
// and we don't want to be continually retrieving it
appIcon.cachedWindows = appIcon.app.get_windows();
if (this._hasWindowsOnWorkspace(appIcon, activeWorkspace))
workspaceIcons.push(appIcon);
else
otherIcons.push(appIcon);
workspaceIcons.push(appIcon);
}
for (let i = 0; i < otherApps.length; i++) {
let appIcon = new AppIcon(otherApps[i]);
appIcon.cachedWindows = appIcon.app.get_windows();
otherIcons.push(appIcon);
}
workspaceIcons.sort(Lang.bind(this, this._sortAppIcon));
otherIcons.sort(Lang.bind(this, this._sortAppIcon));
this.icons = [];
this._arrows = [];
@ -934,7 +957,7 @@ AppSwitcher.prototype = {
_allocate: function (actor, box, flags) {
// Allocate the main list items
SwitcherList.prototype._allocate.call(this, actor, box, flags);
this.parent(actor, box, flags);
let arrowHeight = Math.floor(this.actor.get_theme_node().get_padding(St.Side.BOTTOM) / 3);
let arrowWidth = arrowHeight * 2;
@ -989,7 +1012,7 @@ AppSwitcher.prototype = {
this._arrows[this._curApp].remove_style_pseudo_class('highlighted');
}
SwitcherList.prototype.highlight.call(this, n, justOutline);
this.parent(n, justOutline);
this._curApp = n;
if (this._curApp != -1) {
@ -1012,31 +1035,15 @@ AppSwitcher.prototype = {
if (appIcon.cachedWindows.length == 1)
arrow.hide();
},
_hasWindowsOnWorkspace: function(appIcon, workspace) {
let windows = appIcon.cachedWindows;
for (let i = 0; i < windows.length; i++) {
if (windows[i].get_workspace() == workspace)
return true;
}
return false;
},
_sortAppIcon : function(appIcon1, appIcon2) {
return appIcon1.app.compare(appIcon2.app);
}
};
});
function ThumbnailList(windows) {
this._init(windows);
}
ThumbnailList.prototype = {
__proto__ : SwitcherList.prototype,
const ThumbnailList = new Lang.Class({
Name: 'ThumbnailList',
Extends: SwitcherList,
_init : function(windows) {
SwitcherList.prototype._init.call(this);
this.parent(false);
let activeWorkspace = global.screen.get_active_workspace();
@ -1114,7 +1121,7 @@ ThumbnailList.prototype = {
// Make sure we only do this once
this._thumbnailBins = new Array();
}
};
});
function _drawArrow(area, side) {
let themeNode = area.get_theme_node();

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
@ -26,11 +26,9 @@ const MAX_APPLICATION_WORK_MILLIS = 75;
const MENU_POPUP_TIMEOUT = 600;
const SCROLL_TIME = 0.1;
function AlphabeticalView() {
this._init();
}
const AlphabeticalView = new Lang.Class({
Name: 'AlphabeticalView',
AlphabeticalView.prototype = {
_init: function() {
this._grid = new IconGrid.IconGrid({ xAlign: St.Align.START });
this._appSystem = Shell.AppSystem.get_default();
@ -130,13 +128,11 @@ AlphabeticalView.prototype = {
this._addApp(app);
}
}
};
});
function ViewByCategories() {
this._init();
}
const ViewByCategories = new Lang.Class({
Name: 'ViewByCategories',
ViewByCategories.prototype = {
_init: function() {
this._appSystem = Shell.AppSystem.get_default();
this.actor = new St.BoxLayout({ style_class: 'all-app' });
@ -281,16 +277,14 @@ ViewByCategories.prototype = {
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}
}
};
});
/* This class represents a display containing a collection of application items.
* The applications are sorted based on their name.
*/
function AllAppDisplay() {
this._init();
}
const AllAppDisplay = new Lang.Class({
Name: 'AllAppDisplay',
AllAppDisplay.prototype = {
_init: function() {
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed', Lang.bind(this, function() {
@ -306,17 +300,15 @@ AllAppDisplay.prototype = {
_redisplay: function() {
this._appView.refresh();
}
};
});
function AppSearchProvider() {
this._init();
}
AppSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
const AppSearchProvider = new Lang.Class({
Name: 'AppSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("APPLICATIONS"));
this.parent(_("APPLICATIONS"));
this._appSys = Shell.AppSystem.get_default();
},
@ -364,17 +356,15 @@ AppSearchProvider.prototype = {
let icon = new AppWellIcon(app);
return icon.actor;
}
};
});
function SettingsSearchProvider() {
this._init();
}
SettingsSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
const SettingsSearchProvider = new Lang.Class({
Name: 'SettingsSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("SETTINGS"));
this.parent(_("SETTINGS"));
this._appSys = Shell.AppSystem.get_default();
this._gnomecc = this._appSys.lookup_app('gnome-control-center.desktop');
},
@ -412,35 +402,28 @@ SettingsSearchProvider.prototype = {
let icon = new AppWellIcon(app);
return icon.actor;
}
};
});
function AppIcon(app, params) {
this._init(app, params);
}
AppIcon.prototype = {
__proto__: IconGrid.BaseIcon.prototype,
const AppIcon = new Lang.Class({
Name: 'AppIcon',
Extends: IconGrid.BaseIcon,
_init : function(app, params) {
this.app = app;
let label = this.app.get_name();
IconGrid.BaseIcon.prototype._init.call(this,
label,
params);
this.parent(label, params);
},
createIcon: function(iconSize) {
return this.app.create_icon_texture(iconSize);
}
};
});
function AppWellIcon(app, iconParams, onActivateOverride) {
this._init(app, iconParams, onActivateOverride);
}
const AppWellIcon = new Lang.Class({
Name: 'AppWellIcon',
AppWellIcon.prototype = {
_init : function(app, iconParams, onActivateOverride) {
this.app = app;
this.actor = new St.Button({ style_class: 'app-well-app',
@ -620,22 +603,19 @@ AppWellIcon.prototype = {
getDragActorSource: function() {
return this.icon.icon;
}
};
});
Signals.addSignalMethods(AppWellIcon.prototype);
function AppIconMenu(source) {
this._init(source);
}
AppIconMenu.prototype = {
__proto__: PopupMenu.PopupMenu.prototype,
const AppIconMenu = new Lang.Class({
Name: 'AppIconMenu',
Extends: PopupMenu.PopupMenu,
_init: function(source) {
let side = St.Side.LEFT;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
side = St.Side.RIGHT;
PopupMenu.PopupMenu.prototype._init.call(this, source.actor, 0.5, side);
this.parent(source.actor, 0.5, side);
// We want to keep the item hovered while the menu is up
this.blockSourceEvents = true;
@ -723,5 +703,5 @@ AppIconMenu.prototype = {
}
this.close();
}
};
});
Signals.addSignalMethods(AppIconMenu.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Shell = imports.gi.Shell;
const Lang = imports.lang;
@ -6,11 +6,9 @@ const Signals = imports.signals;
const Main = imports.ui.main;
function AppFavorites() {
this._init();
}
const AppFavorites = new Lang.Class({
Name: 'AppFavorites',
AppFavorites.prototype = {
FAVORITE_APPS_KEY: 'favorite-apps',
_init: function() {
@ -122,7 +120,7 @@ AppFavorites.prototype = {
this._addFavorite(appId, pos);
}));
}
};
});
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const DBus = imports.dbus;
const Mainloop = imports.mainloop;
const Gio = imports.gi.Gio;
const Params = imports.misc.params;
@ -16,69 +15,58 @@ const SETTING_ENABLE_AUTOMOUNT = 'automount';
const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
const ConsoleKitSessionIface = {
name: 'org.freedesktop.ConsoleKit.Session',
methods: [{ name: 'IsActive',
inSignature: '',
outSignature: 'b' }],
signals: [{ name: 'ActiveChanged',
inSignature: 'b' }]
};
const ConsoleKitSessionIface = <interface name="org.freedesktop.ConsoleKit.Session">
<method name="IsActive">
<arg type="b" direction="out" />
</method>
<signal name="ActiveChanged">
<arg type="b" direction="out" />
</signal>
</interface>;
const ConsoleKitSessionProxy = DBus.makeProxyClass(ConsoleKitSessionIface);
const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
const ConsoleKitManagerIface = {
name: 'org.freedesktop.ConsoleKit.Manager',
methods: [{ name: 'GetCurrentSession',
inSignature: '',
outSignature: 'o' }]
};
const ConsoleKitManagerIface = <interface name="org.freedesktop.ConsoleKit.Manager">
<method name="GetCurrentSession">
<arg type="o" direction="out" />
</method>
</interface>;
const ConsoleKitManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ConsoleKitManagerIface);
function ConsoleKitManager() {
this._init();
};
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
g_interface_name: ConsoleKitManagerInfo.name,
g_interface_info: ConsoleKitManagerInfo,
g_name: 'org.freedesktop.ConsoleKit',
g_object_path: '/org/freedesktop/ConsoleKit/Manager',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
ConsoleKitManager.prototype = {
_init: function() {
this.sessionActive = true;
self.connect('notify::g-name-owner', function() {
if (self.g_name_owner) {
self.GetCurrentSessionRemote(function([session]) {
self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
DBus.system.proxifyObject(this,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
self.sessionActive = isActive;
});
self._ckSession.IsActiveRemote(function([isActive]) {
self.sessionActive = isActive;
});
});
} else {
self.sessionActive = true;
}
});
DBus.system.watch_name('org.freedesktop.ConsoleKit',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onManagerAppeared),
Lang.bind(this, this._onManagerVanished));
},
_onManagerAppeared: function(owner) {
this.GetCurrentSessionRemote(Lang.bind(this, this._onCurrentSession));
},
_onManagerVanished: function(oldOwner) {
this.sessionActive = true;
},
_onCurrentSession: function(session) {
this._ckSession = new ConsoleKitSessionProxy(DBus.system, 'org.freedesktop.ConsoleKit', session);
this._ckSession.connect
('ActiveChanged', Lang.bind(this, function(object, isActive) {
this.sessionActive = isActive;
}));
this._ckSession.IsActiveRemote(Lang.bind(this, function(isActive) {
this.sessionActive = isActive;
}));
}
};
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);
function AutomountManager() {
this._init();
self.init(null);
return self;
}
AutomountManager.prototype = {
const AutomountManager = new Lang.Class({
Name: 'AutomountManager',
_init: function() {
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
this._volumeQueue = [];
@ -86,9 +74,8 @@ AutomountManager.prototype = {
this.ckListener = new ConsoleKitManager();
this._ssProxy = new ScreenSaver.ScreenSaverProxy();
this._ssProxy.connect('ActiveChanged',
Lang.bind(this,
this._screenSaverActiveChanged));
this._ssProxy.connectSignal('ActiveChanged',
Lang.bind(this, this._screenSaverActiveChanged));
this._volumeMonitor = Gio.VolumeMonitor.get();
@ -111,7 +98,7 @@ AutomountManager.prototype = {
Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
},
_screenSaverActiveChanged: function(object, isActive) {
_screenSaverActiveChanged: function(object, senderName, [isActive]) {
if (!isActive) {
this._volumeQueue.forEach(Lang.bind(this, function(volume) {
this._checkAndMountVolume(volume);
@ -209,10 +196,14 @@ AutomountManager.prototype = {
}
}
// Volume is already mounted, don't bother.
if (volume.get_mount())
return;
if (!this._settings.get_boolean(SETTING_ENABLE_AUTOMOUNT) ||
!volume.should_automount() ||
!volume.can_mount()) {
// allow the autorun to run anyway; this can happen if the
// allow the autorun to run anyway; this can happen if the
// mount gets added programmatically later, even if
// should_automount() or can_mount() are false, like for
// blank optical media.
@ -275,4 +266,4 @@ AutomountManager.prototype = {
return false;
});
}
}
});

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
@ -62,31 +61,23 @@ function startAppForMount(app, mount) {
/******************************************/
const HotplugSnifferIface = {
name: 'org.gnome.Shell.HotplugSniffer',
methods: [{ name: 'SniffURI',
inSignature: 's',
outSignature: 'as' }]
};
const HotplugSnifferIface = <interface name="org.gnome.Shell.HotplugSniffer">
<method name="SniffURI">
<arg type="s" direction="in" />
<arg type="as" direction="out" />
</method>
</interface>;
const HotplugSniffer = function() {
this._init();
};
HotplugSniffer.prototype = {
_init: function() {
DBus.session.proxifyObject(this,
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {
return new HotplugSnifferProxy(Gio.DBus.session,
'org.gnome.Shell.HotplugSniffer',
'/org/gnome/Shell/HotplugSniffer');
},
};
DBus.proxifyPrototype(HotplugSniffer.prototype, HotplugSnifferIface);
function ContentTypeDiscoverer(callback) {
this._init(callback);
}
ContentTypeDiscoverer.prototype = {
const ContentTypeDiscoverer = new Lang.Class({
Name: 'ContentTypeDiscoverer',
_init: function(callback) {
this._callback = callback;
},
@ -114,9 +105,8 @@ ContentTypeDiscoverer.prototype = {
let root = mount.get_root();
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote
(root.get_uri(), DBus.CALL_FLAG_START,
Lang.bind(this, function(contentTypes) {
hotplugSniffer.SniffURIRemote(root.get_uri(),
Lang.bind(this, function([contentTypes]) {
this._emitCallback(mount, contentTypes);
}));
}
@ -144,13 +134,11 @@ ContentTypeDiscoverer.prototype = {
this._callback(mount, apps, contentTypes);
}
}
});
function AutorunManager() {
this._init();
}
const AutorunManager = new Lang.Class({
Name: 'AutorunManager',
AutorunManager.prototype = {
_init: function() {
this._volumeMonitor = Gio.VolumeMonitor.get();
@ -267,17 +255,14 @@ AutorunManager.prototype = {
+ ': ' + e.toString());
}
},
}
});
function AutorunResidentSource() {
this._init();
}
AutorunResidentSource.prototype = {
__proto__: MessageTray.Source.prototype,
const AutorunResidentSource = new Lang.Class({
Name: 'AutorunResidentSource',
Extends: MessageTray.Source,
_init: function() {
MessageTray.Source.prototype._init.call(this, _("Removable Devices"));
this.parent(_("Removable Devices"));
this._mounts = [];
@ -332,19 +317,14 @@ AutorunResidentSource.prototype = {
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
}
});
function AutorunResidentNotification(source) {
this._init(source);
}
AutorunResidentNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const AutorunResidentNotification = new Lang.Class({
Name: 'AutorunResidentNotification',
Extends: MessageTray.Notification,
_init: function(source) {
MessageTray.Notification.prototype._init.call(this, source,
source.title, null,
{ customContent: true });
this.parent(source, source.title, null, { customContent: true });
// set the notification as resident
this.setResident(true);
@ -418,13 +398,11 @@ AutorunResidentNotification.prototype = {
return item;
},
}
});
function AutorunTransientDispatcher() {
this._init();
}
const AutorunTransientDispatcher = new Lang.Class({
Name: 'AutorunTransientDispatcher',
AutorunTransientDispatcher.prototype = {
_init: function() {
this._sources = [];
this._settings = new Gio.Settings({ schema: SETTINGS_SCHEMA });
@ -491,7 +469,7 @@ AutorunTransientDispatcher.prototype = {
let app = null;
if (setting == AutorunSetting.RUN) {
app = Gio.app_info_get_default_for_type(type, false);
app = Gio.app_info_get_default_for_type(contentTypes[0], false);
} else if (setting == AutorunSetting.FILES) {
app = Gio.app_info_get_default_for_type('inode/directory', false);
}
@ -515,17 +493,14 @@ AutorunTransientDispatcher.prototype = {
// destroy the notification source
source.destroy();
}
}
});
function AutorunTransientSource(mount, apps) {
this._init(mount, apps);
}
AutorunTransientSource.prototype = {
__proto__: MessageTray.Source.prototype,
const AutorunTransientSource = new Lang.Class({
Name: 'AutorunTransientSource',
Extends: MessageTray.Source,
_init: function(mount, apps) {
MessageTray.Source.prototype._init.call(this, mount.get_name());
this.parent(mount.get_name());
this.mount = mount;
this.apps = apps;
@ -542,19 +517,14 @@ AutorunTransientSource.prototype = {
return new St.Icon({ gicon: this.mount.get_icon(),
icon_size: this.ICON_SIZE });
}
}
});
function AutorunTransientNotification(source) {
this._init(source);
}
AutorunTransientNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const AutorunTransientNotification = new Lang.Class({
Name: 'AutorunTransientNotification',
Extends: MessageTray.Notification,
_init: function(source) {
MessageTray.Notification.prototype._init.call(this, source,
source.title, null,
{ customContent: true });
this.parent(source, source.title, null, { customContent: true });
this._box = new St.BoxLayout({ style_class: 'hotplug-transient-box',
vertical: true });
@ -629,5 +599,5 @@ AutorunTransientNotification.prototype = {
return button;
}
}
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -21,11 +21,9 @@ const POPUP_ANIMATION_TIME = 0.15;
* placed. The arrow position may be controlled via setArrowOrigin().
*
*/
function BoxPointer(side, binProperties) {
this._init(side, binProperties);
}
const BoxPointer = new Lang.Class({
Name: 'BoxPointer',
BoxPointer.prototype = {
_init: function(arrowSide, binProperties) {
this._arrowSide = arrowSide;
this._arrowOrigin = 0;
@ -46,6 +44,7 @@ BoxPointer.prototype = {
this._yOffset = 0;
this._xPosition = 0;
this._yPosition = 0;
this._sourceAlignment = 0.5;
},
show: function(animate, onComplete) {
@ -75,7 +74,7 @@ BoxPointer.prototype = {
Tweener.addTween(this, { opacity: 255,
xOffset: 0,
yOffset: 0,
transition: "linear",
transition: 'linear',
onComplete: onComplete,
time: POPUP_ANIMATION_TIME });
},
@ -106,7 +105,7 @@ BoxPointer.prototype = {
Tweener.addTween(this, { opacity: 0,
xOffset: xOffset,
yOffset: yOffset,
transition: "linear",
transition: 'linear',
time: POPUP_ANIMATION_TIME,
onComplete: Lang.bind(this, function () {
this.actor.hide();
@ -180,7 +179,7 @@ BoxPointer.prototype = {
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped)
this._reposition(this._sourceActor, this._alignment);
this._reposition(this._sourceActor, this._arrowAlignment);
},
_drawBorder: function(area) {
@ -312,24 +311,37 @@ BoxPointer.prototype = {
this.actor.show();
this._sourceActor = sourceActor;
this._alignment = alignment;
this._arrowAlignment = alignment;
this._reposition(sourceActor, alignment);
},
setSourceAlignment: function(alignment) {
this._sourceAlignment = alignment;
if (!this._sourceActor)
return;
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.actor.show();
this._reposition(this._sourceActor, this._arrowAlignment);
},
_reposition: function(sourceActor, alignment) {
// Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) / 2;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) / 2;
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [minWidth, minHeight, natWidth, natHeight] = this.actor.get_preferred_size();
// We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is
// separated from its sourceActor
let primary = Main.layoutManager.primaryMonitor;
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
let themeNode = this.actor.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base');
@ -364,8 +376,8 @@ BoxPointer.prototype = {
case St.Side.BOTTOM:
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
resX = Math.max(resX, primary.x + 10);
resX = Math.min(resX, primary.x + primary.width - (10 + natWidth));
resX = Math.max(resX, monitor.x + 10);
resX = Math.min(resX, monitor.x + monitor.width - (10 + natWidth));
this.setArrowOrigin(sourceCenterX - resX);
break;
@ -373,8 +385,8 @@ BoxPointer.prototype = {
case St.Side.RIGHT:
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
resY = Math.max(resY, primary.y + 10);
resY = Math.min(resY, primary.y + primary.height - (10 + natHeight));
resY = Math.max(resY, monitor.y + 10);
resY = Math.min(resY, monitor.y + monitor.height - (10 + natHeight));
this.setArrowOrigin(sourceCenterY - resY);
break;
@ -438,4 +450,4 @@ BoxPointer.prototype = {
get opacity() {
return this.actor.opacity;
}
};
});

View File

@ -1,6 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
@ -156,28 +155,24 @@ function _getEventDayAbbreviation(dayNumber) {
// Abstraction for an appointment/event in a calendar
function CalendarEvent(date, end, summary, allDay) {
this._init(date, end, summary, allDay);
}
const CalendarEvent = new Lang.Class({
Name: 'CalendarEvent',
CalendarEvent.prototype = {
_init: function(date, end, summary, allDay) {
this.date = date;
this.end = end;
this.summary = summary;
this.allDay = allDay;
}
};
});
// Interface for appointments/events - e.g. the contents of a calendar
//
// First, an implementation with no events
function EmptyEventSource() {
this._init();
}
const EmptyEventSource = new Lang.Class({
Name: 'EmptyEventSource',
EmptyEventSource.prototype = {
_init: function() {
},
@ -192,33 +187,32 @@ EmptyEventSource.prototype = {
hasEvents: function(day) {
return false;
}
};
});
Signals.addSignalMethods(EmptyEventSource.prototype);
const CalendarServerIface = {
name: 'org.gnome.Shell.CalendarServer',
methods: [{ name: 'GetEvents',
inSignature: 'xxb',
outSignature: 'a(sssbxxa{sv})' }],
signals: [{ name: 'Changed',
inSignature: '' }]
};
const CalendarServerIface = <interface name="org.gnome.Shell.CalendarServer">
<method name="GetEvents">
<arg type="x" direction="in" />
<arg type="x" direction="in" />
<arg type="b" direction="in" />
<arg type="a(sssbxxa{sv})" direction="out" />
</method>
<signal name="Changed" />
</interface>;
const CalendarServer = function () {
this._init();
};
const CalendarServerInfo = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
CalendarServer.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.Shell.CalendarServer', '/org/gnome/Shell/CalendarServer');
}
};
function CalendarServer() {
var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
g_interface_name: CalendarServerInfo.name,
g_interface_info: CalendarServerInfo,
g_name: 'org.gnome.Shell.CalendarServer',
g_object_path: '/org/gnome/Shell/CalendarServer',
g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
// an implementation that reads data from a session bus service
function DBusEventSource(owner) {
this._init(owner);
self.init(null);
return self;
}
function _datesEqual(a, b) {
@ -239,18 +233,22 @@ function _dateIntervalsOverlap(a0, a1, b0, b1)
return true;
}
// an implementation that reads data from a session bus service
const DBusEventSource = new Lang.Class({
Name: 'DBusEventSource',
DBusEventSource.prototype = {
_init: function(owner) {
_init: function() {
this._resetCache();
this._dbusProxy = new CalendarServer(owner);
this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
this._dbusProxy = new CalendarServer();
this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
DBus.session.watch_name('org.gnome.Shell.CalendarServer',
false, // do not launch a name-owner if none exists
Lang.bind(this, this._onNameAppeared),
Lang.bind(this, this._onNameVanished));
this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
if (this._dbusProxy.g_name_owner)
this._onNameAppeared();
else
this._onNameVanished();
}));
},
_resetCache: function() {
@ -273,7 +271,7 @@ DBusEventSource.prototype = {
this._loadEvents(false);
},
_onEventsReceived: function(appointments) {
_onEventsReceived: function([appointments]) {
let newEvents = [];
if (appointments != null) {
for (let n = 0; n < appointments.length; n++) {
@ -296,9 +294,9 @@ DBusEventSource.prototype = {
_loadEvents: function(forceReload) {
if (this._curRequestBegin && this._curRequestEnd){
let callFlags = 0;
let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
if (forceReload)
callFlags |= DBus.CALL_FLAG_START;
callFlags = Gio.DBusCallFlags.NONE;
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
@ -339,17 +337,15 @@ DBusEventSource.prototype = {
return true;
}
};
});
Signals.addSignalMethods(DBusEventSource.prototype);
// Calendar:
// @eventSource: is an object implementing the EventSource API, e.g. the
// requestRange(), getEvents(), hasEvents() methods and the ::changed signal.
function Calendar(eventSource) {
this._init(eventSource);
}
const Calendar = new Lang.Class({
Name: 'Calendar',
Calendar.prototype = {
_init: function(eventSource) {
if (eventSource) {
this._eventSource = eventSource;
@ -615,15 +611,13 @@ Calendar.prototype = {
if (this._eventSource)
this._eventSource.requestRange(beginDate, iter, forceReload);
}
};
});
Signals.addSignalMethods(Calendar.prototype);
function EventsList(eventSource) {
this._init(eventSource);
}
const EventsList = new Lang.Class({
Name: 'EventsList',
EventsList.prototype = {
_init: function(eventSource) {
this.actor = new St.BoxLayout({ vertical: true, style_class: 'events-header-vbox'});
this._date = new Date();
@ -754,4 +748,4 @@ EventsList.prototype = {
this._showOtherDay(this._date);
}
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Folks = imports.gi.Folks
const Lang = imports.lang;
@ -20,13 +20,12 @@ function launchContact(id) {
/* This class represents a shown contact search result in the overview */
function Contact(id) {
this._init(id);
}
const Contact = new Lang.Class({
Name: 'Contact',
Contact.prototype = {
_init: function(id) {
this.individual = Shell.ContactSystem.get_default().get_individual(id);
this._contactSys = Shell.ContactSystem.get_default();
this.individual = this._contactSys.get_individual(id);
this.actor = new St.Bin({ style_class: 'contact',
reactive: true,
@ -56,7 +55,12 @@ Contact.prototype = {
x_align: St.Align.START,
y_align: St.Align.MIDDLE });
let aliasText = this.individual.alias || _("Unknown");
let email = this._contactSys.get_email_for_display(this.individual);
let aliasText = this.individual.alias ||
this.individual.full_name ||
this.individual.nickname ||
email ||
_("Unknown");
let aliasLabel = new St.Label({ text: aliasText,
style_class: 'contact-details-alias' });
details.add(aliasLabel, { x_fill: true,
@ -125,19 +129,16 @@ Contact.prototype = {
return tc.load_icon_name(null, 'avatar-default', St.IconType.FULLCOLOR, size);
}
},
};
});
/* Searches for and returns contacts */
function ContactSearchProvider() {
this._init();
}
ContactSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
const ContactSearchProvider = new Lang.Class({
Name: 'ContactSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("CONTACTS"));
this.parent(_("CONTACTS"));
this._contactSys = Shell.ContactSystem.get_default();
},
@ -176,4 +177,4 @@ ContactSearchProvider.prototype = {
activateResult: function(id, params) {
launchContact(id);
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
@ -22,11 +22,9 @@ const SortGroup = {
BOTTOM: 2
};
function CtrlAltTabManager() {
this._init();
}
const CtrlAltTabManager = new Lang.Class({
Name: 'CtrlAltTabManager',
CtrlAltTabManager.prototype = {
_init: function() {
this._items = [];
this._focusManager = St.FocusManager.get_for_stage(global.stage);
@ -134,17 +132,15 @@ CtrlAltTabManager.prototype = {
}));
}
}
};
});
function mod(a, b) {
return (a + b) % b;
}
function CtrlAltTabPopup() {
this._init();
}
const CtrlAltTabPopup = new Lang.Class({
Name: 'CtrlAltTabPopup',
CtrlAltTabPopup.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'ctrlAltTabPopup',
reactive: true });
@ -187,7 +183,7 @@ CtrlAltTabPopup.prototype = {
let [childMinHeight, childNaturalHeight] = this._switcher.actor.get_preferred_height(primary.width - hPadding);
let [childMinWidth, childNaturalWidth] = this._switcher.actor.get_preferred_width(childNaturalHeight);
childBox.x1 = Math.max(primary.x + leftPadding, primary.x + Math.floor((primary.width - childNaturalWidth) / 2));
childBox.x2 = Math.min(primary.width - hPadding, childBox.x1 + childNaturalWidth);
childBox.x2 = Math.min(primary.x + primary.width - hPadding, childBox.x1 + childNaturalWidth);
childBox.y1 = primary.y + Math.floor((primary.height - childNaturalHeight) / 2);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._switcher.actor.allocate(childBox, flags);
@ -303,17 +299,14 @@ CtrlAltTabPopup.prototype = {
this._selection = num;
this._switcher.highlight(num);
}
};
});
function CtrlAltTabSwitcher(items) {
this._init(items);
}
CtrlAltTabSwitcher.prototype = {
__proto__ : AltTab.SwitcherList.prototype,
const CtrlAltTabSwitcher = new Lang.Class({
Name: 'CtrlAltTabSwitcher',
Extends: AltTab.SwitcherList,
_init : function(items) {
AltTab.SwitcherList.prototype._init.call(this, true);
this.parent(true);
for (let i = 0; i < items.length; i++)
this._addIcon(items[i]);
@ -336,4 +329,4 @@ CtrlAltTabSwitcher.prototype = {
this.addItem(box, text);
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Signals = imports.signals;
@ -19,11 +19,9 @@ const DASH_ANIMATION_TIME = 0.2;
// A container like StBin, but taking the child's scale into account
// when requesting a size
function DashItemContainer() {
this._init();
}
const DashItemContainer = new Lang.Class({
Name: 'DashItemContainer',
DashItemContainer.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'dash-item-container' });
this.actor.connect('get-preferred-width',
@ -37,6 +35,7 @@ DashItemContainer.prototype = {
this.child = null;
this._childScale = 1;
this._childOpacity = 255;
this.animatingOut = false;
},
_allocate: function(actor, box, flags) {
@ -115,6 +114,7 @@ DashItemContainer.prototype = {
return;
}
this.animatingOut = true;
this.childScale = 1.0;
Tweener.addTween(this,
{ childScale: 0.0,
@ -155,17 +155,14 @@ DashItemContainer.prototype = {
get childOpacity() {
return this._childOpacity;
}
};
});
function RemoveFavoriteIcon() {
this._init();
}
RemoveFavoriteIcon.prototype = {
__proto__: DashItemContainer.prototype,
const RemoveFavoriteIcon = new Lang.Class({
Name: 'RemoveFavoriteIcon',
Extends: DashItemContainer,
_init: function() {
DashItemContainer.prototype._init.call(this);
this.parent();
this._iconBin = new St.Bin({ style_class: 'remove-favorite' });
this._iconActor = null;
@ -177,12 +174,6 @@ RemoveFavoriteIcon.prototype = {
this._iconBin._delegate = this;
this.setChild(this._iconBin);
this.hiding = false;
},
animateOutAndDestroy: function() {
DashItemContainer.prototype.animateOutAndDestroy.call(this);
this.hiding = true;
},
_createIcon: function(size) {
@ -223,28 +214,21 @@ RemoveFavoriteIcon.prototype = {
return true;
}
};
});
function DragPlaceholderItem() {
this._init();
}
DragPlaceholderItem.prototype = {
__proto__: DashItemContainer.prototype,
const DragPlaceholderItem = new Lang.Class({
Name: 'DragPlaceholderItem',
Extends: DashItemContainer,
_init: function() {
DashItemContainer.prototype._init.call(this);
this.setChild(new St.Bin({ style_class: 'dash-placeholder' }));
this.parent();
this.setChild(new St.Bin({ style_class: 'placeholder' }));
}
};
});
const Dash = new Lang.Class({
Name: 'Dash',
function Dash() {
this._init();
}
Dash.prototype = {
_init : function() {
this._maxHeight = -1;
this.iconSize = 64;
@ -314,15 +298,12 @@ Dash.prototype = {
_endDrag: function() {
this._clearDragPlaceholder();
if (this._favRemoveTarget) {
this._favRemoveTarget.actor.hide();
this._adjustIconSize();
this._favRemoveTarget.actor.show();
this._favRemoveTarget.animateOutAndDestroy();
this._favRemoveTarget.actor.connect('destroy', Lang.bind(this,
function() {
this._favRemoveTarget = null;
}));
this._adjustIconSize();
}
DND.removeDragMonitor(this._dragMonitor);
},
@ -401,8 +382,18 @@ Dash.prototype = {
},
_adjustIconSize: function() {
let children = this._box.get_children();
if (children.length == 0) {
// For the icon size, we only consider children which are "proper"
// icons (i.e. ignoring drag placeholders) and which are not
// animating out (which means they will be destroyed at the end of
// the animation)
let iconChildren = this._box.get_children().filter(function(actor) {
return actor._delegate.child &&
actor._delegate.child._delegate &&
actor._delegate.child._delegate.icon &&
!actor._delegate.animatingOut;
});
if (iconChildren.length == 0) {
this._box.add_style_pseudo_class('empty');
return;
}
@ -412,23 +403,45 @@ Dash.prototype = {
if (this._maxHeight == -1)
return;
let iconChildren = children.filter(function(actor) {
return actor.visible &&
actor._delegate.child &&
actor._delegate.child._delegate &&
actor._delegate.child._delegate.icon;
});
// Compute the amount of extra space (or missing space) we have
// per icon with the current icon size
let [minHeight, natHeight] = this.actor.get_preferred_height(-1);
let diff = (this._maxHeight - natHeight) / iconChildren.length;
let themeNode = this.actor.get_theme_node();
let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
x2: 42 /* whatever */,
y2: this._maxHeight });
let maxContent = themeNode.get_content_box(maxAllocation);
let availHeight = maxContent.y2 - maxContent.y1;
let spacing = themeNode.get_length('spacing');
let firstIcon = iconChildren[0]._delegate.child._delegate.icon;
let minHeight, natHeight;
// Enforce the current icon size during the size request if
// the icon is animating
if (firstIcon._animating) {
let [currentWidth, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_size(this.iconSize, this.iconSize);
[minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
firstIcon.icon.set_size(currentWidth, currentHeight);
} else {
[minHeight, natHeight] = iconChildren[0].get_preferred_height(-1);
}
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (natHeight - this.iconSize) +
(iconChildren.length - 1) * spacing;
let availSize = availHeight / iconChildren.length;
let iconSizes = [ 16, 22, 24, 32, 48, 64 ];
let newIconSize = 16;
for (let i = 0; i < iconSizes.length; i++) {
if (iconSizes[i] < this.iconSize + diff)
if (iconSizes[i] < availSize)
newIconSize = iconSizes[i];
}
@ -459,11 +472,15 @@ Dash.prototype = {
icon.icon.set_size(icon.icon.width * scale,
icon.icon.height * scale);
icon._animating = true;
Tweener.addTween(icon.icon,
{ width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
transition: 'easeOutQuad'
transition: 'easeOutQuad',
onComplete: function() {
icon._animating = false;
}
});
}
},
@ -566,29 +583,7 @@ Dash.prototype = {
this._box.insert_actor(addedItems[i].item.actor,
addedItems[i].pos);
// Hide removed actors to not take them into account
// when adjusting the icon size ...
for (let i = 0; i < removedActors.length; i++)
removedActors[i].hide();
// ... and do the same for the remove target if necessary
if (this._favRemoveTarget && this._favRemoveTarget.hiding)
this._favRemoveTarget.actor.hide();
this._adjustIconSize();
if (this._favRemoveTarget && this._favRemoveTarget.hiding)
this._favRemoveTarget.actor.show();
// Skip animations on first run when adding the initial set
// of items, to avoid all items zooming in at once
if (!this._shownInitially) {
this._shownInitially = true;
return;
}
for (let i = 0; i < removedActors.length; i++) {
removedActors[i].show();
let item = removedActors[i]._delegate;
// Don't animate item removal when the overview is hidden
@ -598,6 +593,15 @@ Dash.prototype = {
item.actor.destroy();
}
this._adjustIconSize();
// Skip animations on first run when adding the initial set
// of items, to avoid all items zooming in at once
if (!this._shownInitially) {
this._shownInitially = true;
return;
}
// Don't animate item addition when the overview is hidden
if (!Main.overview.visible)
return;
@ -746,6 +750,6 @@ Dash.prototype = {
return true;
}
};
});
Signals.addSignalMethods(Dash.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
@ -40,12 +40,9 @@ function _onVertSepRepaint (area)
cr.stroke();
};
function DateMenuButton() {
this._init.apply(this, arguments);
}
DateMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
const DateMenuButton = new Lang.Class({
Name: 'DateMenuButton',
Extends: PanelMenu.Button,
_init: function(params) {
params = Params.parse(params, { showEvents: true });
@ -57,7 +54,7 @@ DateMenuButton.prototype = {
let menuAlignment = 0.25;
if (St.Widget.get_default_direction() == St.TextDirection.RTL)
menuAlignment = 1.0 - menuAlignment;
PanelMenu.Button.prototype._init.call(this, menuAlignment);
this.parent(menuAlignment);
this._clock = new St.Label();
this.actor.add_actor(this._clock);
@ -239,4 +236,4 @@ DateMenuButton.prototype = {
}
}
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
@ -69,11 +69,9 @@ function removeDragMonitor(monitor) {
}
}
function _Draggable(actor, params) {
this._init(actor, params);
}
const _Draggable = new Lang.Class({
Name: 'Draggable',
_Draggable.prototype = {
_init : function(actor, params) {
params = Params.parse(params, { manualMode: false,
restoreOnSuccess: false,
@ -596,7 +594,7 @@ _Draggable.prototype = {
this._dragActor = undefined;
currentDraggable = null;
}
};
});
Signals.addSignalMethods(_Draggable.prototype);

View File

@ -1,19 +1,16 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DocInfo = imports.misc.docInfo;
const Lang = imports.lang;
const Params = imports.misc.params;
const Search = imports.ui.search;
function DocSearchProvider() {
this._init();
}
DocSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
const DocSearchProvider = new Lang.Class({
Name: 'DocSearchProvider',
Extends: Search.SearchProvider,
_init: function(name) {
Search.SearchProvider.prototype._init.call(this, _("RECENT ITEMS"));
this.parent(_("RECENT ITEMS"));
this._docManager = DocInfo.getDocManager();
},
@ -44,4 +41,4 @@ DocSearchProvider.prototype = {
getSubsearchResultSet: function(previousResults, terms) {
return this._docManager.subsearch(previousResults, terms);
}
};
});

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2010 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
@ -18,19 +18,19 @@
* 02111-1307, USA.
*/
const DBus = imports.dbus;
const Lang = imports.lang;
const Signals = imports.signals;
const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const GnomeSession = imports.misc.gnomeSession
const GnomeSession = imports.misc.gnomeSession;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
@ -43,22 +43,23 @@ const _DIALOG_ICON_SIZE = 32;
const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = {
name: 'org.gnome.SessionManager.EndSessionDialog',
methods: [{ name: 'Open',
inSignature: 'uuuao',
outSignature: ''
}
],
signals: [{ name: 'Canceled',
inSignature: '',
}],
properties: []
};
const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
<method name="Open">
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="u" direction="in" />
<arg type="ao" direction="in" />
</method>
<signal name="ConfirmedLogout" />
<signal name="ConfirmedReboot" />
<signal name="ConfirmedShutdown" />
<signal name="Canceled" />
<signal name="Closed" />
</interface>;
const logoutDialogContent = {
subjectWithUser: _("Log Out %s"),
subject: _("Log Out"),
subjectWithUser: C_("title", "Log Out %s"),
subject: C_("title", "Log Out"),
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: function(user, seconds) {
return ngettext("%s will be logged out automatically in %d second.",
@ -72,12 +73,12 @@ const logoutDialogContent = {
},
endDescription: _("Logging out of the system."),
confirmButtons: [{ signal: 'ConfirmedLogout',
label: _("Log Out") }],
label: C_("button", "Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon'
};
const shutdownDialogContent = {
subject: _("Power Off"),
subject: C_("title", "Power Off"),
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will power off automatically in %d second.",
@ -86,15 +87,15 @@ const shutdownDialogContent = {
},
endDescription: _("Powering off the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: _("Restart") },
label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown',
label: _("Power Off") }],
label: C_("button", "Power Off") }],
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
const restartDialogContent = {
subject: _("Restart"),
subject: C_("title", "Restart"),
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will restart automatically in %d second.",
@ -103,7 +104,7 @@ const restartDialogContent = {
},
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: _("Restart") }],
label: C_("button", "Restart") }],
iconName: 'system-shutdown',
iconStyleClass: 'end-session-dialog-shutdown-icon'
};
@ -141,11 +142,9 @@ function findAppFromInhibitor(inhibitor) {
return app;
}
function ListItem(app, reason) {
this._init(app, reason);
}
const ListItem = new Lang.Class({
Name: 'ListItem',
ListItem.prototype = {
_init: function(app, reason) {
this._app = app;
this._reason = reason;
@ -191,7 +190,7 @@ ListItem.prototype = {
this.emit('activate');
this._app.activate();
}
};
});
Signals.addSignalMethods(ListItem.prototype);
// The logout timer only shows updates every 10 seconds
@ -229,29 +228,19 @@ function _setLabelText(label, text) {
}
}
function EndSessionDialog() {
if (_endSessionDialog == null) {
this._init();
DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
this);
_endSessionDialog = this;
}
return _endSessionDialog;
}
function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
let dialog = new EndSessionDialog();
_endSessionDialog = new EndSessionDialog();
}
EndSessionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const EndSessionDialog = new Lang.Class({
Name: 'EndSessionDialog',
Extends: ModalDialog.ModalDialog,
_init: function() {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'end-session-dialog' });
this.parent({ styleClass: 'end-session-dialog' });
this._user = AccountsService.UserManager.get_default().get_user(GLib.get_user_name());
@ -326,6 +315,9 @@ EndSessionDialog.prototype = {
if (this._applicationList.get_children().length == 0)
scrollView.hide();
}));
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
},
_onDestroy: function() {
@ -439,26 +431,20 @@ EndSessionDialog.prototype = {
},
close: function() {
ModalDialog.ModalDialog.prototype.close.call(this);
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Closed', '', []);
this.parent();
this._dbusImpl.emit_signal('Closed', null);
},
cancel: function() {
this._stopTimer();
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
'Canceled', '', []);
this._dbusImpl.emit_signal('Canceled', null);
this.close(global.get_current_time());
},
_confirm: function(signal) {
this._fadeOutDialog();
this._stopTimer();
DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
'org.gnome.SessionManager.EndSessionDialog',
signal, '', []);
this._dbusImpl.emit_signal(signal, null);
},
_onOpened: function() {
@ -510,39 +496,41 @@ EndSessionDialog.prototype = {
this._updateContent();
},
OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
OpenAsync: function(parameters, invocation) {
let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._inhibitors = [];
this._applicationList.destroy_children();
this._type = type;
if (!(this._type in DialogContent))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
if (!(this._type in DialogContent)) {
invocation.report_dbus_error('org.gnome.Shell.ModalDialog.TypeError',
"Unknown dialog type requested");
return;
}
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
this._onInhibitorLoaded(proxy);
}));
inhibitor.connect('is-loaded',
Lang.bind(this, function() {
this._onInhibitorLoaded(inhibitor);
}));
this._inhibitors.push(inhibitor);
}
this._updateButtons();
if (!this.open(timestamp))
throw new DBus.DBusError('org.gnome.Shell.ModalDialog.GrabError',
"Cannot grab pointer and keyboard");
if (!this.open(timestamp)) {
invocation.report_dbus_error('org.gnome.Shell.ModalDialog.GrabError',
"Cannot grab pointer and keyboard");
return;
}
this._updateContent();
let signalId = this.connect('opened',
Lang.bind(this, function() {
callback();
invocation.return_value(null);
this.disconnect(signalId);
}));
}
};
DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
imports.gi.versions.Clutter = '1.0';
imports.gi.versions.Gio = '2.0';

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
@ -22,6 +22,7 @@ const ExtensionState = {
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
@ -62,6 +63,9 @@ const extensionMeta = {};
const extensions = {};
// Maps uuid -> extension state object (returned from init())
const extensionStateObjs = {};
// Contains the order that extensions were enabled in.
const extensionOrder = [];
// Arrays of uuids
var enabledExtensions;
// GFile for user extensions
@ -212,6 +216,27 @@ function disableExtension(uuid) {
let extensionState = extensionStateObjs[uuid];
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
let orderIdx = extensionOrder.indexOf(uuid);
let order = extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
extensionStateObjs[uuid].disable();
} catch(e) {
logExtensionError(uuid, e.toString());
}
}
try {
extensionState.disable();
} catch(e) {
@ -219,6 +244,17 @@ function disableExtension(uuid) {
return;
}
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
try {
extensionStateObjs[uuid].enable();
} catch(e) {
logExtensionError(uuid, e.toString());
}
}
extensionOrder.splice(orderIdx, 1);
meta.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', meta);
}
@ -228,11 +264,18 @@ function enableExtension(uuid) {
if (!meta)
return;
if (meta.state == ExtensionState.INITIALIZED) {
loadExtension(meta.dir, meta.type, true);
return;
}
if (meta.state != ExtensionState.DISABLED)
return;
let extensionState = extensionStateObjs[uuid];
extensionOrder.push(uuid);
try {
extensionState.enable();
} catch(e) {
@ -254,7 +297,7 @@ function logExtensionError(uuid, message, state) {
state: state });
}
function loadExtension(dir, enabled, type) {
function loadExtension(dir, type, enabled) {
let info;
let uuid = dir.get_basename();
@ -289,7 +332,7 @@ function loadExtension(dir, enabled, type) {
}
if (extensions[uuid] != undefined) {
logExtensionError(uuid, "extension already loaded");
logExtensionError(uuid, 'extension already loaded');
return;
}
@ -303,14 +346,9 @@ function loadExtension(dir, enabled, type) {
return;
}
if (!versionCheck(meta['shell-version'], Config.PACKAGE_VERSION) ||
(meta['js-version'] && !versionCheck(meta['js-version'], Config.GJS_VERSION))) {
logExtensionError(uuid, 'extension is not compatible with current GNOME Shell and/or GJS version');
return;
}
extensionMeta[uuid] = meta;
meta.type = type;
meta.dir = dir;
meta.path = dir.get_path();
meta.error = '';
@ -324,6 +362,11 @@ function loadExtension(dir, enabled, type) {
return;
}
if (!enabled) {
meta.state = ExtensionState.INITIALIZED;
return;
}
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
logExtensionError(uuid, 'Missing extension.js');
@ -383,8 +426,7 @@ function loadExtension(dir, enabled, type) {
meta.state = ExtensionState.DISABLED;
if (enabled)
enableExtension(uuid);
enableExtension(uuid);
_signals.emit('extension-loaded', meta.uuid);
_signals.emit('extension-state-changed', meta);
@ -444,13 +486,12 @@ function _loadExtensionsIn(dir, type) {
let name = info.get_name();
let child = dir.get_child(name);
let enabled = enabledExtensions.indexOf(name) != -1;
loadExtension(child, enabled, type);
loadExtension(child, type, enabled);
}
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';
@ -458,17 +499,15 @@ function loadExtensions() {
if (dir.query_exists(null))
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
}
_loadExtensionsIn(userExtensionsDir, ExtensionType.PER_USER);
}
function InstallExtensionDialog(uuid, version_tag, name) {
this._init(uuid, version_tag, name);
}
InstallExtensionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const InstallExtensionDialog = new Lang.Class({
Name: 'InstallExtensionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(uuid, version_tag, name) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
this.parent({ styleClass: 'extension-dialog' });
this._uuid = uuid;
this._version_tag = version_tag;
@ -528,4 +567,4 @@ InstallExtensionDialog.prototype = {
this.close(global.get_current_time());
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
@ -10,11 +10,9 @@ const Params = imports.misc.params;
const ICON_SIZE = 48;
function BaseIcon(label, createIcon) {
this._init(label, createIcon);
}
const BaseIcon = new Lang.Class({
Name: 'BaseIcon',
BaseIcon.prototype = {
_init : function(label, params) {
params = Params.parse(params, { createIcon: null,
setSizeManually: false,
@ -149,13 +147,11 @@ BaseIcon.prototype = {
this._createIconTexture(size);
}
};
});
function IconGrid(params) {
this._init(params);
}
const IconGrid = new Lang.Class({
Name: 'IconGrid',
IconGrid.prototype = {
_init: function(params) {
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
@ -324,4 +320,4 @@ IconGrid.prototype = {
visibleItemsCount: function() {
return this._grid.get_children().length - this._grid.get_n_skip_paint();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Caribou = imports.gi.Caribou;
const Clutter = imports.gi.Clutter;
@ -39,34 +39,31 @@ const PRETTY_KEYS = {
'Alt_L': 'Alt'
};
const CaribouKeyboardIface = {
name: 'org.gnome.Caribou.Keyboard',
methods: [ { name: 'Show',
inSignature: 'u',
outSignature: ''
},
{ name: 'Hide',
inSignature: 'u',
outSignature: ''
},
{ name: 'SetCursorLocation',
inSignature: 'iiii',
outSignature: ''
},
{ name: 'SetEntryLocation',
inSignature: 'iiii',
outSignature: ''
} ],
properties: [ { name: 'Name',
signature: 's',
access: 'read' } ]
};
const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
<method name='Show'>
<arg type='u' direction='in' />
</method>
<method name='Hide'>
<arg type='u' direction='in' />
</method>
<method name='SetCursorLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<method name='SetEntryLocation'>
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
<arg type='i' direction='in' />
</method>
<property name='Name' access='read' type='s' />
</interface>;
function Key() {
this._init.apply(this, arguments);
}
const Key = new Lang.Class({
Name: 'Key',
Key.prototype = {
_init : function(key) {
this._key = key;
@ -75,7 +72,7 @@ Key.prototype = {
this._extended_keys = this._key.get_extended_keys();
this._extended_keyboard = null;
if (this._key.name == "Control_L" || this._key.name == "Alt_L")
if (this._key.name == 'Control_L' || this._key.name == 'Alt_L')
this._key.latch = true;
this._key.connect('key-pressed', Lang.bind(this, function ()
@ -192,15 +189,15 @@ Key.prototype = {
this._boxPointer.hide(true);
}
}
};
});
function Keyboard() {
this._init.apply(this, arguments);
}
const Keyboard = new Lang.Class({
// HACK: we can't set Name, because it collides with Name dbus property
// Name: 'Keyboard',
Keyboard.prototype = {
_init: function () {
DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
this.actor = null;
@ -218,7 +215,7 @@ Keyboard.prototype = {
this._redraw();
},
_settingsChanged: function () {
_settingsChanged: function (settings, key) {
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
if (!this._enableKeyboard && !this._keyboard)
return;
@ -228,9 +225,20 @@ Keyboard.prototype = {
if (this._keyboard)
this._destroyKeyboard();
if (this._enableKeyboard)
this._setupKeyboard();
else
if (this._enableKeyboard) {
// If we've been called because the setting actually just
// changed to true (as opposed to being called from
// this._init()), then we want to pop up the keyboard.
let showKeyboard = (settings != null);
// However, caribou-gtk-module or this._onKeyFocusChanged
// will probably immediately tell us to hide it, so we
// have to fake things out so we'll ignore that request.
if (showKeyboard)
this._timestamp = global.display.get_current_time_roundtrip() + 1;
this._setupKeyboard(showKeyboard);
} else
Main.layoutManager.hideKeyboard(true);
},
@ -246,7 +254,7 @@ Keyboard.prototype = {
this._destroySource();
},
_setupKeyboard: function() {
_setupKeyboard: function(show) {
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
@ -263,20 +271,26 @@ Keyboard.prototype = {
this._keyboardNotifyId = this._keyboard.connect('notify::active-group', Lang.bind(this, this._onGroupChanged));
this._focusNotifyId = global.stage.connect('notify::key-focus', Lang.bind(this, this._onKeyFocusChanged));
this._createSource();
if (show)
this.show();
else
this._createSource();
},
_onKeyFocusChanged: function () {
let focus = global.stage.key_focus;
// Showing an extended key popup will grab focus, but ignore that
if (focus && focus._extended_keys)
// Showing an extended key popup and clicking a key from the extended keys
// will grab focus, but ignore that
if (focus && (focus._extended_keys || (focus._key && focus._key.extended_key)))
return;
let time = global.get_current_time();
if (focus instanceof Clutter.Text)
this.show();
this.Show(time);
else
this.hide();
this.Hide(time);
},
_addKeys: function () {
@ -305,7 +319,8 @@ Keyboard.prototype = {
},
_getTrayIcon: function () {
let trayButton = new St.Button ({ label: "tray", style_class: 'keyboard-key' });
let trayButton = new St.Button ({ label: _("tray"),
style_class: 'keyboard-key' });
trayButton.key_width = 1;
trayButton.connect('button-press-event', Lang.bind(this, function () {
Main.messageTray.toggle();
@ -339,7 +354,7 @@ Keyboard.prototype = {
right_box.add(button.actor);
else
left_box.add(button.actor);
if (key.name == "Caribou_Prefs") {
if (key.name == 'Caribou_Prefs') {
key.connect('key-released', Lang.bind(this, this.hide));
// Add new key for hiding message tray
@ -476,6 +491,9 @@ Keyboard.prototype = {
// D-Bus methods
Show: function(timestamp) {
if (!this._enableKeyboard)
return;
if (timestamp - this._timestamp < 0)
return;
@ -484,6 +502,9 @@ Keyboard.prototype = {
},
Hide: function(timestamp) {
if (!this._enableKeyboard)
return;
if (timestamp - this._timestamp < 0)
return;
@ -492,29 +513,31 @@ Keyboard.prototype = {
},
SetCursorLocation: function(x, y, w, h) {
if (!this._enableKeyboard)
return;
// this._setLocation(x, y);
},
SetEntryLocation: function(x, y, w, h) {
if (!this._enableKeyboard)
return;
// this._setLocation(x, y);
},
get Name() {
return 'gnome-shell';
}
};
DBus.conformExport(Keyboard.prototype, CaribouKeyboardIface);
});
function KeyboardSource() {
this._init.apply(this, arguments);
}
KeyboardSource.prototype = {
__proto__: MessageTray.Source.prototype,
const KeyboardSource = new Lang.Class({
Name: 'KeyboardSource',
Extends: MessageTray.Source,
_init: function(keyboard) {
this.parent(_("Keyboard"));
this._keyboard = keyboard;
MessageTray.Source.prototype._init.call(this, _("Keyboard"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -525,7 +548,7 @@ KeyboardSource.prototype = {
icon_size: this.ICON_SIZE });
},
handleSummaryClick: function() {
handleSummaryClick: function() {
let event = Clutter.get_current_event();
if (event.type() != Clutter.EventType.BUTTON_RELEASE)
return false;
@ -537,4 +560,4 @@ KeyboardSource.prototype = {
open: function() {
this._keyboard.show();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -17,11 +17,9 @@ const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STARTUP_ANIMATION_TIME = 0.2;
const KEYBOARD_ANIMATION_TIME = 0.5;
function LayoutManager() {
this._init.apply(this, arguments);
}
const LayoutManager = new Lang.Class({
Name: 'LayoutManager',
LayoutManager.prototype = {
_init: function () {
this._rtl = (St.Widget.get_default_direction() == St.TextDirection.RTL);
this.monitors = [];
@ -216,10 +214,10 @@ LayoutManager.prototype = {
let monitorLeft = monitor.x, monitorRight = monitor.x + monitor.width;
let primaryLeft = primary.x, primaryRight = primary.x + primary.width;
if ((monitorLeft >= primaryLeft && monitorLeft <= primaryRight) ||
(monitorRight >= primaryLeft && monitorRight <= primaryRight) ||
(primaryLeft >= monitorLeft && primaryLeft <= monitorRight) ||
(primaryRight >= monitorLeft && primaryRight <= monitorRight))
if ((monitorLeft >= primaryLeft && monitorLeft < primaryRight) ||
(monitorRight > primaryLeft && monitorRight <= primaryRight) ||
(primaryLeft >= monitorLeft && primaryLeft < monitorRight) ||
(primaryRight > monitorLeft && primaryRight <= monitorRight))
return true;
return false;
@ -369,8 +367,12 @@ LayoutManager.prototype = {
// Removes @actor from the chrome
removeChrome: function(actor) {
this._chrome.removeActor(actor);
},
findMonitorForActor: function(actor) {
return this._chrome.findMonitorForActor(actor);
}
};
});
Signals.addSignalMethods(LayoutManager.prototype);
@ -378,11 +380,9 @@ Signals.addSignalMethods(LayoutManager.prototype);
//
// This class manages a "hot corner" that can toggle switching to
// overview.
function HotCorner() {
this._init();
}
const HotCorner = new Lang.Class({
Name: 'HotCorner',
HotCorner.prototype = {
_init : function() {
// We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding
@ -544,7 +544,7 @@ HotCorner.prototype = {
return true;
return false;
}
};
});
// This manages the shell "chrome"; the UI that's visible in the
@ -557,11 +557,9 @@ const defaultParams = {
affectsInputRegion: true
};
function Chrome() {
this._init.apply(this, arguments);
}
const Chrome = new Lang.Class({
Name: 'Chrome',
Chrome.prototype = {
_init: function(layoutManager) {
this._layoutManager = layoutManager;
@ -583,12 +581,13 @@ Chrome.prototype = {
this._screenSaverActive = false;
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
function(result, err) {
if (!err)
this._onScreenSaverActiveChanged(this._screenSaverProxy, result);
}));
this._screenSaverProxy.connectSignal('ActiveChanged', Lang.bind(this, function(proxy, senderName, [isActive]) {
this._onScreenSaverActiveChanged(isActive);
}));
this._screenSaverProxy.GetActiveRemote(Lang.bind(this, function(result, err) {
if (!err)
this._onScreenSaverActiveChanged(result[0]);
}));
this._relayout();
},
@ -621,7 +620,7 @@ Chrome.prototype = {
// 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])
if (!params.hasOwnProperty(prop))
params[prop] = ancestorData[prop];
}
@ -700,7 +699,7 @@ Chrome.prototype = {
else if (this._inOverview)
visible = true;
else if (!actorData.visibleInFullscreen &&
this._findMonitorForActor(actorData.actor).inFullscreen)
this.findMonitorForActor(actorData.actor).inFullscreen)
visible = false;
else
visible = true;
@ -729,7 +728,7 @@ Chrome.prototype = {
this._queueUpdateRegions();
},
_onScreenSaverActiveChanged: function(proxy, screenSaverActive) {
_onScreenSaverActiveChanged: function(screenSaverActive) {
this._screenSaverActive = screenSaverActive;
this._updateVisibility();
this._queueUpdateRegions();
@ -762,7 +761,7 @@ Chrome.prototype = {
// This call guarantees that we return some monitor to simplify usage of it
// In practice all tracked actors should be visible on some monitor anyway
_findMonitorForActor: function(actor) {
findMonitorForActor: function(actor) {
let [x, y] = actor.get_transformed_position();
let [w, h] = actor.get_transformed_size();
let monitor = this._findMonitorForRect(x, y, w, h);
@ -821,6 +820,18 @@ Chrome.prototype = {
monitor.inFullscreen = true;
}
if (layer == Meta.StackLayer.OVERRIDE_REDIRECT) {
// Check whether the window is screen sized
let isScreenSized =
(window.x == 0 && window.y == 0 &&
window.width == global.screen_width &&
window.height == global.screen_height);
if (isScreenSized) {
for (let i = 0; i < this._monitors.length; i++)
this._monitors[i].inFullscreen = true;
}
// Or whether it is monitor sized
let monitor = this._findMonitorForWindow(window);
if (monitor &&
window.x <= monitor.x &&
@ -964,4 +975,4 @@ Chrome.prototype = {
return false;
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Meta = imports.gi.Meta;
@ -30,11 +30,9 @@ const Tweener = imports.ui.tweener;
* @container and will track any changes in its size. You can override
* this by passing an explicit width and height in @params.
*/
function Lightbox(container, params) {
this._init(container, params);
}
const Lightbox = new Lang.Class({
Name: 'Lightbox',
Lightbox.prototype = {
_init : function(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
@ -196,4 +194,4 @@ Lightbox.prototype = {
this.highlight(null);
}
};
});

View File

@ -1,14 +1,12 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
const St = imports.gi.St;
function Link(props) {
this._init(props);
}
const Link = new Lang.Class({
Name: 'Link',
Link.prototype = {
_init : function(props) {
let realProps = { reactive: true,
track_hover: true,
@ -19,6 +17,5 @@ Link.prototype = {
this.actor = new St.Button(realProps);
}
};
});
Signals.addSignalMethods(Link.prototype);

View File

@ -1,8 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Cogl = imports.gi.Cogl;
const GConf = imports.gi.GConf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
@ -17,8 +16,10 @@ const Mainloop = imports.mainloop;
const History = imports.misc.history;
const ExtensionSystem = imports.ui.extensionSystem;
const Link = imports.ui.link;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
const JsParse = imports.misc.jsParse;
/* Imports...feel free to add here as needed */
var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
@ -40,12 +41,88 @@ var commandHeader = 'const Clutter = imports.gi.Clutter; ' +
'const r = Lang.bind(Main.lookingGlass, Main.lookingGlass.getResult); ';
const HISTORY_KEY = 'looking-glass-history';
// Time between tabs for them to count as a double-tab event
const AUTO_COMPLETE_DOUBLE_TAB_DELAY = 500;
const AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION = 0.2;
const AUTO_COMPLETE_GLOBAL_KEYWORDS = _getAutoCompleteGlobalKeywords();
function Notebook() {
this._init();
function _getAutoCompleteGlobalKeywords() {
const keywords = ['true', 'false', 'null', 'new'];
// Don't add the private properties of window (i.e., ones starting with '_')
const windowProperties = Object.getOwnPropertyNames(window).filter(function(a){ return a.charAt(0) != '_' });
const headerProperties = JsParse.getDeclaredConstants(commandHeader);
return keywords.concat(windowProperties).concat(headerProperties);
}
Notebook.prototype = {
const AutoComplete = new Lang.Class({
Name: 'AutoComplete',
_init: function(entry) {
this._entry = entry;
this._entry.connect('key-press-event', Lang.bind(this, this._entryKeyPressEvent));
this._lastTabTime = global.get_current_time();
},
_processCompletionRequest: function(event) {
if (event.completions.length == 0) {
return;
}
// Unique match = go ahead and complete; multiple matches + single tab = complete the common starting string;
// multiple matches + double tab = emit a suggest event with all possible options
if (event.completions.length == 1) {
this.additionalCompletionText(event.completions[0], event.attrHead);
this.emit('completion', { completion: event.completions[0], type: 'whole-word' });
} else if (event.completions.length > 1 && event.tabType === 'single') {
let commonPrefix = JsParse.getCommonPrefix(event.completions);
if (commonPrefix.length > 0) {
this.additionalCompletionText(commonPrefix, event.attrHead);
this.emit('completion', { completion: commonPrefix, type: 'prefix' });
this.emit('suggest', { completions: event.completions});
}
} else if (event.completions.length > 1 && event.tabType === 'double') {
this.emit('suggest', { completions: event.completions});
}
},
_entryKeyPressEvent: function(actor, event) {
let cursorPos = this._entry.clutter_text.get_cursor_position();
let text = this._entry.get_text();
if (cursorPos != -1) {
text = text.slice(0, cursorPos);
}
if (event.get_key_symbol() == Clutter.Tab) {
let [completions, attrHead] = JsParse.getCompletions(text, commandHeader, AUTO_COMPLETE_GLOBAL_KEYWORDS);
let currTime = global.get_current_time();
if ((currTime - this._lastTabTime) < AUTO_COMPLETE_DOUBLE_TAB_DELAY) {
this._processCompletionRequest({ tabType: 'double',
completions: completions,
attrHead: attrHead });
} else {
this._processCompletionRequest({ tabType: 'single',
completions: completions,
attrHead: attrHead });
}
this._lastTabTime = currTime;
}
},
// Insert characters of text not already included in head at cursor position. i.e., if text="abc" and head="a",
// the string "bc" will be appended to this._entry
additionalCompletionText: function(text, head) {
let additionalCompletionText = text.slice(head.length);
let cursorPos = this._entry.clutter_text.get_cursor_position();
this._entry.clutter_text.insert_text(additionalCompletionText, cursorPos);
}
});
Signals.addSignalMethods(AutoComplete.prototype);
const Notebook = new Lang.Class({
Name: 'Notebook',
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
@ -150,25 +227,40 @@ Notebook.prototype = {
return;
let vAdjust = tabData.scrollView.vscroll.adjustment;
vAdjust.value = vAdjust.upper - vAdjust.page_size;
},
nextTab: function() {
let nextIndex = this._selectedIndex;
if (nextIndex < this._tabs.length - 1) {
++nextIndex;
}
this.selectIndex(nextIndex);
},
prevTab: function() {
let prevIndex = this._selectedIndex;
if (prevIndex > 0) {
--prevIndex;
}
this.selectIndex(prevIndex);
}
};
});
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
if (typeof(o) == typeof(objectToString)) {
// special case this since the default is way, way too verbose
return "<js function>";
return '<js function>';
} else {
return "" + o;
return '' + o;
}
}
function ObjLink(o, title) {
this._init(o, title);
}
ObjLink.prototype = {
__proto__: Link.Link,
const ObjLink = new Lang.Class({
Name: 'ObjLink',
Extends: Link.Link,
_init: function(o, title) {
let text;
@ -178,7 +270,8 @@ ObjLink.prototype = {
text = objectToString(o);
text = GLib.markup_escape_text(text, -1);
this._obj = o;
Link.Link.prototype._init.call(this, { label: text });
this.parent({ label: text });
this.actor.get_child().single_line_mode = true;
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
},
@ -186,13 +279,11 @@ ObjLink.prototype = {
_onClicked: function (link) {
Main.lookingGlass.inspectObject(this._obj, this.actor);
}
};
});
function Result(command, o, index) {
this._init(command, o, index);
}
const Result = new Lang.Class({
Name: 'Result',
Result.prototype = {
_init : function(command, o, index) {
this.index = index;
this.o = o;
@ -214,13 +305,11 @@ Result.prototype = {
padBin.add_actor(line);
this.actor.add(padBin);
}
};
});
function WindowList() {
this._init();
}
const WindowList = new Lang.Class({
Name: 'WindowList',
WindowList.prototype = {
_init : function () {
this.actor = new St.BoxLayout({ name: 'Windows', vertical: true, style: 'spacing: 8px' });
let tracker = Shell.WindowTracker.get_default();
@ -261,14 +350,12 @@ WindowList.prototype = {
}
}
}
};
});
Signals.addSignalMethods(WindowList.prototype);
function ObjInspector() {
this._init();
}
const ObjInspector = new Lang.Class({
Name: 'ObjInspector',
ObjInspector.prototype = {
_init : function () {
this._obj = null;
this._previousObj = null;
@ -322,7 +409,7 @@ ObjInspector.prototype = {
link = new St.Label({ text: '<error>' });
}
let hbox = new St.BoxLayout();
let propText = propName + ": " + valueStr;
let propText = propName + ': ' + valueStr;
hbox.add(new St.Label({ text: propName + ': ' }));
hbox.add(link);
this._container.add_actor(hbox);
@ -343,7 +430,7 @@ ObjInspector.prototype = {
this.actor.move_anchor_point(Math.floor(sourceX + sourceWidth / 2),
Math.floor(sourceY + sourceHeight / 2));
Tweener.addTween(this.actor, { scale_x: 1, scale_y: 1,
transition: "easeOutQuad",
transition: 'easeOutQuad',
time: 0.2 });
} else {
this.actor.set_scale(1, 1);
@ -368,7 +455,7 @@ ObjInspector.prototype = {
_onBack: function() {
this.selectObject(this._previousObj, true);
}
};
});
function addBorderPaintHook(actor) {
let signalId = actor.connect_after('paint',
@ -394,11 +481,9 @@ function addBorderPaintHook(actor) {
return signalId;
}
function Inspector() {
this._init();
}
const Inspector = new Lang.Class({
Name: 'Inspector',
Inspector.prototype = {
_init: function() {
let container = new Shell.GenericContainer({ width: 0,
height: 0 });
@ -537,15 +622,13 @@ Inspector.prototype = {
this._borderPaintId = addBorderPaintHook(this._target);
}
}
};
});
Signals.addSignalMethods(Inspector.prototype);
function ErrorLog() {
this._init();
}
const ErrorLog = new Lang.Class({
Name: 'ErrorLog',
ErrorLog.prototype = {
_init: function() {
this.actor = new St.BoxLayout();
this.text = new St.Label();
@ -580,13 +663,11 @@ ErrorLog.prototype = {
}
this.text.text = text;
}
};
});
function Memory() {
this._init();
}
const Memory = new Lang.Class({
Name: 'Memory',
Memory.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true });
this._glibc_uordblks = new St.Label();
@ -631,13 +712,11 @@ Memory.prototype = {
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
}
};
});
function Extensions() {
this._init();
}
const Extensions = new Lang.Class({
Name: 'Extensions',
Extensions.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
@ -685,11 +764,40 @@ Extensions.prototype = {
Main.lookingGlass.close();
},
_onViewErrors: function (actor) {
let meta = actor._extensionMeta;
let shouldShow = !actor._isShowing;
if (shouldShow) {
let errors = ExtensionSystem.errors[meta.uuid];
let errorDisplay = new St.BoxLayout({ vertical: true });
if (errors && errors.length) {
for (let i = 0; i < errors.length; i ++)
errorDisplay.add(new St.Label({ text: errors[i] }));
} else {
/* Translators: argument is an extension UUID. */
let message = _("%s has not emitted any errors.").format(meta.uuid);
errorDisplay.add(new St.Label({ text: message }));
}
actor._errorDisplay = errorDisplay;
actor._parentBox.add(errorDisplay);
actor.label = _("Hide Errors");
} else {
actor._errorDisplay.destroy();
actor._errorDisplay = null;
actor.label = _("Show Errors");
}
actor._isShowing = shouldShow;
},
_stateToString: function(extensionState) {
switch (extensionState) {
case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionSystem.ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
return _("Error");
@ -710,38 +818,39 @@ Extensions.prototype = {
text: meta.description || 'No description' });
box.add(description, { expand: true });
let metaBox = new St.BoxLayout();
let metaBox = new St.BoxLayout({ style_class: 'lg-extension-meta' });
box.add(metaBox);
let stateString = this._stateToString(meta.state);
let state = new St.Label({ style_class: 'lg-extension-state',
text: this._stateToString(meta.state) });
let actionsContainer = new St.Bin({ x_align: St.Align.END });
metaBox.add(actionsContainer);
let actionsBox = new St.BoxLayout({ style_class: 'lg-extension-actions' });
actionsContainer.set_child(actionsBox);
metaBox.add(state);
let viewsource = new Link.Link({ label: _("View Source") });
viewsource.actor._extensionMeta = meta;
viewsource.actor.connect('clicked', Lang.bind(this, this._onViewSource));
actionsBox.add(viewsource.actor);
metaBox.add(viewsource.actor);
if (meta.url) {
let webpage = new Link.Link({ label: _("Web Page") });
webpage.actor._extensionMeta = meta;
webpage.actor.connect('clicked', Lang.bind(this, this._onWebPage));
actionsBox.add(webpage.actor);
metaBox.add(webpage.actor);
}
let viewerrors = new Link.Link({ label: _("Show Errors") });
viewerrors.actor._extensionMeta = meta;
viewerrors.actor._parentBox = box;
viewerrors.actor._isShowing = false;
viewerrors.actor.connect('clicked', Lang.bind(this, this._onViewErrors));
metaBox.add(viewerrors.actor);
return box;
}
};
});
function LookingGlass() {
this._init();
}
const LookingGlass = new Lang.Class({
Name: 'LookingGlass',
LookingGlass.prototype = {
_init : function() {
this._borderPaintTarget = null;
this._borderPaintId = 0;
@ -758,7 +867,8 @@ LookingGlass.prototype = {
this.actor = new St.BoxLayout({ name: 'LookingGlassDialog',
style_class: 'lg-dialog',
vertical: true,
visible: false });
visible: false,
reactive: true });
this.actor.connect('key-press-event', Lang.bind(this, this._globalKeyPressEvent));
this._interfaceSettings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
@ -813,14 +923,15 @@ LookingGlass.prototype = {
this._resultsArea = new St.BoxLayout({ name: 'ResultsArea', vertical: true });
this._evalBox.add(this._resultsArea, { expand: true });
let entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(entryArea);
this._entryArea = new St.BoxLayout({ name: 'EntryArea' });
this._evalBox.add_actor(this._entryArea);
let label = new St.Label({ text: 'js>>> ' });
entryArea.add(label);
this._entryArea.add(label);
this._entry = new St.Entry({ can_focus: true });
entryArea.add(this._entry, { expand: true });
ShellEntry.addContextMenu(this._entry);
this._entryArea.add(this._entry, { expand: true });
this._windowList = new WindowList();
this._windowList.connect('selected', Lang.bind(this, function(list, window) {
@ -839,6 +950,9 @@ LookingGlass.prototype = {
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', Lang.bind(this, function (o, e) {
// Hide any completions we are currently showing
this._hideCompletions();
let text = o.get_text();
// Ensure we don't get newlines in the command; the history file is
// newline-separated.
@ -854,6 +968,17 @@ LookingGlass.prototype = {
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entry.clutter_text });
this._autoComplete = new AutoComplete(this._entry);
this._autoComplete.connect('suggest', Lang.bind(this, function(a,e) {
this._showCompletions(e.completions);
}));
// If a completion is completed unambiguously, the currently-displayed completion
// suggestions become irrelevant.
this._autoComplete.connect('completion', Lang.bind(this, function(a,e) {
if (e.type == 'whole-word')
this._hideCompletions();
}));
this._resize();
},
@ -898,6 +1023,59 @@ LookingGlass.prototype = {
this._notebook.scrollToBottom(0);
},
_showCompletions: function(completions) {
if (!this._completionActor) {
let actor = new St.BoxLayout({ vertical: true });
this._completionText = new St.Label({ name: 'LookingGlassAutoCompletionText', style_class: 'lg-completions-text' });
this._completionText.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._completionText.clutter_text.line_wrap = true;
actor.add(this._completionText);
let line = new Clutter.Rectangle();
let padBin = new St.Bin({ x_fill: true, y_fill: true });
padBin.add_actor(line);
actor.add(padBin);
this._completionActor = actor;
this._evalBox.insert_before(this._completionActor, this._entryArea);
}
this._completionText.set_text(completions.join(', '));
// Setting the height to -1 allows us to get its actual preferred height rather than
// whatever was last given in set_height by Tweener.
this._completionActor.set_height(-1);
let [minHeight, naturalHeight] = this._completionText.get_preferred_height(this._resultsArea.get_width());
// Don't reanimate if we are already visible
if (this._completionActor.visible) {
this._completionActor.height = naturalHeight;
} else {
this._completionActor.show();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: naturalHeight,
opacity: 255
});
}
},
_hideCompletions: function() {
if (this._completionActor) {
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
transition: 'easeOutQuad',
height: 0,
opacity: 0,
onComplete: Lang.bind(this, function () {
this._completionActor.hide();
})
});
}
},
_evaluate : function(command) {
this._history.addItem(command);
@ -962,6 +1140,7 @@ LookingGlass.prototype = {
// Handle key events which are relevant for all tabs of the LookingGlass
_globalKeyPressEvent : function(actor, event) {
let symbol = event.get_key_symbol();
let modifierState = Shell.get_event_state(event);
if (symbol == Clutter.Escape) {
if (this._objInspector.actor.visible) {
this._objInspector.close();
@ -970,6 +1149,14 @@ LookingGlass.prototype = {
}
return true;
}
// Ctrl+PgUp and Ctrl+PgDown switches tabs in the notebook view
if (modifierState & Clutter.ModifierType.CONTROL_MASK) {
if (symbol == Clutter.KEY_Page_Up) {
this._notebook.prevTab();
} else if (symbol == Clutter.KEY_Page_Down) {
this._notebook.nextTab();
}
}
return false;
},
@ -1020,5 +1207,5 @@ LookingGlass.prototype = {
})
});
}
};
});
Signals.addSignalMethods(LookingGlass.prototype);

View File

@ -1,6 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@ -12,22 +13,6 @@ const Main = imports.ui.main;
const MagnifierDBus = imports.ui.magnifierDBus;
const Params = imports.misc.params;
// Keep enums in sync with GSettings schemas
const MouseTrackingMode = {
NONE: 0,
CENTERED: 1,
PROPORTIONAL: 2,
PUSH: 3
};
const ScreenPosition = {
NONE: 0,
FULL_SCREEN: 1,
TOP_HALF: 2,
BOTTOM_HALF: 3,
LEFT_HALF: 4,
RIGHT_HALF: 5
};
const MOUSE_POLL_FREQUENCY = 50;
const CROSSHAIRS_CLIP_SIZE = [100, 100];
@ -51,11 +36,9 @@ const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
let magDBusService = null;
function Magnifier() {
this._init();
}
const Magnifier = new Lang.Class({
Name: 'Magnifier',
Magnifier.prototype = {
_init: function() {
// Magnifier is a manager of ZoomRegions.
this._zoomRegions = [];
@ -520,7 +503,7 @@ Magnifier.prototype = {
if (this._zoomRegions.length) {
let position = this._settings.get_enum(SCREEN_POSITION_KEY);
this._zoomRegions[0].setScreenPosition(position);
if (position != ScreenPosition.FULL_SCREEN)
if (position != GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN)
this._updateLensMode();
}
},
@ -558,21 +541,19 @@ Magnifier.prototype = {
);
}
}
};
});
Signals.addSignalMethods(Magnifier.prototype);
function ZoomRegion(magnifier, mouseSourceActor) {
this._init(magnifier, mouseSourceActor);
}
const ZoomRegion = new Lang.Class({
Name: 'ZoomRegion',
ZoomRegion.prototype = {
_init: function(magnifier, mouseSourceActor) {
this._magnifier = magnifier;
this._mouseTrackingMode = MouseTrackingMode.NONE;
this._mouseTrackingMode = GDesktopEnums.MagnifierMouseTrackingMode.NONE;
this._clampScrollingAtEdges = false;
this._lensMode = false;
this._screenPosition = ScreenPosition.FULL_SCREEN;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
this._magView = null;
this._uiGroupClone = null;
@ -647,7 +628,8 @@ ZoomRegion.prototype = {
* @mode: One of the enum MouseTrackingMode values.
*/
setMouseTrackingMode: function(mode) {
if (mode >= MouseTrackingMode.NONE && mode <= MouseTrackingMode.PUSH)
if (mode >= GDesktopEnums.MagnifierMouseTrackingMode.NONE &&
mode <= GDesktopEnums.MagnifierMouseTrackingMode.PUSH)
this._mouseTrackingMode = mode;
},
@ -668,7 +650,7 @@ ZoomRegion.prototype = {
*/
setViewPort: function(viewPort) {
this._setViewPort(viewPort);
this._screenPosition = ScreenPosition.NONE;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.NONE;
},
/**
@ -750,7 +732,7 @@ ZoomRegion.prototype = {
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = ScreenPosition.TOP_HALF;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.TOP_HALF;
},
/**
@ -764,7 +746,7 @@ ZoomRegion.prototype = {
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
this._setViewPort(viewPort);
this._screenPosition = ScreenPosition.BOTTOM_HALF;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF;
},
/**
@ -778,7 +760,7 @@ ZoomRegion.prototype = {
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = ScreenPosition.LEFT_HALF;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.LEFT_HALF;
},
/**
@ -792,7 +774,7 @@ ZoomRegion.prototype = {
viewPort.width = global.screen_width/2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = ScreenPosition.RIGHT_HALF;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF;
},
/**
@ -808,7 +790,7 @@ ZoomRegion.prototype = {
viewPort.height = global.screen_height;
this.setViewPort(viewPort);
this._screenPosition = ScreenPosition.FULL_SCREEN;
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
},
/**
@ -821,19 +803,19 @@ ZoomRegion.prototype = {
*/
setScreenPosition: function(inPosition) {
switch (inPosition) {
case ScreenPosition.FULL_SCREEN:
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case ScreenPosition.TOP_HALF:
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case ScreenPosition.BOTTOM_HALF:
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case ScreenPosition.LEFT_HALF:
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case ScreenPosition.RIGHT_HALF:
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
}
@ -856,7 +838,7 @@ ZoomRegion.prototype = {
*/
scrollToMousePos: function() {
this._followingCursor = true;
if (this._mouseTrackingMode != MouseTrackingMode.NONE)
if (this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE)
this._changeROI({ redoCursorTracking: true });
else
this._updateMousePosition();
@ -991,7 +973,7 @@ ZoomRegion.prototype = {
this._yMagFactor = params.yMagFactor;
if (params.redoCursorTracking &&
this._mouseTrackingMode != MouseTrackingMode.NONE) {
this._mouseTrackingMode != GDesktopEnums.MagnifierMouseTrackingMode.NONE) {
// This depends on this.xMagFactor/yMagFactor already being updated
[params.xCenter, params.yCenter] = this._centerFromMousePosition();
}
@ -1041,7 +1023,7 @@ ZoomRegion.prototype = {
_isFullScreen: function() {
// Does the magnified view occupy the whole screen? Note that this
// doesn't necessarily imply
// this._screenPosition = ScreenPosition.FULL_SCREEN;
// this._screenPosition = GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN;
if (this._viewPortX != 0 || this._viewPortY != 0)
return false;
@ -1058,13 +1040,13 @@ ZoomRegion.prototype = {
let xMouse = this._magnifier.xMouse;
let yMouse = this._magnifier.yMouse;
if (this._mouseTrackingMode == MouseTrackingMode.PROPORTIONAL) {
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
return this._centerFromMouseProportional(xMouse, yMouse);
}
else if (this._mouseTrackingMode == MouseTrackingMode.PUSH) {
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
return this._centerFromMousePush(xMouse, yMouse);
}
else if (this._mouseTrackingMode == MouseTrackingMode.CENTERED) {
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
return this._centerFromMouseCentered(xMouse, yMouse);
}
@ -1164,13 +1146,11 @@ ZoomRegion.prototype = {
yMagMouse - groupHeight / 2);
}
}
};
});
function Crosshairs() {
this._init();
}
const Crosshairs = new Lang.Class({
Name: 'Crosshairs',
Crosshairs.prototype = {
_init: function() {
// Set the group containing the crosshairs to three times the desktop
@ -1426,4 +1406,4 @@ Crosshairs.prototype = {
this._vertTopHair.set_position((groupWidth - thickness) / 2, top);
this._vertBottomHair.set_position((groupWidth - thickness) / 2, bottom);
}
};
});

View File

@ -1,6 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Main = imports.ui.main;
const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
@ -10,61 +11,99 @@ 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: []
};
const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
<method name="setActive">
<arg type="b" direction="in" />
</method>
<method name="isActive">
<arg type="b" direction="out" />
</method>
<method name="showCursor" />
<method name="hideCursor" />
<method name="createZoomRegion">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
<arg type="ai" direction="in" />
<arg type="ai" direction="in" />
<arg type="o" direction="out" />
</method>
<method name="addZoomRegion">
<arg type="o" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="getZoomRegions">
<arg type="ao" direction="out" />
</method>
<method name="clearAllZoomRegions" />
<method name="fullScreenCapable">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireSize">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireSize">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireLength">
<arg type="i" direction="in" />
</method>
<method name="getCrosswireLength">
<arg type="i" direction="out" />
</method>
<method name="setCrosswireClip">
<arg type="b" direction="in" />
</method>
<method name="getCrosswireClip">
<arg type="b" direction="out" />
</method>
<method name="setCrosswireColor">
<arg type="u" direction="in" />
</method>
<method name="getCrosswireColor">
<arg type="u" direction="out" />
</method>
</interface>;
// 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: []
};
const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
<method name="setMagFactor">
<arg type="d" direction="in" />
<arg type="d" direction="in" />
</method>
<method name="getMagFactor">
<arg type="d" direction="out" />
<arg type="d" direction="out" />
</method>
<method name="setRoi">
<arg type="ai" direction="in" />
</method>
<method name="getRoi">
<arg type="ai" direction="out" />
</method>
<method name="shiftContentsTo">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="out" />
</method>
<method name="moveResize">
<arg type="ai" direction="in" />
</method>
</interface>;
// 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();
}
const ShellMagnifier = new Lang.Class({
Name: 'ShellMagnifier',
ShellMagnifier.prototype = {
_init: function() {
this._zoomers = {};
DBus.session.exportObject(MAG_SERVICE_PATH, this);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
},
/**
@ -195,10 +234,10 @@ ShellMagnifier.prototype = {
Main.magnifier.clearAllZoomRegions();
for (let objectPath in this._zoomers) {
let proxyAndZoomer = this._zoomers[objectPath];
proxyAndZoomer.proxy.destroy();
proxyAndZoomer.proxy = null;
proxyAndZoomer.zoomRegion = null;
delete this._zoomers[objectPath];
DBus.session.unexportObject(proxyAndZoomer);
}
this._zoomers = {};
},
@ -285,7 +324,7 @@ ShellMagnifier.prototype = {
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
};
});
/**
* ShellMagnifierZoomRegion:
@ -293,15 +332,14 @@ ShellMagnifier.prototype = {
* @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);
}
const ShellMagnifierZoomRegion = new Lang.Class({
Name: 'ShellMagnifierZoomRegion',
ShellMagnifierZoomRegion.prototype = {
_init: function(zoomerObjectPath, zoomRegion) {
this._zoomRegion = zoomRegion;
DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
DBus.session.exportObject(zoomerObjectPath, this);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
},
/**
@ -376,8 +414,9 @@ ShellMagnifierZoomRegion.prototype = {
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);
destroy: function() {
this._dbusImpl.unexport();
}
});

View File

@ -1,11 +1,9 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
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;
@ -129,22 +127,16 @@ function _initRecorder() {
function _initUserSession() {
_initRecorder();
keyboard.init();
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT, false, -1, 1);
ExtensionSystem.init();
ExtensionSystem.loadExtensions();
let shellwm = global.window_manager;
shellwm.takeover_keybinding('panel_run_dialog');
shellwm.connect('keybinding::panel_run_dialog', function () {
Meta.keybindings_set_custom_handler('panel-run-dialog', function() {
getRunDialog().open();
});
shellwm.takeover_keybinding('panel_main_menu');
shellwm.connect('keybinding::panel_main_menu', function () {
Meta.keybindings_set_custom_handler('panel-main-menu', function () {
overview.toggle();
});
@ -165,11 +157,6 @@ function start() {
Gio.DesktopAppInfo.set_desktop_env('GNOME');
shellDBusService = new ShellDBus.GnomeShell();
// Force a connection now; dbus.js will do this internally
// if we use its name acquisition stuff but we aren't right
// now; to do so we'd need to convert from its async calls
// back into sync ones.
DBus.session.flush();
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
@ -496,9 +483,9 @@ function notify(msg, details) {
function notifyError(msg, details) {
// Also print to stderr so it's logged somewhere
if (details)
log("error: " + msg + ": " + details);
log('error: ' + msg + ': ' + details);
else
log("error: " + msg)
log('error: ' + msg);
notify(msg, details);
}
@ -585,16 +572,6 @@ function _globalKeyPressHandler(actor, event) {
// This relies on the fact that Clutter.ModifierType is the same as Gdk.ModifierType
let action = global.display.get_keybinding_action(keyCode, modifierState);
// The screenshot action should always be available (even if a
// modal dialog is present)
if (action == Meta.KeyBindingAction.COMMAND_SCREENSHOT) {
let gconf = GConf.Client.get_default();
let command = gconf.get_string('/apps/metacity/keybinding_commands/command_screenshot');
if (command != null && command != '')
Util.spawnCommandLine(command);
return true;
}
// Other bindings are only available to the user session when the overview is up and
// no modal dialog is present.
if (global.session_type == Shell.SessionType.USER && (!overview.visible || modalCount > 1))
@ -670,14 +647,17 @@ function _findModal(actor) {
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
*
* @options: optional Meta.ModalOptions flags to indicate that the
* pointer is alrady grabbed
*
* Returns: true iff we successfully acquired a grab or already had one
*/
function pushModal(actor, timestamp) {
function pushModal(actor, timestamp, options) {
if (timestamp == undefined)
timestamp = global.get_current_time();
if (modalCount == 0) {
if (!global.begin_modal(timestamp)) {
if (!global.begin_modal(timestamp, options ? options : 0)) {
log('pushModal: invocation of begin_modal failed');
return false;
}

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
@ -83,11 +83,9 @@ function _fixMarkup(text, allowMarkup) {
return GLib.markup_escape_text(text, -1);
}
function URLHighlighter(text, lineWrap, allowMarkup) {
this._init(text, lineWrap, allowMarkup);
}
const URLHighlighter = new Lang.Class({
Name: 'URLHighlighter',
URLHighlighter.prototype = {
_init: function(text, lineWrap, allowMarkup) {
if (!text)
text = '';
@ -211,13 +209,11 @@ URLHighlighter.prototype = {
}
return -1;
}
};
});
function FocusGrabber() {
this._init();
}
const FocusGrabber = new Lang.Class({
Name: 'FocusGrabber',
FocusGrabber.prototype = {
_init: function() {
this.actor = null;
@ -252,7 +248,8 @@ FocusGrabber.prototype = {
this._prevFocusedWindow = global.display.focus_window;
this._prevKeyFocusActor = global.stage.get_key_focus();
if (!Main.overview.visible)
if (global.stage_input_mode == Shell.StageInputMode.NONREACTIVE ||
global.stage_input_mode == Shell.StageInputMode.NORMAL)
global.set_stage_input_mode(Shell.StageInputMode.FOCUSED);
// Use captured-event to notice clicks outside the focused actor
@ -350,7 +347,7 @@ FocusGrabber.prototype = {
this._togglingFocusGrabMode = false;
}
}
}
});
Signals.addSignalMethods(FocusGrabber.prototype);
// Notification:
@ -407,11 +404,9 @@ Signals.addSignalMethods(FocusGrabber.prototype);
// the content and the action area of the notification will be cleared.
// The content area is also always cleared if 'customContent' is false
// because it might contain the @banner that didn't fit in the banner mode.
function Notification(source, title, banner, params) {
this._init(source, title, banner, params);
}
const Notification = new Lang.Class({
Name: 'Notification',
Notification.prototype = {
IMAGE_SIZE: 125,
_init: function(source, title, banner, params) {
@ -596,8 +591,7 @@ Notification.prototype = {
this._table.add_style_class_name('multi-line-notification');
this._scrollArea = new St.ScrollView({ name: 'notification-scrollview',
vscrollbar_policy: this._scrollPolicy,
hscrollbar_policy: Gtk.PolicyType.NEVER,
style_class: 'vfade' });
hscrollbar_policy: Gtk.PolicyType.NEVER });
this._table.add(this._scrollArea, { row: 1,
col: 2 });
this._updateLastColumnSettings();
@ -702,6 +696,7 @@ Notification.prototype = {
this._imageBin.opacity = 230;
this._table.add_style_class_name('multi-line-notification');
this._table.add_style_class_name('notification-with-image');
this._addBannerBody();
this._updateLastColumnSettings();
this._table.add(this._imageBin, { row: 1,
col: 1,
@ -952,14 +947,12 @@ Notification.prototype = {
this.actor.destroy();
this.actor._delegate = null;
}
};
});
Signals.addSignalMethods(Notification.prototype);
function Source(title) {
this._init(title);
}
const Source = new Lang.Class({
Name: 'MessageTraySource',
Source.prototype = {
ICON_SIZE: 24,
_init: function(title) {
@ -990,6 +983,7 @@ Source.prototype = {
this.isTransient = false;
this.isChat = false;
this.isMuted = false;
this.notifications = [];
},
@ -1054,6 +1048,13 @@ Source.prototype = {
this.emit('title-changed');
},
setMuted: function(muted) {
if (!this.isChat || this.isMuted == muted)
return;
this.isMuted = muted;
this.emit('muted-changed');
},
// Called to create a new icon actor (of size this.ICON_SIZE).
// Must be overridden by the subclass if you do not pass icons
// explicitly to the Notification() constructor.
@ -1092,7 +1093,8 @@ Source.prototype = {
notify: function(notification) {
this.pushNotification(notification);
this.emit('notify', notification);
if (!this.isMuted)
this.emit('notify', notification);
},
destroy: function(reason) {
@ -1132,14 +1134,12 @@ Source.prototype = {
_lastNotificationRemoved: function() {
this.destroy();
}
};
});
Signals.addSignalMethods(Source.prototype);
function SummaryItem(source) {
this._init(source);
}
const SummaryItem = new Lang.Class({
Name: 'SummaryItem',
SummaryItem.prototype = {
_init: function(source) {
this.source = source;
this.source.connect('notification-added', Lang.bind(this, this._notificationAddedToSource));
@ -1208,6 +1208,18 @@ SummaryItem.prototype = {
}));
this.rightClickMenu.add(item.actor);
if (source.isChat) {
item = new PopupMenu.PopupMenuItem('');
item.actor.connect('notify::mapped', Lang.bind(this, function() {
item.label.set_text(source.isMuted ? _("Unmute") : _("Mute"));
}));
item.connect('activate', Lang.bind(this, function() {
source.setMuted(!source.isMuted);
this.emit('done-displaying-content');
}));
this.rightClickMenu.add(item.actor);
}
let focusManager = St.FocusManager.get_for_stage(global.stage);
focusManager.add_group(this.rightClickMenu);
},
@ -1318,21 +1330,22 @@ SummaryItem.prototype = {
if (this.notificationStack.get_children().length > 0)
this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
}
};
});
Signals.addSignalMethods(SummaryItem.prototype);
function MessageTray() {
this._init();
}
const MessageTray = new Lang.Class({
Name: 'MessageTray',
MessageTray.prototype = {
_init: function() {
this._presence = new GnomeSession.Presence();
this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
this._onStatusChanged(proxy.status);
}));
this._userStatus = GnomeSession.PresenceStatus.AVAILABLE;
this._busy = false;
this._backFromAway = false;
this._presence.connect('StatusChanged', Lang.bind(this, this._onStatusChanged));
this._presence.getStatus(Lang.bind(this, this._onStatusChanged));
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._onStatusChanged(status);
}));
this.actor = new St.Group({ name: 'message-tray',
reactive: true,
@ -1516,6 +1529,14 @@ MessageTray.prototype = {
source.connect('notify', Lang.bind(this, this._onNotify));
source.connect('muted-changed', Lang.bind(this,
function () {
if (source.isMuted)
this._notificationQueue = this._notificationQueue.filter(function(notification) {
return source != notification.source;
});
}));
summaryItem.actor.connect('notify::hover', Lang.bind(this,
function () {
this._onSummaryItemHoverChanged(summaryItem);
@ -1585,7 +1606,7 @@ MessageTray.prototype = {
summaryItemToRemove.actor.destroy();
if (needUpdate);
if (needUpdate)
this._updateState();
},
@ -1830,7 +1851,7 @@ MessageTray.prototype = {
// automatically. Instead, the user is able to expand the notification by mousing away from it and then
// mousing back in. Because this is an expected action, we set the boolean flag that indicates that a longer
// timeout should be used before popping down the notification.
if (this._notificationBin.contains(actorAtShowNotificationPosition)) {
if (this.actor.contains(actorAtShowNotificationPosition)) {
this._useLongerTrayLeftTimeout = true;
return;
}
@ -1872,7 +1893,7 @@ MessageTray.prototype = {
this._updateState();
},
_onStatusChanged: function(presence, status) {
_onStatusChanged: function(status) {
this._backFromAway = (this._userStatus == GnomeSession.PresenceStatus.IDLE && this._userStatus != status);
this._userStatus = status;
@ -2393,17 +2414,14 @@ MessageTray.prototype = {
if (this._clickedSummaryItem)
this._updateState();
}
};
});
function SystemNotificationSource() {
this._init();
}
SystemNotificationSource.prototype = {
__proto__: Source.prototype,
const SystemNotificationSource = new Lang.Class({
Name: 'SystemNotificationSource',
Extends: Source,
_init: function() {
Source.prototype._init.call(this, _("System Information"));
this.parent(_("System Information"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -2417,4 +2435,4 @@ SystemNotificationSource.prototype = {
open: function() {
this.destroy();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
@ -29,11 +29,9 @@ const State = {
FADED_OUT: 4
};
function ModalDialog() {
this._init();
}
const ModalDialog = new Lang.Class({
Name: 'ModalDialog',
ModalDialog.prototype = {
_init: function(params) {
params = Params.parse(params, { shellReactive: false,
styleClass: null });
@ -110,7 +108,7 @@ ModalDialog.prototype = {
this._buttonLayout.destroy_children();
this._actionKeys = {};
for (let i = 0; i < buttons.length; i ++) {
for (let i = 0; i < buttons.length; i++) {
let buttonInfo = buttons[i];
let label = buttonInfo['label'];
let action = buttonInfo['action'];
@ -303,5 +301,5 @@ ModalDialog.prototype = {
})
});
}
};
});
Signals.addSignalMethods(ModalDialog.prototype);

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@ -30,16 +30,14 @@ const St = imports.gi.St;
const ModalDialog = imports.ui.modalDialog;
const PopupMenu = imports.ui.popupMenu;
const ShellEntry = imports.ui.shellEntry;
function NetworkSecretDialog() {
this._init.apply(this, arguments);
}
NetworkSecretDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const NetworkSecretDialog = new Lang.Class({
Name: 'NetworkSecretDialog',
Extends: ModalDialog.ModalDialog,
_init: function(agent, requestId, connection, settingName, hints) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
this.parent({ styleClass: 'polkit-dialog' });
this._agent = agent;
this._requestId = requestId;
@ -103,6 +101,8 @@ NetworkSecretDialog.prototype = {
secret.entry = new St.Entry({ style_class: 'polkit-dialog-password-entry',
text: secret.value, can_focus: reactive,
reactive: reactive });
ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password });
if (secret.validate)
secret.valid = secret.validate(secret);
@ -127,34 +127,14 @@ NetworkSecretDialog.prototype = {
} else
secret.valid = true;
secretTable.add(label, { row: pos, col: 0, x_align: St.Align.START, y_align: St.Align.START });
secretTable.add(label, { row: pos, col: 0, x_expand: false, x_fill: true, x_align: St.Align.START, y_align: St.Align.START });
secretTable.add(secret.entry, { row: pos, col: 1, x_expand: true, x_fill: true, y_align: St.Align.END });
pos++;
if (secret.password) {
if (secret.password)
secret.entry.clutter_text.set_password_char('\u25cf');
// FIXME: need a real checkbox here
let button = new St.Button({ button_mask: St.ButtonMask.ONE,
can_focus: true });
let checkbox = new St.BoxLayout({ vertical: false,
style_class: 'network-dialog-show-password-checkbox'
});
let _switch = new PopupMenu.Switch(false);
checkbox.add(_switch.actor);
checkbox.add(new St.Label({ text: _("Show password") }), { expand: true });
button.connect('clicked', function() {
_switch.toggle();
if (_switch.state)
secret.entry.clutter_text.set_password_char('');
else
secret.entry.clutter_text.set_password_char('\u25cf');
});
button.child = checkbox;
secretTable.add(button, { row: pos, col: 1, x_expand: true, x_fill: true, y_fill: true })
pos++;
}
}
messageBox.add(secretTable);
this._okButton = { label: _("Connect"),
@ -375,13 +355,11 @@ NetworkSecretDialog.prototype = {
return content;
}
};
});
function NetworkAgent() {
this._init.apply(this, arguments);
}
const NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
NetworkAgent.prototype = {
_init: function() {
this._native = new Shell.NetworkAgent({ auto_register: true,
identifier: 'org.gnome.Shell.NetworkAgent' });
@ -404,4 +382,4 @@ NetworkAgent.prototype = {
this._dialogs[requestId].close(global.get_current_time());
this._dialogs[requestId].destroy();
}
};
});

View File

@ -1,7 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
@ -16,49 +16,52 @@ const Util = imports.misc.util;
let nextNotificationId = 1;
// Should really be defined in dbus.js
const BusIface = {
name: 'org.freedesktop.DBus',
methods: [{ name: 'GetConnectionUnixProcessID',
inSignature: 's',
outSignature: 'i' }]
};
// Should really be defined in Gio.js
const BusIface = <interface name="org.freedesktop.DBus">
<method name="GetConnectionUnixProcessID">
<arg type="s" direction="in" />
<arg type="u" direction="out" />
</method>
</interface>;
const Bus = function () {
this._init();
};
var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
function Bus() {
return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
}
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 NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
<method name="Notify">
<arg type="s" direction="in"/>
<arg type="u" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="s" direction="in"/>
<arg type="as" direction="in"/>
<arg type="a{sv}" direction="in"/>
<arg type="i" direction="in"/>
<arg type="u" direction="out"/>
</method>
<method name="CloseNotification">
<arg type="u" direction="in"/>
</method>
<method name="GetCapabilities">
<arg type="as" direction="out"/>
</method>
<method name="GetServerInformation">
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
<arg type="s" direction="out"/>
</method>
<signal name="NotificationClosed">
<arg type="u"/>
<arg type="u"/>
</signal>
<signal name="ActionInvoked">
<arg type="u"/>
<arg type="s"/>
</signal>
</interface>;
const NotificationClosedReason = {
EXPIRED: 1,
@ -84,13 +87,12 @@ const rewriteRules = {
]
};
function NotificationDaemon() {
this._init();
}
const NotificationDaemon = new Lang.Class({
Name: 'NotificationDaemon',
NotificationDaemon.prototype = {
_init: function() {
DBus.session.exportObject('/org/freedesktop/Notifications', this);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
this._sources = {};
this._senderToPid = {};
@ -109,6 +111,14 @@ NotificationDaemon.prototype = {
_iconForNotificationData: function(icon, hints, size) {
let textureCache = St.TextureCache.get_default();
// If an icon is not specified, we use 'image-data' or 'image-path' hint for an icon
// and don't show a large image. There are currently many applications that use
// notify_notification_set_icon_from_pixbuf() from libnotify, which in turn sets
// the 'image-data' hint. These applications don't typically pass in 'app_icon'
// argument to Notify() and actually expect the pixbuf to be shown as an icon.
// So the logic here does the right thing for this case. If both an icon and either
// one of 'image-data' or 'image-path' are specified, we show both an icon and
// a large image.
if (icon) {
if (icon.substr(0, 7) == 'file://')
return textureCache.load_uri_async(icon, size, size);
@ -119,6 +129,12 @@ NotificationDaemon.prototype = {
return new St.Icon({ icon_name: icon,
icon_type: St.IconType.FULLCOLOR,
icon_size: size });
} else if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints['image-data'];
return textureCache.load_from_raw(data, hasAlpha, width, height, rowStride, size);
} else if (hints['image-path']) {
return textureCache.load_uri_async(GLib.filename_to_uri(hints['image-path'], null), size, size);
} else {
let stockIcon;
switch (hints.urgency) {
@ -181,8 +197,8 @@ NotificationDaemon.prototype = {
return source;
},
Notify: function(appName, replacesId, icon, summary, body,
actions, hints, timeout) {
NotifyAsync: function(params, invocation) {
let [appName, replacesId, icon, summary, body, actions, hints, timeout] = params;
let id;
// Filter out chat, presence, calls and invitation notifications from
@ -201,7 +217,7 @@ NotificationDaemon.prototype = {
function () {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
}));
return id;
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
let rewrites = rewriteRules[appName];
@ -213,6 +229,11 @@ NotificationDaemon.prototype = {
}
}
for (let hint in hints) {
// unpack the variants
hints[hint] = hints[hint].deep_unpack();
}
hints = Params.parse(hints, { urgency: Urgency.NORMAL }, true);
// Be compatible with the various hints for image data and image path
@ -244,51 +265,55 @@ NotificationDaemon.prototype = {
}
this._notifications[id] = ndata;
let sender = DBus.getCurrentMessageContext().sender;
let sender = invocation.get_sender();
let pid = this._senderToPid[sender];
let source = this._getSource(appName, pid, ndata, sender);
if (source) {
this._notifyForSource(source, ndata);
return id;
return invocation.return_value(GLib.Variant.new('(u)', [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;
return invocation.return_value(GLib.Variant.new('(u)', [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._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this, function (result, excp) {
// The app may have updated or removed the notification
ndata = this._notifications[id];
if (!ndata)
return;
source = this._getSource(appName, pid, ndata, sender);
if (excp) {
logError(excp, 'Call to GetConnectionUnixProcessID failed');
return;
}
// We only store sender-pid entries for persistent sources.
// Removing the entries once the source is destroyed
// would result in the entries associated with transient
// sources removed once the notification is shown anyway.
// However, keeping these pairs would mean that we would
// possibly remove an entry associated with a persistent
// source when a transient source for the same sender is
// distroyed.
if (!source.isTransient) {
this._senderToPid[sender] = pid;
source.connect('destroy', Lang.bind(this,
function() {
delete this._senderToPid[sender];
}));
}
this._notifyForSource(source, ndata);
}));
let [pid] = result;
source = this._getSource(appName, pid, ndata, sender);
return id;
// We only store sender-pid entries for persistent sources.
// Removing the entries once the source is destroyed
// would result in the entries associated with transient
// sources removed once the notification is shown anyway.
// However, keeping these pairs would mean that we would
// possibly remove an entry associated with a persistent
// source when a transient source for the same sender is
// distroyed.
if (!source.isTransient) {
this._senderToPid[sender] = pid;
source.connect('destroy', Lang.bind(this, function() {
delete this._senderToPid[sender];
}));
}
this._notifyForSource(source, ndata);
}));
return invocation.return_value(GLib.Variant.new('(u)', [id]));
},
_notifyForSource: function(source, ndata) {
@ -330,7 +355,8 @@ NotificationDaemon.prototype = {
clear: true });
}
if (hints['image-data'] || hints['image-path']) {
// We only display a large image if an icon is also specified.
if (icon && (hints['image-data'] || hints['image-path'])) {
let image = null;
if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
@ -427,17 +453,13 @@ NotificationDaemon.prototype = {
},
_emitNotificationClosed: function(id, reason) {
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'NotificationClosed', 'uu',
[id, reason]);
this._dbusImpl.emit_signal('NotificationClosed',
GLib.Variant.new('(uu)', [id, reason]));
},
_emitActionInvoked: function(id, action) {
DBus.session.emit_signal('/org/freedesktop/Notifications',
'org.freedesktop.Notifications',
'ActionInvoked', 'us',
[id, action]);
this._dbusImpl.emit_signal('ActionInvoked',
GLib.Variant.new('(us)', [id, action]));
},
_onTrayIconAdded: function(o, icon) {
@ -450,31 +472,23 @@ NotificationDaemon.prototype = {
if (source)
source.destroy();
}
};
});
DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
function Source(title, pid, sender) {
this._init(title, pid, sender);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
const Source = new Lang.Class({
Name: 'NotificationDaemonSource',
Extends: MessageTray.Source,
_init: function(title, pid, sender) {
MessageTray.Source.prototype._init.call(this, title);
this.parent(title);
this._pid = pid;
if (sender)
// TODO: dbus-glib implementation of watch_name() doesnt return an id to be used for
// unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation,
// we should save the id here and call unwatch_name() with it in destroy().
// Moving to GDBus is the work in progress: https://bugzilla.gnome.org/show_bug.cgi?id=648651
// and https://bugzilla.gnome.org/show_bug.cgi?id=622921 .
DBus.session.watch_name(sender,
false,
null,
Lang.bind(this, this._onNameVanished));
this._nameWatcherId = Gio.DBus.session.watch_name(sender,
Gio.BusNameWatcherFlags.NONE,
null,
Lang.bind(this, this._onNameVanished));
else
this._nameWatcherId = 0;
this._setApp();
if (this.app)
@ -582,6 +596,11 @@ Source.prototype = {
},
destroy: function() {
MessageTray.Source.prototype.destroy.call(this);
if (this._nameWatcherId) {
Gio.DBus.session.unwatch_name(this._nameWatcherId);
this._nameWatcherId = 0;
}
this.parent();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
@ -46,11 +46,9 @@ const SwipeScrollResult = {
CLICK: 2
};
function ShellInfo() {
this._init();
}
const ShellInfo = new Lang.Class({
Name: 'ShellInfo',
ShellInfo.prototype = {
_init: function() {
this._source = null;
this._undoCallback = null;
@ -95,13 +93,11 @@ ShellInfo.prototype = {
this._source.notify(notification);
}
};
});
function Overview() {
this._init.apply(this, arguments);
}
const Overview = new Lang.Class({
Name: 'Overview',
Overview.prototype = {
_init : function(params) {
params = Params.parse(params, { isDummy: false });
@ -811,5 +807,5 @@ Overview.prototype = {
this._needsFakePointerEvent = false;
}
}
};
});
Signals.addSignalMethods(Overview.prototype);

View File

@ -1,8 +1,9 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Pango = imports.gi.Pango;
@ -98,11 +99,9 @@ function _unpremultiply(color) {
};
function AnimatedIcon(name, size) {
this._init(name, size);
}
const AnimatedIcon = new Lang.Class({
Name: 'AnimatedIcon',
AnimatedIcon.prototype = {
_init: function(name, size) {
this.actor = new St.Bin({ visible: false });
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
@ -139,13 +138,11 @@ AnimatedIcon.prototype = {
if (this._timeoutId)
Mainloop.source_remove(this._timeoutId);
}
};
});
function TextShadower() {
this._init();
}
const TextShadower = new Lang.Class({
Name: 'TextShadower',
TextShadower.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -225,7 +222,7 @@ TextShadower.prototype = {
child.allocate(childBox, flags);
}
}
};
});
/**
* AppMenuButton:
@ -235,18 +232,19 @@ TextShadower.prototype = {
* this menu also handles startup notification for it. So when we
* have an active startup notification, we switch modes to display that.
*/
function AppMenuButton() {
this._init();
}
const AppMenuButton = new Lang.Class({
Name: 'AppMenuButton',
Extends: PanelMenu.Button,
AppMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
_init: function(menuManager) {
this.parent(0.0, true);
_init: function() {
PanelMenu.Button.prototype._init.call(this, 0.0);
this._startingApps = [];
this._menuManager = menuManager;
this._targetApp = null;
this._appMenuNotifyId = 0;
this._actionGroupNotifyId = 0;
let bin = new St.Bin({ name: 'appMenu' });
this.actor.add_actor(bin);
@ -271,10 +269,6 @@ AppMenuButton.prototype = {
this._iconBottomClip = 0;
this._quitMenu = new PopupMenu.PopupMenuItem('');
this.menu.addMenuItem(this._quitMenu);
this._quitMenu.connect('activate', Lang.bind(this, this._onQuit));
this._visible = !Main.overview.visible;
if (!this._visible)
this.actor.hide();
@ -453,12 +447,6 @@ AppMenuButton.prototype = {
}
},
_onQuit: function() {
if (this._targetApp == null)
return;
this._targetApp.request_quit();
},
_onAppStateChanged: function(appSys, app) {
let state = app.state;
if (state != Shell.AppState.STARTING) {
@ -520,8 +508,10 @@ AppMenuButton.prototype = {
}
if (targetApp == this._targetApp) {
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING)
if (targetApp && targetApp.get_state() != Shell.AppState.STARTING) {
this.stopAnimation();
this._maybeSetMenu();
}
return;
}
@ -531,37 +521,67 @@ AppMenuButton.prototype = {
this._iconBox.hide();
this._label.setText('');
if (this._appMenuNotifyId)
this._targetApp.disconnect(this._appMenuNotifyId);
if (this._actionGroupNotifyId)
this._targetApp.disconnect(this._actionGroupNotifyId);
if (targetApp) {
this._appMenuNotifyId = targetApp.connect('notify::menu', Lang.bind(this, this._sync));
this._actionGroupNotifyId = targetApp.connect('notify::action-group', Lang.bind(this, this._sync));
}
this._targetApp = targetApp;
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);
this._label.setText(targetApp.get_name());
// TODO - _quit() doesn't really work on apps in state STARTING yet
this._quitMenu.label.set_text(_("Quit %s").format(targetApp.get_name()));
this._iconBox.set_child(icon);
this._iconBox.show();
if (targetApp.get_state() == Shell.AppState.STARTING)
this.startAnimation();
else
this._maybeSetMenu();
this.emit('changed');
},
_maybeSetMenu: function() {
let menu;
if (this._targetApp.action_group) {
if (this.menu instanceof PopupMenu.RemoteMenu &&
this.menu.actionGroup == this._targetApp.action_group)
return;
menu = new PopupMenu.RemoteMenu(this.actor, this._targetApp.menu, this._targetApp.action_group);
} else {
if (this.menu && !(this.menu instanceof PopupMenu.RemoteMenu))
return;
// fallback to older menu
menu = new PopupMenu.PopupMenu(this.actor, 0.0, St.Side.TOP, 0);
menu.addAction(_("Quit"), Lang.bind(this, function() {
this._targetApp.request_quit();
}));
}
this.setMenu(menu);
this._menuManager.addMenu(menu);
}
};
});
Signals.addSignalMethods(AppMenuButton.prototype);
// Activities button. Because everything else in the top bar is a
// PanelMenu.Button, it simplifies some things to make this be one too.
// We just hack it up to not actually have a menu attached to it.
function ActivitiesButton() {
this._init.apply(this, arguments);
}
ActivitiesButton.prototype = {
__proto__: PanelMenu.Button.prototype,
const ActivitiesButton = new Lang.Class({
Name: 'ActivitiesButton',
Extends: PanelMenu.Button,
_init: function() {
PanelMenu.Button.prototype._init.call(this, 0.0);
this.parent(0.0);
let container = new Shell.GenericContainer();
container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
@ -698,13 +718,11 @@ ActivitiesButton.prototype = {
Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = 0;
}
};
});
function PanelCorner(panel, side) {
this._init(panel, side);
}
const PanelCorner = new Lang.Class({
Name: 'PanelCorner',
PanelCorner.prototype = {
_init: function(box, side) {
this._side = side;
@ -880,14 +898,12 @@ PanelCorner.prototype = {
this.actor.set_size(cornerRadius, innerBorderWidth + cornerRadius);
this.actor.set_anchor_point(0, innerBorderWidth);
}
};
});
function Panel() {
this._init();
}
const Panel = new Lang.Class({
Name: 'Panel',
Panel.prototype = {
_init : function() {
this.actor = new Shell.GenericContainer({ name: 'panel',
reactive: true });
@ -938,9 +954,8 @@ Panel.prototype = {
// more cleanly with the rest of the panel
this._menus.addMenu(this._activitiesButton.menu);
this._appMenu = new AppMenuButton();
this._appMenu = new AppMenuButton(this._menus);
this._leftBox.add(this._appMenu.actor);
this._menus.addMenu(this._appMenu.menu);
}
/* center */
@ -1114,5 +1129,4 @@ Panel.prototype = {
if (box && box._delegate instanceof PanelMenu.ButtonBox)
box.destroy();
},
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
@ -11,11 +11,9 @@ const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
function ButtonBox(params) {
this._init.apply(this, arguments);
};
const ButtonBox = new Lang.Class({
Name: 'ButtonBox',
ButtonBox.prototype = {
_init: function(params) {
params = Params.parse(params, { style_class: 'panel-button' }, true);
this.actor = new Shell.GenericContainer(params);
@ -92,31 +90,45 @@ ButtonBox.prototype = {
child.allocate(childBox, flags);
},
}
});
function Button(menuAlignment) {
this._init(menuAlignment);
}
const Button = new Lang.Class({
Name: 'PanelMenuButton',
Extends: ButtonBox,
Button.prototype = {
__proto__: ButtonBox.prototype,
_init: function(menuAlignment) {
ButtonBox.prototype._init.call(this, { reactive: true,
can_focus: true,
track_hover: true });
_init: function(menuAlignment, dontCreateMenu) {
this.parent({ reactive: true,
can_focus: true,
track_hover: true });
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
this.menu.actor.add_style_class_name('panel-menu');
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
this.menu.actor.hide();
if (dontCreateMenu)
this.menu = null;
else
this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
},
setMenu: function(menu) {
if (this.menu)
this.menu.destroy();
this.menu = menu;
if (this.menu) {
this.menu.actor.add_style_class_name('panel-menu');
this.menu.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.menu.actor.connect('key-press-event', Lang.bind(this, this._onMenuKeyPress));
Main.uiGroup.add_actor(this.menu.actor);
this.menu.actor.hide();
}
},
_onButtonPress: function(actor, event) {
if (!this.menu)
return;
if (!this.menu.isOpen) {
// Setting the max-height won't do any good if the minimum height of the
// menu is higher then the screen; it's useful if part of the menu is
@ -130,6 +142,9 @@ Button.prototype = {
},
_onSourceKeyPress: function(actor, event) {
if (!this.menu)
return false;
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_space || symbol == Clutter.KEY_Return) {
this.menu.toggle();
@ -175,7 +190,7 @@ Button.prototype = {
this.emit('destroy');
}
};
});
Signals.addSignalMethods(Button.prototype);
/* SystemStatusButton:
@ -184,15 +199,13 @@ Signals.addSignalMethods(Button.prototype);
* 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,
const SystemStatusButton = new Lang.Class({
Name: 'SystemStatusButton',
Extends: Button,
_init: function(iconName,tooltipText) {
Button.prototype._init.call(this, 0.0);
this.parent(0.0);
this._iconActor = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
@ -219,4 +232,4 @@ SystemStatusButton.prototype = {
this.tooltip = null;
}
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
@ -22,11 +22,9 @@ const Util = imports.misc.util;
* @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);
}
const PlaceInfo = new Lang.Class({
Name: 'PlaceInfo',
PlaceInfo.prototype = {
_init: function(id, name, iconFactory, launch) {
this.id = id;
this.name = name;
@ -55,7 +53,7 @@ PlaceInfo.prototype = {
isRemovable: function() {
return false;
}
};
});
// Helper function to translate launch parameters into a GAppLaunchContext
function _makeLaunchContext(params)
@ -72,12 +70,9 @@ function _makeLaunchContext(params)
return launchContext;
}
function PlaceDeviceInfo(mount) {
this._init(mount);
}
PlaceDeviceInfo.prototype = {
__proto__: PlaceInfo.prototype,
const PlaceDeviceInfo = new Lang.Class({
Name: 'PlaceDeviceInfo',
Extends: PlaceInfo,
_init: function(mount) {
this._mount = mount;
@ -123,13 +118,11 @@ PlaceDeviceInfo.prototype = {
_("Retry"));
}
}
};
});
function PlacesManager() {
this._init();
}
const PlacesManager = new Lang.Class({
Name: 'PlacesManager',
PlacesManager.prototype = {
_init: function() {
this._defaultPlaces = [];
this._mounts = [];
@ -195,9 +188,9 @@ PlacesManager.prototype = {
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._monitor = this._bookmarksFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
this._bookmarkTimeoutId = 0;
monitor.connect('changed', Lang.bind(this, function () {
this._monitor.connect('changed', Lang.bind(this, function () {
if (this._bookmarkTimeoutId > 0)
return;
/* Defensive event compression */
@ -360,19 +353,15 @@ PlacesManager.prototype = {
_removeById: function(sourceArray, id) {
sourceArray.splice(this._lookupIndexById(sourceArray, id), 1);
}
};
});
Signals.addSignalMethods(PlacesManager.prototype);
function PlaceSearchProvider() {
this._init();
}
PlaceSearchProvider.prototype = {
__proto__: Search.SearchProvider.prototype,
const PlaceSearchProvider = new Lang.Class({
Name: 'PlaceSearchProvider',
Extends: Search.SearchProvider,
_init: function() {
Search.SearchProvider.prototype._init.call(this, _("PLACES & DEVICES"));
this.parent(_("PLACES & DEVICES"));
},
getResultMeta: function(resultId) {
@ -434,4 +423,4 @@ PlaceSearchProvider.prototype = {
let places = previousResults.map(function (id) { return Main.placesManager.lookupPlaceById(id); });
return this._searchPlaces(places, terms);
}
};
});

View File

@ -1,5 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/*
* Copyright 2010 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
@ -27,22 +27,21 @@ const AccountsService = imports.gi.AccountsService;
const Clutter = imports.gi.Clutter;
const St = imports.gi.St;
const Pango = imports.gi.Pango;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Polkit = imports.gi.Polkit;
const PolkitAgent = imports.gi.PolkitAgent;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
function AuthenticationDialog(actionId, message, cookie, userNames) {
this._init(actionId, message, cookie, userNames);
}
AuthenticationDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const AuthenticationDialog = new Lang.Class({
Name: 'AuthenticationDialog',
Extends: ModalDialog.ModalDialog,
_init: function(actionId, message, cookie, userNames) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'polkit-dialog' });
this.parent({ styleClass: 'polkit-dialog' });
this.actionId = actionId;
this.message = message;
@ -87,10 +86,14 @@ AuthenticationDialog.prototype = {
if (userNames.length > 1) {
log('polkitAuthenticationAgent: Received ' + userNames.length +
' identities that can be used for authentication. Only ' +
'considering the first one.');
'considering one.');
}
let userName = userNames[0];
let userName = GLib.get_user_name();
if (userNames.indexOf(userName) < 0)
userName = 'root';
if (userNames.indexOf(userName) < 0)
userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name()
@ -139,6 +142,7 @@ AuthenticationDialog.prototype = {
this._passwordEntry = new St.Entry({ style_class: 'polkit-dialog-password-entry',
text: "",
can_focus: true});
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
this._passwordBox.add(this._passwordEntry,
{expand: true });
@ -328,15 +332,12 @@ AuthenticationDialog.prototype = {
this.close(global.get_current_time());
this._emitDone(false, true);
},
};
});
Signals.addSignalMethods(AuthenticationDialog.prototype);
function AuthenticationAgent() {
this._init();
}
const AuthenticationAgent = new Lang.Class({
Name: 'AuthenticationAgent',
AuthenticationAgent.prototype = {
_init: function() {
this._native = new Shell.PolkitAuthenticationAgent();
this._native.connect('initiate', Lang.bind(this, this._onInitiate));
@ -397,7 +398,7 @@ AuthenticationAgent.prototype = {
this._reallyCompleteRequest(wasDismissed);
}
}
}
});
function init() {
let agent = new AuthenticationAgent();

View File

@ -1,8 +1,10 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@ -26,11 +28,9 @@ function _ensureStyle(actor) {
actor.ensure_style();
}
function PopupBaseMenuItem(params) {
this._init(params);
}
const PopupBaseMenuItem = new Lang.Class({
Name: 'PopupBaseMenuItem',
PopupBaseMenuItem.prototype = {
_init: function (params) {
params = Params.parse (params, { reactive: true,
activate: true,
@ -108,14 +108,16 @@ PopupBaseMenuItem.prototype = {
this.emit('activate', event);
},
setActive: function (active) {
setActive: function (active, params) {
let activeChanged = active != this.active;
params = Params.parse (params, { grabKeyboard: true });
if (activeChanged) {
this.active = active;
if (active) {
this.actor.add_style_pseudo_class('active');
this.actor.grab_key_focus();
if (params.grabKeyboard)
this.actor.grab_key_focus();
} else
this.actor.remove_style_pseudo_class('active');
this.emit('active-changed', active);
@ -375,33 +377,27 @@ PopupBaseMenuItem.prototype = {
x -= availWidth + this._spacing;
}
}
};
});
Signals.addSignalMethods(PopupBaseMenuItem.prototype);
function PopupMenuItem() {
this._init.apply(this, arguments);
}
PopupMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupMenuItem = new Lang.Class({
Name: 'PopupMenuItem',
Extends: PopupBaseMenuItem,
_init: function (text, params) {
PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
this.label = new St.Label({ text: text });
this.addActor(this.label);
}
};
});
function PopupSeparatorMenuItem() {
this._init();
}
PopupSeparatorMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupSeparatorMenuItem = new Lang.Class({
Name: 'PopupSeparatorMenuItem',
Extends: PopupBaseMenuItem,
_init: function () {
PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
this.parent({ reactive: false });
this._drawingArea = new St.DrawingArea({ style_class: 'popup-separator-menu-item' });
this.addActor(this._drawingArea, { span: -1, expand: true });
@ -427,22 +423,19 @@ PopupSeparatorMenuItem.prototype = {
cr.rectangle(margin, gradientOffset, gradientWidth, gradientHeight);
cr.fill();
}
};
});
const PopupAlternatingMenuItemState = {
DEFAULT: 0,
ALTERNATIVE: 1
}
function PopupAlternatingMenuItem() {
this._init.apply(this, arguments);
}
PopupAlternatingMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupAlternatingMenuItem = new Lang.Class({
Name: 'PopupAlternatingMenuItem',
Extends: PopupBaseMenuItem,
_init: function(text, alternateText, params) {
PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
this.actor.add_style_class_name('popup-alternating-menu-item');
this._text = text;
@ -528,17 +521,14 @@ PopupAlternatingMenuItem.prototype = {
this._updateLabel();
}
};
});
function PopupSliderMenuItem() {
this._init.apply(this, arguments);
}
PopupSliderMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupSliderMenuItem = new Lang.Class({
Name: 'PopupSliderMenuItem',
Extends: PopupBaseMenuItem,
_init: function(value) {
PopupBaseMenuItem.prototype._init.call(this, { activate: false });
this.parent({ activate: false });
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
@ -714,13 +704,11 @@ PopupSliderMenuItem.prototype = {
}
return false;
}
};
});
function Switch() {
this._init.apply(this, arguments);
}
const Switch = new Lang.Class({
Name: 'Switch',
Switch.prototype = {
_init: function(state) {
this.actor = new St.Bin({ style_class: 'toggle-switch' });
// Translators: this MUST be either "toggle-switch-us"
@ -743,17 +731,14 @@ Switch.prototype = {
toggle: function() {
this.setToggleState(!this.state);
}
};
});
function PopupSwitchMenuItem() {
this._init.apply(this, arguments);
}
PopupSwitchMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupSwitchMenuItem = new Lang.Class({
Name: 'PopupSwitchMenuItem',
Extends: PopupBaseMenuItem,
_init: function(text, active, params) {
PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
this.label = new St.Label({ text: text });
this._switch = new Switch(active);
@ -788,7 +773,7 @@ PopupSwitchMenuItem.prototype = {
this.toggle();
}
PopupBaseMenuItem.prototype.activate.call(this, event);
this.parent(event);
},
toggle: function() {
@ -803,17 +788,14 @@ PopupSwitchMenuItem.prototype = {
setToggleState: function(state) {
this._switch.setToggleState(state);
}
};
});
function PopupImageMenuItem() {
this._init.apply(this, arguments);
}
PopupImageMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupImageMenuItem = new Lang.Class({
Name: 'PopupImageMenuItem',
Extends: PopupBaseMenuItem,
_init: function (text, iconName, params) {
PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
this.label = new St.Label({ text: text });
this.addActor(this.label);
@ -826,13 +808,12 @@ PopupImageMenuItem.prototype = {
setIcon: function(name) {
this._icon.icon_name = name;
}
};
});
function PopupMenuBase() {
throw new TypeError('Trying to instantiate abstract class PopupMenuBase');
}
const PopupMenuBase = new Lang.Class({
Name: 'PopupMenuBase',
Abstract: true,
PopupMenuBase.prototype = {
_init: function(sourceActor, styleClass) {
this.sourceActor = sourceActor;
@ -1019,6 +1000,11 @@ PopupMenuBase.prototype = {
}
if (menuItem instanceof PopupMenuSection) {
this._connectSubMenuSignals(menuItem, menuItem);
menuItem._closingId = this.connect('open-state-changed',
function(self, open) {
if (!open)
menuItem.close(false);
});
menuItem.connect('destroy', Lang.bind(this, function() {
menuItem.disconnect(menuItem._subMenuActivateId);
menuItem.disconnect(menuItem._subMenuActiveChangeId);
@ -1132,20 +1118,17 @@ PopupMenuBase.prototype = {
this.emit('destroy');
}
};
});
Signals.addSignalMethods(PopupMenuBase.prototype);
function PopupMenu() {
this._init.apply(this, arguments);
}
const PopupMenu = new Lang.Class({
Name: 'PopupMenu',
Extends: PopupMenuBase,
PopupMenu.prototype = {
__proto__: PopupMenuBase.prototype,
_init: function(sourceActor, arrowAlignment, arrowSide) {
this.parent(sourceActor, 'popup-menu-content');
_init: function(sourceActor, alignment, arrowSide) {
PopupMenuBase.prototype._init.call (this, sourceActor, 'popup-menu-content');
this._alignment = alignment;
this._arrowAlignment = arrowAlignment;
this._arrowSide = arrowSide;
this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
@ -1198,13 +1181,17 @@ PopupMenu.prototype = {
this._boxPointer.setArrowOrigin(origin);
},
setSourceAlignment: function(alignment) {
this._boxPointer.setSourceAlignment(alignment);
},
open: function(animate) {
if (this.isOpen)
return;
this.isOpen = true;
this._boxPointer.setPosition(this.sourceActor, this._alignment);
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.show(animate);
this.actor.raise_top();
@ -1224,17 +1211,14 @@ PopupMenu.prototype = {
this.isOpen = false;
this.emit('open-state-changed', false);
}
};
});
function PopupSubMenu() {
this._init.apply(this, arguments);
}
PopupSubMenu.prototype = {
__proto__: PopupMenuBase.prototype,
const PopupSubMenu = new Lang.Class({
Name: 'PopupSubMenu',
Extends: PopupMenuBase,
_init: function(sourceActor, sourceArrow) {
PopupMenuBase.prototype._init.call(this, sourceActor);
this.parent(sourceActor);
this._arrow = sourceArrow;
this._arrow.rotation_center_z_gravity = Clutter.Gravity.CENTER;
@ -1389,7 +1373,7 @@ PopupSubMenu.prototype = {
return false;
}
};
});
/**
* PopupMenuSection:
@ -1399,35 +1383,30 @@ PopupSubMenu.prototype = {
* can add it to another menu), but is completely transparent
* to the user
*/
function PopupMenuSection() {
this._init.apply(this, arguments);
}
PopupMenuSection.prototype = {
__proto__: PopupMenuBase.prototype,
const PopupMenuSection = new Lang.Class({
Name: 'PopupMenuSection',
Extends: PopupMenuBase,
_init: function() {
PopupMenuBase.prototype._init.call(this);
this.parent();
this.actor = this.box;
this.actor._delegate = this;
this.isOpen = true;
},
// deliberately ignore any attempt to open() or close()
open: function(animate) { },
close: function() { },
}
// deliberately ignore any attempt to open() or close(), but emit the
// corresponding signal so children can still pick it up
open: function(animate) { this.emit('open-state-changed', true); },
close: function() { this.emit('open-state-changed', false); },
});
function PopupSubMenuMenuItem() {
this._init.apply(this, arguments);
}
PopupSubMenuMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupSubMenuMenuItem = new Lang.Class({
Name: 'PopupSubMenuMenuItem',
Extends: PopupBaseMenuItem,
_init: function(text) {
PopupBaseMenuItem.prototype._init.call(this);
this.parent();
this.actor.add_style_class_name('popup-submenu-menu-item');
@ -1449,7 +1428,8 @@ PopupSubMenuMenuItem.prototype = {
destroy: function() {
this.menu.destroy();
PopupBaseMenuItem.prototype.destroy.call(this);
this.parent();
},
_onKeyPressEvent: function(actor, event) {
@ -1464,7 +1444,7 @@ PopupSubMenuMenuItem.prototype = {
return true;
}
return PopupBaseMenuItem.prototype._onKeyPressEvent.call(this, actor, event);
return this.parent(actor, event);
},
activate: function(event) {
@ -1474,22 +1454,21 @@ PopupSubMenuMenuItem.prototype = {
_onButtonReleaseEvent: function(actor) {
this.menu.toggle();
}
};
});
function PopupComboMenu() {
this._init.apply(this, arguments);
}
PopupComboMenu.prototype = {
__proto__: PopupMenuBase.prototype,
const PopupComboMenu = new Lang.Class({
Name: 'PopupComboMenu',
Extends: PopupMenuBase,
_init: function(sourceActor) {
PopupMenuBase.prototype._init.call(this,
sourceActor, 'popup-combo-menu');
this.parent(sourceActor, 'popup-combo-menu');
this.actor = this.box;
this.actor._delegate = this;
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
this.actor.connect('key-focus-in', Lang.bind(this, this._onKeyFocusIn));
sourceActor.connect('style-changed',
Lang.bind(this, this._onSourceActorStyleChanged));
this._activeItemPos = -1;
global.focus_manager.add_group(this.actor);
},
@ -1509,6 +1488,26 @@ PopupComboMenu.prototype = {
activeItem.actor.grab_key_focus();
},
_onSourceActorStyleChanged: function() {
// PopupComboBoxMenuItem clones the active item's actors
// to work with arbitrary items in the menu; this means
// that we need to propagate some style information and
// enforce style updates even when the menu is closed
let activeItem = this._getMenuItems()[this._activeItemPos];
if (this.sourceActor.has_style_pseudo_class('insensitive'))
activeItem.actor.add_style_pseudo_class('insensitive');
else
activeItem.actor.remove_style_pseudo_class('insensitive');
// To propagate the :active style, we need to make sure that the
// internal state of the PopupComboMenu is updated as well, but
// we must not move the keyboard grab
activeItem.setActive(this.sourceActor.has_style_pseudo_class('active'),
{ grabKeyboard: false });
_ensureStyle(this.actor);
},
open: function() {
if (this.isOpen)
return;
@ -1568,17 +1567,14 @@ PopupComboMenu.prototype = {
getItemVisible: function(position) {
return this._getMenuItems()[position].actor.visible;
}
};
});
function PopupComboBoxMenuItem() {
this._init.apply(this, arguments);
}
PopupComboBoxMenuItem.prototype = {
__proto__: PopupBaseMenuItem.prototype,
const PopupComboBoxMenuItem = new Lang.Class({
Name: 'PopupComboBoxMenuItem',
Extends: PopupBaseMenuItem,
_init: function (params) {
PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
this._itemBox = new Shell.Stack();
this.addActor(this._itemBox);
@ -1696,16 +1692,254 @@ PopupComboBoxMenuItem.prototype = {
this.setActiveItem(position);
this.emit('active-item-changed', position);
}
};
});
/**
* RemoteMenu:
*
* A PopupMenu that tracks a GMenuModel and shows its actions
* (exposed by GApplication/GActionGroup)
*/
const RemoteMenu = new Lang.Class({
Name: 'RemoteMenu',
Extends: PopupMenu,
_init: function(sourceActor, model, actionGroup) {
this.parent(sourceActor, 0.0, St.Side.TOP);
this.model = model;
this.actionGroup = actionGroup;
this._actions = { };
this._modelChanged(this.model, 0, 0, this.model.get_n_items(), this);
this._actionStateChangeId = this.actionGroup.connect('action-state-changed', Lang.bind(this, this._actionStateChanged));
this._actionEnableChangeId = this.actionGroup.connect('action-enabled-changed', Lang.bind(this, this._actionEnabledChanged));
},
destroy: function() {
if (this._actionStateChangeId) {
this.actionGroup.disconnect(this._actionStateChangeId);
this._actionStateChangeId = 0;
}
if (this._actionEnableChangeId) {
this.actionGroup.disconnect(this._actionEnableChangeId);
this._actionEnableChangeId = 0;
}
this.parent();
},
_createMenuItem: function(model, index) {
let section_link = model.get_item_link(index, Gio.MENU_LINK_SECTION);
if (section_link) {
let item = new PopupMenuSection();
this._modelChanged(section_link, 0, 0, section_link.get_n_items(), item);
return [item, true, ''];
}
// labels are not checked for existance, as they're required for all items
let label = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_LABEL, null).deep_unpack();
// remove all underscores that are not followed by another underscore
label = label.replace(/_([^_])/, '$1');
let submenu_link = model.get_item_link(index, Gio.MENU_LINK_SUBMENU);
if (submenu_link) {
let item = new PopupSubMenuMenuItem(label);
this._modelChanged(submenu_link, 0, 0, submenu_link.get_n_items(), item.menu);
return [item, false, ''];
}
let action_id = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_ACTION, null).deep_unpack();
if (!this.actionGroup.has_action(action_id)) {
// the action may not be there yet, wait for action-added
return [null, false, 'action-added'];
}
if (!this._actions[action_id])
this._actions[action_id] = { enabled: this.actionGroup.get_action_enabled(action_id),
state: this.actionGroup.get_action_state(action_id),
items: [ ],
};
let action = this._actions[action_id];
let item, target, destroyId, specificSignalId;
if (action.state) {
// Docs have get_state_hint(), except that the DBus protocol
// has no provision for it (so ShellApp does not implement it,
// and neither GApplication), and g_action_get_state_hint()
// always returns null
// Funny :)
switch (String.fromCharCode(action.state.classify())) {
case 'b':
item = new PopupSwitchMenuItem(label, action.state.get_boolean());
action.items.push(item);
specificSignalId = item.connect('toggled', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, null);
}));
break;
case 's':
item = new PopupMenuItem(label);
item._remoteTarget = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null).deep_unpack();
action.items.push(item);
item.setShowDot(action.state.deep_unpack() == item._remoteTarget);
specificSignalId = item.connect('activate', Lang.bind(this, function(item) {
this.actionGroup.activate_action(action_id, GLib.Variant.new_string(item._remoteTarget));
}));
break;
default:
log('Action "%s" has state of type %s, which is not supported'.format(action_id, action.state.get_type_string()));
return [null, false, 'action-state-changed'];
}
} else {
target = model.get_item_attribute_value(index, Gio.MENU_ATTRIBUTE_TARGET, null);
item = new PopupMenuItem(label);
action.items.push(item);
specificSignalId = item.connect('activate', Lang.bind(this, function() {
this.actionGroup.activate_action(action_id, target);
}));
}
item.actor.reactive = item.actor.can_focus = action.enabled;
if (action.enabled)
item.actor.remove_style_pseudo_class('insensitive');
else
item.actor.add_style_pseudo_class('insensitive');
destroyId = item.connect('destroy', Lang.bind(this, function() {
item.disconnect(destroyId);
item.disconnect(specificSignalId);
let pos = action.items.indexOf(item);
if (pos != -1)
action.items.splice(pos, 1);
}));
return [item, false, ''];
},
_modelChanged: function(model, position, removed, added, target) {
let j, k;
let j0, k0;
let currentItems = target._getMenuItems();
for (j0 = 0, k0 = 0; j0 < position; j0++, k0++) {
if (currentItems[k0] instanceof PopupSeparatorMenuItem)
k0++;
}
if (removed == -1) {
// special flag to indicate we should destroy everything
for (k = k0; k < currentItems.length; k++)
currentItems[k].destroy();
} else {
for (j = j0, k = k0; j < j0 + removed; j++, k++) {
currentItems[k].destroy();
if (currentItems[k] instanceof PopupSeparatorMenuItem)
j--;
}
}
for (j = j0, k = k0; j < j0 + added; j++, k++) {
let [item, addSeparator, changeSignal] = this._createMenuItem(model, j);
if (item) {
// separators must be added in the parent to make autohiding work
if (addSeparator) {
target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
k++;
}
target.addMenuItem(item, k);
if (addSeparator) {
target.addMenuItem(new PopupSeparatorMenuItem(), k+1);
k++;
}
} else if (changeSignal) {
let signalId = this.actionGroup.connect(changeSignal, Lang.bind(this, function() {
this.actionGroup.disconnect(signalId);
// force a full update
this._modelChanged(model, 0, -1, model.get_n_items(), target);
}));
}
}
if (!model._changedId) {
model._changedId = model.connect('items-changed', Lang.bind(this, this._modelChanged, target));
model._destroyId = target.connect('destroy', function() {
if (model._changedId)
model.disconnect(model._changedId);
if (model._destroyId)
target.disconnect(model._destroyId);
model._changedId = 0;
model._destroyId = 0;
});
}
if (target instanceof PopupMenuSection) {
target.actor.visible = target.numMenuItems != 0;
} else {
let sourceItem = target.sourceActor._delegate;
if (sourceItem instanceof PopupSubMenuMenuItem)
sourceItem.actor.visible = target.numMenuItems != 0;
}
},
_actionStateChanged: function(actionGroup, action_id) {
let action = this._actions[action_id];
if (!action)
return;
action.state = actionGroup.get_action_state(action_id);
if (action.items.length) {
switch (String.fromCharCode(action.state.classify())) {
case 'b':
for (let i = 0; i < action.items.length; i++)
action.items[i].setToggleState(action.state.get_boolean());
break;
case 'd':
for (let i = 0; i < action.items.length; i++)
action.items[i].setValue(action.state.get_double());
break;
case 's':
for (let i = 0; i < action.items.length; i++)
action.items[i].setShowDot(action.items[i]._remoteTarget == action.state.deep_unpack());
}
}
},
_actionEnabledChanged: function(actionGroup, action_id) {
let action = this._actions[action_id];
if (!action)
return;
action.enabled = actionGroup.get_action_enabled(action_id);
if (action.items.length) {
for (let i = 0; i < action.items.length; i++) {
let item = action.items[i];
item.actor.reactive = item.actor.can_focus = action.enabled;
if (action.enabled)
item.actor.remove_style_pseudo_class('insensitive');
else
item.actor.add_style_pseudo_class('insensitive');
}
}
}
});
/* Basic implementation of a menu manager.
* Call addMenu to add menus
*/
function PopupMenuManager(owner) {
this._init(owner);
}
const PopupMenuManager = new Lang.Class({
Name: 'PopupMenuManager',
PopupMenuManager.prototype = {
_init: function(owner) {
this._owner = owner;
this.grabbed = false;
@ -1977,4 +2211,4 @@ PopupMenuManager.prototype = {
if (this._activeMenu != null)
this._activeMenu.close(true);
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
@ -12,6 +12,7 @@ const Signals = imports.signals;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
const History = imports.misc.history;
@ -29,11 +30,9 @@ const EXEC_ARG_KEY = 'exec-arg';
const DIALOG_GROW_TIME = 0.1;
function CommandCompleter() {
this._init();
}
const CommandCompleter = new Lang.Class({
Name: 'CommandCompleter',
CommandCompleter.prototype = {
_init : function() {
this._changedCount = 0;
this._paths = GLib.getenv('PATH').split(':');
@ -161,16 +160,14 @@ CommandCompleter.prototype = {
return common.substr(text.length);
return common;
}
};
});
function RunDialog() {
this._init();
}
const RunDialog = new Lang.Class({
Name: 'RunDialog',
Extends: ModalDialog.ModalDialog,
RunDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init : function() {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'run-dialog' });
this.parent({ styleClass: 'run-dialog' });
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
this._terminalSettings = new Gio.Settings({ schema: TERMINAL_SCHEMA });
@ -210,6 +207,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
this.contentLayout.add(label, { y_align: St.Align.START });
let entry = new St.Entry({ style_class: 'run-dialog-entry' });
ShellEntry.addContextMenu(entry);
this._entryText = entry.clutter_text;
this.contentLayout.add(entry, { y_align: St.Align.START });
@ -382,8 +380,7 @@ __proto__: ModalDialog.ModalDialog.prototype,
if (this._lockdownSettings.get_boolean(DISABLE_COMMAND_LINE_KEY))
return;
ModalDialog.ModalDialog.prototype.open.call(this);
this.parent();
},
};
});
Signals.addSignalMethods(RunDialog.prototype);

View File

@ -1,6 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -70,24 +69,21 @@ function waitLeisure() {
};
}
const PerfHelperIface = {
name: 'org.gnome.Shell.PerfHelper',
methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' },
{ name: 'WaitWindows', inSignature: '', outSignature: '' },
{ name: 'DestroyWindows', inSignature: '', outSignature: ''}]
};
const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
<method name="CreateWindow">
<arg type="i" direction="in" />
<arg type="i" direction="in" />
<arg type="b" direction="in" />
<arg type="b" direction="in" />
</method>
<method name="WaitWindows" />
<method name="DestroyWindows" />
</interface>;
const PerfHelper = function () {
this._init();
};
PerfHelper.prototype = {
_init: function() {
DBus.session.proxifyObject(this, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
}
};
DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface);
var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
function PerfHelper() {
return new PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
}
let _perfHelper = null;
function _getPerfHelper() {

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
@ -23,11 +23,9 @@ const MatchType = {
MULTIPLE_PREFIX: 4
};
function SearchResultDisplay(provider) {
this._init(provider);
}
const SearchResultDisplay = new Lang.Class({
Name: 'SearchResultDisplay',
SearchResultDisplay.prototype = {
_init: function(provider) {
this.provider = provider;
this.actor = null;
@ -96,7 +94,7 @@ SearchResultDisplay.prototype = {
activateSelected: function() {
throw new Error('Not implemented');
}
};
});
/**
* SearchProvider:
@ -105,11 +103,9 @@ SearchResultDisplay.prototype = {
* to the search system, then call registerProvider()
* in SearchSystem with an instance.
*/
function SearchProvider(title) {
this._init(title);
}
const SearchProvider = new Lang.Class({
Name: 'SearchProvider',
SearchProvider.prototype = {
_init: function(title) {
this.title = title;
this.searchSystem = null;
@ -243,14 +239,12 @@ SearchProvider.prototype = {
activateResult: function(id) {
throw new Error('Not implemented');
}
};
});
Signals.addSignalMethods(SearchProvider.prototype);
function OpenSearchSystem() {
this._init();
}
const OpenSearchSystem = new Lang.Class({
Name: 'OpenSearchSystem',
OpenSearchSystem.prototype = {
_init: function() {
this._providers = [];
global.settings.connect('changed::' + DISABLED_OPEN_SEARCH_PROVIDERS_KEY, Lang.bind(this, this._refresh));
@ -338,14 +332,12 @@ OpenSearchSystem.prototype = {
}
}));
}
}
});
Signals.addSignalMethods(OpenSearchSystem.prototype);
function SearchSystem() {
this._init();
}
const SearchSystem = new Lang.Class({
Name: 'SearchSystem',
SearchSystem.prototype = {
_init: function() {
this._providers = [];
this.reset();
@ -433,5 +425,5 @@ SearchSystem.prototype = {
this._previousResults = results;
this.emit('search-completed', results);
},
};
});
Signals.addSignalMethods(SearchSystem.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -15,11 +15,9 @@ const Search = imports.ui.search;
const MAX_SEARCH_RESULTS_ROWS = 1;
function SearchResult(provider, metaInfo, terms) {
this._init(provider, metaInfo, terms);
}
const SearchResult = new Lang.Class({
Name: 'SearchResult',
SearchResult.prototype = {
_init: function(provider, metaInfo, terms) {
this.provider = provider;
this.metaInfo = metaInfo;
@ -97,18 +95,16 @@ SearchResult.prototype = {
else
this.provider.activateResult(this.metaInfo.id, params);
}
};
});
function GridSearchResults(provider, grid) {
this._init(provider, grid);
}
GridSearchResults.prototype = {
__proto__: Search.SearchResultDisplay.prototype,
const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: Search.SearchResultDisplay,
_init: function(provider, grid) {
Search.SearchResultDisplay.prototype._init.call(this, provider);
this.parent(provider);
this._grid = grid || new IconGrid.IconGrid({ rowLimit: MAX_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
this.actor = new St.Bin({ x_align: St.Align.START });
@ -179,14 +175,11 @@ GridSearchResults.prototype = {
let targetActor = this._grid.getItemAtIndex(this.selectionIndex);
targetActor._delegate.activate();
}
};
});
const SearchResults = new Lang.Class({
Name: 'SearchResults',
function SearchResults(searchSystem, openSearchSystem) {
this._init(searchSystem, openSearchSystem);
}
SearchResults.prototype = {
_init: function(searchSystem, openSearchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateCurrentResults));
@ -486,4 +479,4 @@ SearchResults.prototype = {
resultDisplay.activateSelected();
Main.overview.hide();
}
};
});

View File

@ -1,79 +1,77 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Lang = imports.lang;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Config = imports.misc.config;
const ExtensionSystem = imports.ui.extensionSystem;
const Main = imports.ui.main;
const GnomeShellIface = {
name: 'org.gnome.Shell',
methods: [{ name: 'Eval',
inSignature: 's',
outSignature: 'bs'
},
{ name: 'ListExtensions',
inSignature: '',
outSignature: 'a{sa{sv}}'
},
{ name: 'GetExtensionInfo',
inSignature: 's',
outSignature: 'a{sv}'
},
{ name: 'GetExtensionErrors',
inSignature: 's',
outSignature: 'as'
},
{ name: 'ScreenshotArea',
inSignature: 'iiiis',
outSignature: 'b'
},
{ name: 'ScreenshotWindow',
inSignature: 'bs',
outSignature: 'b'
},
{ name: 'Screenshot',
inSignature: 's',
outSignature: 'b'
},
{ name: 'EnableExtension',
inSignature: 's',
outSignature: ''
},
{ name: 'DisableExtension',
inSignature: 's',
outSignature: ''
},
{ name: 'InstallRemoteExtension',
inSignature: 'ss',
outSignature: ''
},
{ name: 'UninstallExtension',
inSignature: 's',
outSignature: 'b'
}
],
signals: [{ name: 'ExtensionStatusChanged',
inSignature: 'sis' }],
properties: [{ name: 'OverviewActive',
signature: 'b',
access: 'readwrite' },
{ name: 'ApiVersion',
signature: 'i',
access: 'read' },
{ name: 'ShellVersion',
signature: 's',
access: 'read' }]
};
const GnomeShellIface = <interface name="org.gnome.Shell">
<method name="Eval">
<arg type="s" direction="in" name="script" />
<arg type="b" direction="out" name="success" />
<arg type="s" direction="out" name="result" />
</method>
<method name="ListExtensions">
<arg type="a{sa{sv}}" direction="out" name="extensions" />
</method>
<method name="GetExtensionInfo">
<arg type="s" direction="in" name="extension" />
<arg type="a{sv}" direction="out" name="info" />
</method>
<method name="GetExtensionErrors">
<arg type="s" direction="in" name="extension" />
<arg type="as" direction="out" name="errors" />
</method>
<method name="ScreenshotArea">
<arg type="i" direction="in" name="x"/>
<arg type="i" direction="in" name="y"/>
<arg type="i" direction="in" name="width"/>
<arg type="i" direction="in" name="height"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="ScreenshotWindow">
<arg type="b" direction="in" name="include_frame"/>
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="Screenshot">
<arg type="s" direction="in" name="filename"/>
<arg type="b" direction="out" name="success"/>
</method>
<method name="EnableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="DisableExtension">
<arg type="s" direction="in" name="uuid"/>
</method>
<method name="InstallRemoteExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="s" direction="in" name="version"/>
</method>
<method name="UninstallExtension">
<arg type="s" direction="in" name="uuid"/>
<arg type="b" direction="out" name="success"/>
</method>
<property name="OverviewActive" type="b" access="readwrite" />
<property name="ApiVersion" type="i" access="read" />
<property name="ShellVersion" type="s" access="read" />
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>
<arg type="s" name="error"/>
</signal>
</interface>;
function GnomeShell() {
this._init();
}
const GnomeShell = new Lang.Class({
Name: 'GnomeShellDBus',
GnomeShell.prototype = {
_init: function() {
DBus.session.exportObject('/org/gnome/Shell', this);
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(GnomeShellIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/Shell');
ExtensionSystem.connect('extension-state-changed',
Lang.bind(this, this._extensionStateChanged));
},
@ -93,6 +91,9 @@ GnomeShell.prototype = {
*
*/
Eval: function(code) {
if (!global.settings.get_boolean('development-tools'))
return [false, null];
let returnValue;
let success;
try {
@ -153,11 +154,33 @@ GnomeShell.prototype = {
},
ListExtensions: function() {
return ExtensionSystem.extensionMeta;
let out = {};
for (let uuid in ExtensionSystem.extensionMeta) {
let dbusObj = this.GetExtensionInfo(uuid);
out[uuid] = dbusObj;
}
return out;
},
GetExtensionInfo: function(uuid) {
return ExtensionSystem.extensionMeta[uuid] || {};
let meta = ExtensionSystem.extensionMeta[uuid] || {};
let out = {};
for (let key in meta) {
let val = meta[key];
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
default:
continue;
}
out[key] = GLib.Variant.new(type, val);
}
return out;
},
GetExtensionErrors: function(uuid) {
@ -202,12 +225,7 @@ GnomeShell.prototype = {
ShellVersion: Config.PACKAGE_VERSION,
_extensionStateChanged: function(_, newState) {
DBus.session.emit_signal('/org/gnome/Shell',
'org.gnome.Shell',
'ExtensionStatusChanged', 'sis',
[newState.uuid, newState.state, newState.error]);
this._dbusImpl.emit_signal('ExtensionStatusChanged',
GLib.Variant.new('(sis)', [newState.uuid, newState.state, newState.error]));
}
};
DBus.conformExport(GnomeShell.prototype, GnomeShellIface);
});

168
js/ui/shellEntry.js Normal file
View File

@ -0,0 +1,168 @@
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const _EntryMenu = new Lang.Class({
Name: 'ShellEntryMenu',
Extends: PopupMenu.PopupMenu,
_init: function(entry, params) {
params = Params.parse (params, { isPassword: false });
this.parent(entry, 0, St.Side.TOP);
this.actor.add_style_class_name('entry-context-menu');
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', Lang.bind(this, this._onCopyActivated));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', Lang.bind(this, this._onPasteActivated));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
if (params.isPassword) {
item = new PopupMenu.PopupMenuItem('');
item.connect('activate', Lang.bind(this,
this._onPasswordActivated));
this.addMenuItem(item);
this._passwordItem = item;
}
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
},
open: function() {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
let direction = Gtk.DirectionType.TAB_FORWARD;
if (!this.actor.navigate_focus(null, direction, false))
this.actor.grab_key_focus();
this.parent();
},
_updateCopyItem: function() {
let selection = this._entry.clutter_text.get_selection();
this._copyItem.setSensitive(selection && selection != '');
},
_updatePasteItem: function() {
this._clipboard.get_text(Lang.bind(this,
function(clipboard, text) {
this._pasteItem.setSensitive(text && text != '');
}));
},
_updatePasswordItem: function() {
let textHidden = (this._entry.clutter_text.password_char);
if (textHidden)
this._passwordItem.label.set_text(_("Show Text"));
else
this._passwordItem.label.set_text(_("Hide Text"));
},
_onCopyActivated: function() {
let selection = this._entry.clutter_text.get_selection();
this._clipboard.set_text(selection);
},
_onPasteActivated: function() {
this._clipboard.get_text(Lang.bind(this,
function(clipboard, text) {
if (!text)
return;
this._entry.clutter_text.delete_selection();
let pos = this._entry.clutter_text.get_cursor_position();
this._entry.clutter_text.insert_text(text, pos);
}));
},
_onPasswordActivated: function() {
let visible = !!(this._entry.clutter_text.password_char);
this._entry.clutter_text.set_password_char(visible ? '' : '\u25cf');
}
});
function _setMenuAlignment(entry, stageX) {
let [success, entryX, entryY] = entry.transform_stage_point(stageX, 0);
if (success)
entry._menu.setSourceAlignment(entryX / entry.width);
};
function _onClicked(action, actor) {
let entry = actor._menu ? actor : actor.get_parent();
if (entry._menu.isOpen) {
entry._menu.close();
} else if (action.get_button() == 3) {
let [stageX, stageY] = action.get_coords();
_setMenuAlignment(entry, stageX);
entry._menu.open();
}
};
function _onLongPress(action, actor, state) {
let entry = actor._menu ? actor : actor.get_parent();
if (state == Clutter.LongPressState.QUERY)
return action.get_button() == 1 && !entry._menu.isOpen;
if (state == Clutter.LongPressState.ACTIVATE) {
let [stageX, stageY] = action.get_coords();
_setMenuAlignment(entry, stageX);
entry._menu.open();
}
return false;
};
function _onPopup(actor) {
let entry = actor._menu ? actor : actor.get_parent();
let [success, textX, textY, lineHeight] = entry.clutter_text.position_to_coords(-1);
if (success)
entry._menu.setSourceAlignment(textX / entry.width);
entry._menu.open();
};
function addContextMenu(entry, params) {
if (entry._menu)
return;
entry._menu = new _EntryMenu(entry, params);
entry._menuManager = new PopupMenu.PopupMenuManager({ actor: entry });
entry._menuManager.addMenu(entry._menu);
let clickAction;
// Add a click action to both the entry and its clutter_text; the former
// so padding is included in the clickable area, the latter because the
// event processing of ClutterText prevents event-bubbling.
clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', _onClicked);
clickAction.connect('long-press', _onLongPress);
entry.clutter_text.add_action(clickAction);
clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', _onClicked);
clickAction.connect('long-press', _onLongPress);
entry.add_action(clickAction);
entry.connect('popup-menu', _onPopup);
}

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Signals = imports.signals;
@ -50,11 +50,9 @@ function _setLabelsForMessage(dialog, message) {
/* -------------------------------------------------------- */
function ListItem(app) {
this._init(app);
}
const ListItem = new Lang.Class({
Name: 'ListItem',
ListItem.prototype = {
_init: function(app) {
this._app = app;
@ -86,14 +84,12 @@ ListItem.prototype = {
this.emit('activate');
this._app.activate();
}
};
});
Signals.addSignalMethods(ListItem.prototype);
function ShellMountOperation(source, params) {
this._init(source, params);
}
const ShellMountOperation = new Lang.Class({
Name: 'ShellMountOperation',
ShellMountOperation.prototype = {
_init: function(source, params) {
params = Params.parse(params, { reaskPassword: false });
@ -190,17 +186,14 @@ ShellMountOperation.prototype = {
this._processesDialog.update(message, processes, choices);
},
}
});
function ShellMountQuestionDialog(icon) {
this._init(icon);
}
ShellMountQuestionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const ShellMountQuestionDialog = new Lang.Class({
Name: 'ShellMountQuestionDialog',
Extends: ModalDialog.ModalDialog,
_init: function(icon) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'mount-question-dialog' });
this.parent({ styleClass: 'mount-question-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
@ -236,19 +229,16 @@ ShellMountQuestionDialog.prototype = {
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
}
});
Signals.addSignalMethods(ShellMountQuestionDialog.prototype);
function ShellMountPasswordSource(message, icon, reaskPassword) {
this._init(message, icon, reaskPassword);
}
ShellMountPasswordSource.prototype = {
__proto__: MessageTray.Source.prototype,
const ShellMountPasswordSource = new Lang.Class({
Name: 'ShellMountPasswordSource',
Extends: MessageTray.Source,
_init: function(message, icon, reaskPassword) {
let strings = message.split('\n');
MessageTray.Source.prototype._init.call(this, strings[0]);
this.parent(strings[0]);
this._notification = new ShellMountPasswordNotification(this, strings, icon, reaskPassword);
@ -256,21 +246,15 @@ ShellMountPasswordSource.prototype = {
Main.messageTray.add(this);
this.notify(this._notification);
},
}
});
Signals.addSignalMethods(ShellMountPasswordSource.prototype);
function ShellMountPasswordNotification(source, strings, icon, reaskPassword) {
this._init(source, strings, icon, reaskPassword);
}
ShellMountPasswordNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const ShellMountPasswordNotification = new Lang.Class({
Name: 'ShellMountPasswordNotification',
Extends: MessageTray.Notification,
_init: function(source, strings, icon, reaskPassword) {
MessageTray.Notification.prototype._init.call(this, source,
strings[0], null,
{ customContent: true,
icon: icon });
this.parent(source, strings[0], null, { customContent: true, icon: icon });
// set the notification to transient and urgent, so that it
// expands out
@ -305,17 +289,14 @@ ShellMountPasswordNotification.prototype = {
this.source.emit('password-ready', text);
}
}
});
function ShellProcessesDialog(icon) {
this._init(icon);
}
ShellProcessesDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
const ShellProcessesDialog = new Lang.Class({
Name: 'ShellProcessesDialog',
Extends: ModalDialog.ModalDialog,
_init: function(icon) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'show-processes-dialog' });
this.parent({ styleClass: 'show-processes-dialog' });
let mainContentLayout = new St.BoxLayout();
this.contentLayout.add(mainContentLayout, { x_fill: true,
@ -401,5 +382,5 @@ ShellProcessesDialog.prototype = {
_setLabelsForMessage(this, message);
_setButtonsForChoices(this, choices);
}
}
});
Signals.addSignalMethods(ShellProcessesDialog.prototype);

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const GConf = imports.gi.GConf;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
@ -30,8 +29,8 @@ const DPI_FACTOR_LARGE = 1.25;
const DPI_FACTOR_LARGER = 1.5;
const DPI_FACTOR_LARGEST = 2.0;
const KEY_META_DIR = '/apps/metacity/general';
const KEY_VISUAL_BELL = KEY_META_DIR + '/visual_bell';
const WM_SCHEMA = 'org.gnome.desktop.wm.preferences';
const KEY_VISUAL_BELL = 'visual-bell';
const DESKTOP_INTERFACE_SCHEMA = 'org.gnome.desktop.interface';
const KEY_GTK_THEME = 'gtk-theme';
@ -40,19 +39,12 @@ const KEY_TEXT_SCALING_FACTOR = 'text-scaling-factor';
const HIGH_CONTRAST_THEME = 'HighContrast';
function ATIndicator() {
this._init.apply(this, arguments);
}
ATIndicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const ATIndicator = new Lang.Class({
Name: 'ATIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-accessibility', null);
let client = GConf.Client.get_default();
client.add_dir(KEY_META_DIR, GConf.ClientPreloadType.PRELOAD_ONELEVEL, null);
client.notify_add(KEY_META_DIR, Lang.bind(this, this._keyChanged), null, null);
this.parent('preferences-desktop-accessibility', null);
let highContrast = this._buildHCItem();
this.menu.addMenuItem(highContrast);
@ -72,7 +64,7 @@ ATIndicator.prototype = {
'screen-keyboard-enabled');
this.menu.addMenuItem(screenKeyboard);
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
let visualBell = this._buildItem(_("Visual Alerts"), WM_SCHEMA, KEY_VISUAL_BELL);
this.menu.addMenuItem(visualBell);
let stickyKeys = this._buildItem(_("Sticky Keys"), A11Y_SCHEMA, KEY_STICKY_KEYS_ENABLED);
@ -102,22 +94,6 @@ ATIndicator.prototype = {
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,
@ -191,10 +167,5 @@ ATIndicator.prototype = {
widget.setToggleState(active);
});
return widget;
},
_keyChanged: function() {
this.emit('gconf-changed');
}
};
Signals.addSignalMethods(ATIndicator.prototype);
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gdk = imports.gi.Gdk;
@ -23,15 +23,12 @@ const ConnectionState = {
CONNECTING: 3
}
function Indicator() {
this._init.apply(this, arguments);
}
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const Indicator = new Lang.Class({
Name: 'BTIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'bluetooth-disabled', null);
this.parent('bluetooth-disabled', null);
GLib.spawn_command_line_sync ('pkill -f "^bluetooth-applet$"');
this._applet = new GnomeBluetoothApplet.Applet();
@ -204,9 +201,10 @@ Indicator.prototype = {
_buildDeviceSubMenu: function(item, device) {
if (device.can_connect) {
let menuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
item._connected = device.connected;
item._connectedMenuitem = new PopupMenu.PopupSwitchMenuItem(_("Connection"), device.connected);
item._connectedMenuitem.connect('toggled', Lang.bind(this, function() {
item._connectedMenuItem = menuitem;
menuitem.connect('toggled', Lang.bind(this, function() {
if (item._connected > ConnectionState.CONNECTED) {
// operation already in progress, revert
// (should not happen anyway)
@ -241,7 +239,7 @@ Indicator.prototype = {
}
}));
item.menu.addMenuItem(item._connectedMenuitem);
item.menu.addMenuItem(menuitem);
}
if (device.capabilities & GnomeBluetoothApplet.Capabilities.OBEX_PUSH) {
@ -334,17 +332,14 @@ Indicator.prototype = {
_cancelRequest: function() {
this._source.destroy();
}
}
});
function Source() {
this._init.apply(this, arguments);
}
Source.prototype = {
__proto__: MessageTray.Source.prototype,
const Source = new Lang.Class({
Name: 'BluetoothSource',
Extends: MessageTray.Source,
_init: function() {
MessageTray.Source.prototype._init.call(this, _("Bluetooth"));
this.parent(_("Bluetooth"));
this._setSummaryIcon(this.createNotificationIcon());
},
@ -358,7 +353,7 @@ Source.prototype = {
}
}));
MessageTray.Source.prototype.notify.call(this, notification);
this.parent(notification);
},
createNotificationIcon: function() {
@ -366,21 +361,17 @@ Source.prototype = {
icon_type: St.IconType.SYMBOLIC,
icon_size: this.ICON_SIZE });
}
}
});
function AuthNotification() {
this._init.apply(this, arguments);
}
AuthNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const AuthNotification = new Lang.Class({
Name: 'AuthNotification',
Extends: MessageTray.Notification,
_init: function(source, applet, device_path, name, long_name, uuid) {
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Authorization request from %s").format(name),
{ customContent: true });
this.parent(source,
_("Bluetooth"),
_("Authorization request from %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -406,21 +397,17 @@ AuthNotification.prototype = {
this.destroy();
}));
}
}
});
function ConfirmNotification() {
this._init.apply(this, arguments);
}
ConfirmNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const ConfirmNotification = new Lang.Class({
Name: 'ConfirmNotification',
Extends: MessageTray.Notification,
_init: function(source, applet, device_path, name, long_name, pin) {
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Pairing confirmation for %s").format(name),
{ customContent: true });
this.parent(source,
_("Bluetooth"),
_("Pairing confirmation for %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -439,21 +426,17 @@ ConfirmNotification.prototype = {
this.destroy();
}));
}
}
});
function PinNotification() {
this._init.apply(this, arguments);
}
PinNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const PinNotification = new Lang.Class({
Name: 'PinNotification',
Extends: MessageTray.Notification,
_init: function(source, applet, device_path, name, long_name, numeric) {
MessageTray.Notification.prototype._init.call(this,
source,
_("Bluetooth"),
_("Pairing request for %s").format(name),
{ customContent: true });
this.parent(source,
_("Bluetooth"),
_("Pairing request for %s").format(name),
{ customContent: true });
this.setResident(true);
this._applet = applet;
@ -502,7 +485,7 @@ PinNotification.prototype = {
},
grabFocus: function(lockTray) {
MessageTray.Notification.prototype.grabFocus.call(this, lockTray);
this.parent(lockTray);
global.stage.set_key_focus(this._entry);
}
}
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GdkPixbuf = imports.gi.GdkPixbuf;
@ -14,15 +14,12 @@ const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const Util = imports.misc.util;
function LayoutMenuItem() {
this._init.apply(this, arguments);
}
LayoutMenuItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const LayoutMenuItem = new Lang.Class({
Name: 'LayoutMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(config, id, indicator, long_name) {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this.parent();
this._config = config;
this._id = id;
@ -33,20 +30,18 @@ LayoutMenuItem.prototype = {
},
activate: function(event) {
PopupMenu.PopupBaseMenuItem.prototype.activate.call(this);
this.parent(event);
this._config.lock_group(this._id);
}
};
});
function XKBIndicator() {
this._init.call(this);
}
XKBIndicator.prototype = {
__proto__: PanelMenu.Button.prototype,
const XKBIndicator = new Lang.Class({
Name: 'XKBIndicator',
Extends: PanelMenu.Button,
_init: function() {
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this.parent(0.0);
this._container = new Shell.GenericContainer();
this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
@ -221,4 +216,4 @@ XKBIndicator.prototype = {
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].allocate_align_fill(box, 0.5, 0, false, false, flags);
}
};
});

View File

@ -1,6 +1,5 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const ByteArray = imports.byteArray;
const DBus = imports.dbus;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
@ -98,15 +97,12 @@ function ssidToLabel(ssid) {
return label;
}
function NMNetworkMenuItem() {
this._init.apply(this, arguments);
}
NMNetworkMenuItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const NMNetworkMenuItem = new Lang.Class({
Name: 'NMNetworkMenuItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(accessPoints, title, params) {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);
this.parent(params);
accessPoints = sortAccessPoints(accessPoints);
this.bestAP = accessPoints[0];
@ -185,21 +181,18 @@ NMNetworkMenuItem.prototype = {
apObj.updateId = 0;
}
PopupMenu.PopupBaseMenuItem.prototype.destroy.call(this);
this.parent();
}
};
});
function NMWiredSectionTitleMenuItem() {
this._init.apply(this, arguments);
}
NMWiredSectionTitleMenuItem.prototype = {
__proto__: PopupMenu.PopupSwitchMenuItem.prototype,
const NMWiredSectionTitleMenuItem = new Lang.Class({
Name: 'NMWiredSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
_init: function(label, params) {
params = params || { };
params.style_class = 'popup-subtitle-menu-item';
PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, label, false, params);
this.parent(label, false, params);
},
updateForDevice: function(device) {
@ -212,7 +205,7 @@ NMWiredSectionTitleMenuItem.prototype = {
},
activate: function(event) {
PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
this.parent(event);
if (!this._device) {
log('Section title activated when there is more than one device, should be non reactive');
@ -231,19 +224,16 @@ NMWiredSectionTitleMenuItem.prototype = {
else
this._device.deactivate();
}
};
});
function NMWirelessSectionTitleMenuItem() {
this._init.apply(this, arguments);
}
NMWirelessSectionTitleMenuItem.prototype = {
__proto__: PopupMenu.PopupSwitchMenuItem.prototype,
const NMWirelessSectionTitleMenuItem = new Lang.Class({
Name: 'NMWirelessSectionTitleMenuItem',
Extends: PopupMenu.PopupSwitchMenuItem,
_init: function(client, property, title, params) {
params = params || { };
params.style_class = 'popup-subtitle-menu-item';
PopupMenu.PopupSwitchMenuItem.prototype._init.call(this, title, false, params);
this.parent(title, false, params);
this._client = client;
this._property = property + '_enabled';
@ -269,7 +259,7 @@ NMWirelessSectionTitleMenuItem.prototype = {
},
activate: function(event) {
PopupMenu.PopupSwitchMenuItem.prototype.activate.call(this, event);
this.parent(event);
this._client[this._setEnabledFunc](this._switch.state);
},
@ -286,13 +276,12 @@ NMWirelessSectionTitleMenuItem.prototype = {
this.emit('enabled-changed', enabled);
}
};
});
function NMDevice() {
throw new TypeError('Instantanting abstract class NMDevice');
}
const NMDevice = new Lang.Class({
Name: 'NMDevice',
Abstract: true,
NMDevice.prototype = {
_init: function(client, device, connections) {
this.device = device;
if (device) {
@ -674,26 +663,23 @@ NMDevice.prototype = {
return out;
}
};
});
Signals.addSignalMethods(NMDevice.prototype);
function NMDeviceWired() {
this._init.apply(this, arguments);
}
NMDeviceWired.prototype = {
__proto__: NMDevice.prototype,
const NMDeviceWired = new Lang.Class({
Name: 'NMDeviceWired',
Extends: NMDevice,
_init: function(client, device, connections) {
this._autoConnectionName = _("Auto Ethernet");
this.category = NMConnectionCategory.WIRED;
NMDevice.prototype._init.call(this, client, device, connections);
this.parent(client, device, connections);
},
_createSection: function() {
NMDevice.prototype._createSection.call(this);
this.parent();
// if we have only one connection (normal or automatic)
// we hide the connection list, and use the switch to control
@ -718,14 +704,11 @@ NMDeviceWired.prototype = {
}));
return connection;
}
};
});
function NMDeviceModem() {
this._init.apply(this, arguments);
}
NMDeviceModem.prototype = {
__proto__: NMDevice.prototype,
const NMDeviceModem = new Lang.Class({
Name: 'NMDeviceModem',
Extends: NMDevice,
_init: function(client, device, connections) {
let is_wwan = false;
@ -774,7 +757,7 @@ NMDeviceModem.prototype = {
}));
}
NMDevice.prototype._init.call(this, client, device, connections);
this.parent(client, device, connections);
},
setEnabled: function(enabled) {
@ -787,7 +770,7 @@ NMDeviceModem.prototype = {
this.statusItem.setStatus(this.getStatusLabel());
}
NMDevice.prototype.setEnabled.call(this, enabled);
this.parent(enabled);
},
get connected() {
@ -804,7 +787,7 @@ NMDeviceModem.prototype = {
this._signalQualityId = 0;
}
NMDevice.prototype.destroy.call(this);
this.parent();
},
_getSignalIcon: function() {
@ -825,13 +808,13 @@ NMDeviceModem.prototype = {
this.section.addMenuItem(this._operatorItem);
}
NMDevice.prototype._createSection.call(this);
this.parent();
},
_clearSection: function() {
this._operatorItem = null;
NMDevice.prototype._clearSection.call(this);
this.parent();
},
_createAutomaticConnection: function() {
@ -841,14 +824,11 @@ NMDeviceModem.prototype = {
'connect-3g', this.device.get_path()]);
return null;
}
};
});
function NMDeviceBluetooth() {
this._init.apply(this, arguments);
}
NMDeviceBluetooth.prototype = {
__proto__: NMDevice.prototype,
const NMDeviceBluetooth = new Lang.Class({
Name: 'NMDeviceBluetooth',
Extends: NMDevice,
_init: function(client, device, connections) {
this._autoConnectionName = this._makeConnectionName(device);
@ -856,7 +836,7 @@ NMDeviceBluetooth.prototype = {
this.category = NMConnectionCategory.WWAN;
NMDevice.prototype._init.call(this, client, device, connections);
this.parent(client, device, connections);
},
_createAutomaticConnection: function() {
@ -886,23 +866,20 @@ NMDeviceBluetooth.prototype = {
this._clearSection();
this._createSection();
}
};
});
// Not a real device, but I save a lot code this way
function NMDeviceVPN() {
this._init.apply(this, arguments);
}
NMDeviceVPN.prototype = {
__proto__: NMDevice.prototype,
const NMDeviceVPN = new Lang.Class({
Name: 'NMDeviceVPN',
Extends: NMDevice,
_init: function(client) {
// Disable autoconnections
this._autoConnectionName = null;
this.category = NMConnectionCategory.VPN;
NMDevice.prototype._init.call(this, client, null, [ ]);
this.parent(client, null, [ ]);
},
connectionValid: function(connection) {
@ -918,7 +895,7 @@ NMDeviceVPN.prototype = {
},
setActiveConnection: function(activeConnection) {
NMDevice.prototype.setActiveConnection.call(this, activeConnection);
this.parent(activeConnection);
this.emit('active-connection-changed');
},
@ -935,14 +912,11 @@ NMDeviceVPN.prototype = {
getStatusLabel: function() {
return null;
}
};
});
function NMDeviceWireless() {
this._init.apply(this, arguments);
}
NMDeviceWireless.prototype = {
__proto__: NMDevice.prototype,
const NMDeviceWireless = new Lang.Class({
Name: 'NMDeviceWireless',
Extends: NMDevice,
_init: function(client, device, connections) {
this.category = NMConnectionCategory.WIRELESS;
@ -1014,7 +988,7 @@ NMDeviceWireless.prototype = {
this._apAddedId = device.connect('access-point-added', Lang.bind(this, this._accessPointAdded));
this._apRemovedId = device.connect('access-point-removed', Lang.bind(this, this._accessPointRemoved));
NMDevice.prototype._init.call(this, client, device, validConnections);
this.parent(client, device, validConnections);
},
destroy: function() {
@ -1034,7 +1008,7 @@ NMDeviceWireless.prototype = {
this._apRemovedId = 0;
}
NMDevice.prototype.destroy.call(this);
this.parent();
},
setEnabled: function(enabled) {
@ -1104,10 +1078,10 @@ NMDeviceWireless.prototype = {
let activeAp = this.device.active_access_point;
if (activeAp) {
let pos = this._findNetwork(activeAp);
let res = this._findExistingNetwork(activeAp);
if (pos != -1)
this._activeNetwork = this._networks[pos];
if (res != null)
this._activeNetwork = this._networks[res.network];
}
// we don't refresh the view here, setActiveConnection will
@ -1181,6 +1155,18 @@ NMDeviceWireless.prototype = {
return true;
},
_findExistingNetwork: function(accessPoint) {
for (let i = 0; i < this._networks.length; i++) {
let apObj = this._networks[i];
for (let j = 0; j < apObj.accessPoints.length; j++) {
if (apObj.accessPoints[j] == accessPoint)
return { network: i, ap: j };
}
}
return null;
},
_findNetwork: function(accessPoint) {
if (accessPoint.get_ssid() == null)
return -1;
@ -1273,22 +1259,15 @@ NMDeviceWireless.prototype = {
},
_accessPointRemoved: function(device, accessPoint) {
let pos = this._findNetwork(accessPoint);
let res = this._findExistingNetwork(accessPoint);
if (pos == -1) {
if (res == null) {
log('Removing an access point that was never added');
return;
}
let apObj = this._networks[pos];
let i = apObj.accessPoints.indexOf(accessPoint);
if (i == -1) {
log('Removing an access point that was never added');
return;
}
apObj.accessPoints.splice(i, 1);
let apObj = this._networks[res.network];
apObj.accessPoints.splice(res.ap, 1);
if (apObj.accessPoints.length == 0) {
if (this._activeNetwork == apObj)
@ -1302,22 +1281,26 @@ NMDeviceWireless.prototype = {
// we removed an item in the main menu, and we have a more submenu
// we need to extract the first item in more and move it to the submenu
let apObj = this._overflowItem.menu.firstMenuItem;
if (apObj.item) {
apObj.item.destroy();
let item = this._overflowItem.menu.firstMenuItem;
if (item && item._apObj) {
item.destroy();
// clear the cycle, and allow the construction of the new item
item._apObj.item = null;
this._createNetworkItem(apObj, NUM_VISIBLE_NETWORKS-1);
this._createNetworkItem(item._apObj, NUM_VISIBLE_NETWORKS-1);
} else {
log('The more... menu was existing and empty! This should not happen');
}
}
// This can happen if the removed connection is from the overflow
// menu, or if we just moved the last connection out from the menu
if (this._overflowItem.menu.length == 0) {
if (this._overflowItem.menu.numMenuItems == 0) {
this._overflowItem.destroy();
this._overflowItem = null;
}
}
this._networks.splice(pos, 1);
this._networks.splice(res.network, 1);
} else if (apObj.item)
apObj.item.updateAccessPoints(apObj.accessPoints);
@ -1339,7 +1322,7 @@ NMDeviceWireless.prototype = {
},
_clearSection: function() {
NMDevice.prototype._clearSection.call(this);
this.parent();
for (let i = 0; i < this._networks.length; i++)
this._networks[i].item = null;
@ -1489,18 +1472,16 @@ NMDeviceWireless.prototype = {
}
if(apObj.connections.length > 0) {
if (apObj.connections.length == 1)
if (apObj.connections.length == 1) {
apObj.item = this._createAPItem(apObj.connections[0], apObj, false);
else {
} else {
let title = apObj.ssidText;
apObj.item = new PopupMenu.PopupSubMenuMenuItem(title);
apObj.item._apObj = apObj;
for (let i = 0; i < apObj.connections.length; i++)
apObj.item.menu.addMenuItem(this._createAPItem(apObj.connections[i], apObj, true));
}
} else {
apObj.item = new NMNetworkMenuItem(apObj.accessPoints);
apObj.item._apObj = apObj;
apObj.item.connect('activate', Lang.bind(this, function() {
let accessPoints = sortAccessPoints(apObj.accessPoints);
if ( (accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
@ -1515,6 +1496,8 @@ NMDeviceWireless.prototype = {
}
}));
}
apObj.item._apObj = apObj;
if (position < NUM_VISIBLE_NETWORKS) {
apObj.isMore = false;
this.section.addMenuItem(apObj.item, position);
@ -1547,16 +1530,14 @@ NMDeviceWireless.prototype = {
this._createNetworkItem(apObj, j + activeOffset);
}
},
};
});
function NMApplet() {
this._init.apply(this, arguments);
}
NMApplet.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const NMApplet = new Lang.Class({
Name: 'NMApplet',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'network-error');
this.parent('network-error', null);
this._client = NMClient.Client.new();
@ -2056,10 +2037,11 @@ NMApplet.prototype = {
}
this.setIcon('network-wireless-connected');
} else {
if (this._accessPointUpdateId && this._activeAccessPoint != ap) {
this._activeAccessPoint.disconnect(this._accessPointUpdateId);
if (this._activeAccessPoint != ap) {
if (this._accessPointUpdateId)
this._activeAccessPoint.disconnect(this._accessPointUpdateId);
this._activeAccessPoint = ap;
this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(function() {
this._activeAccessPointUpdateId = ap.connect('notify::strength', Lang.bind(this, function() {
this.setIcon('network-wireless-signal-' + signalToIcon(ap.strength));
}));
}
@ -2086,8 +2068,9 @@ NMApplet.prototype = {
break;
}
if (this._mobileUpdateId && this._mobileUpdateDevice != dev) {
this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
if (dev.mobileDevice != this._mobileUpdateDevice) {
if (this._mobileUpdateId)
this._mobileUpdateDevice.disconnect(this._mobileUpdateId);
this._mobileUpdateDevice = dev.mobileDevice;
this._mobileUpdateId = dev.mobileDevice.connect('notify::signal-quality', Lang.bind(this, function() {
this.setIcon('network-cellular-signal-' + signalToIcon(dev.mobileDevice.signal_quality));
@ -2120,17 +2103,14 @@ NMApplet.prototype = {
this._mobileUpdateId = 0;
}
}
};
});
function NMMessageTraySource() {
this._init();
}
NMMessageTraySource.prototype = {
__proto__: MessageTray.Source.prototype,
const NMMessageTraySource = new Lang.Class({
Name: 'NMMessageTraySource',
Extends: MessageTray.Source,
_init: function() {
MessageTray.Source.prototype._init.call(this, _("Network Manager"));
this.parent(_("Network Manager"));
let icon = new St.Icon({ icon_name: 'network-transmit-receive',
icon_type: St.IconType.SYMBOLIC,
@ -2138,4 +2118,4 @@ NMMessageTraySource.prototype = {
});
this._setSummaryIcon(icon);
}
};
});

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Gio = imports.gi.Gio;
const DBus = imports.dbus;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
@ -40,31 +39,27 @@ const UPDeviceState = {
PENDING_DISCHARGE: 6
};
const PowerManagerInterface = {
name: 'org.gnome.SettingsDaemon.Power',
methods: [
{ name: 'GetDevices', inSignature: '', outSignature: 'a(susbut)' },
{ name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susbut)' },
],
signals: [
{ name: 'Changed', inSignature: '' },
],
properties: [
{ name: 'Icon', signature: 's', access: 'read' },
]
};
let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
<method name="GetDevices">
<arg type="a(susdut)" direction="out" />
</method>
<method name="GetPrimaryDevice">
<arg type="(susdut)" direction="out" />
</method>
<signal name="Changed" />
<property name="Icon" type="s" access="read" />
</interface>;
function Indicator() {
this._init.apply(this, arguments);
}
const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const Indicator = new Lang.Class({
Name: 'PowerIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'battery-missing');
this._proxy = new PowerManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
this.parent('battery-missing', null);
this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH);
this._deviceItems = [ ];
this._hasPrimary = false;
@ -81,19 +76,19 @@ Indicator.prototype = {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addSettingsAction(_("Power Settings"), 'gnome-power-panel.desktop');
this._proxy.connect('Changed', Lang.bind(this, this._devicesChanged));
this._proxy.connectSignal('Changed', Lang.bind(this, this._devicesChanged));
this._devicesChanged();
},
_readPrimaryDevice: function() {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(device, error) {
this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
if (error) {
this._hasPrimary = false;
this._primaryDeviceId = null;
this._batteryItem.actor.hide();
return;
}
let [device_id, device_type, icon, percentage, state, seconds] = device;
let [[device_id, device_type, icon, percentage, state, seconds]] = result;
if (device_type == UPDeviceType.BATTERY) {
this._hasPrimary = true;
let time = Math.round(seconds / 60);
@ -130,7 +125,7 @@ Indicator.prototype = {
},
_readOtherDevices: function() {
this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
this._proxy.GetDevicesRemote(Lang.bind(this, function(result, error) {
this._deviceItems.forEach(function(i) { i.destroy(); });
this._deviceItems = [];
@ -139,6 +134,7 @@ Indicator.prototype = {
}
let position = 0;
let [devices] = result;
for (let i = 0; i < devices.length; i++) {
let [device_id, device_type] = devices[i];
if (device_type == UPDeviceType.AC_POWER || device_id == this._primaryDeviceId)
@ -153,37 +149,33 @@ Indicator.prototype = {
},
_devicesChanged: function() {
this._proxy.GetRemote('Icon', Lang.bind(this, function(icon, error) {
if (icon) {
let gicon = Shell.util_icon_from_string (icon);
this.setGIcon(gicon);
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
}));
let icon = this._proxy.Icon;
if (icon) {
let gicon = Gio.icon_new_for_string(icon);
this.setGIcon(gicon);
this.actor.show();
} else {
this.menu.close();
this.actor.hide();
}
this._readPrimaryDevice();
this._readOtherDevices();
}
};
});
function DeviceItem() {
this._init.apply(this, arguments);
}
DeviceItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const DeviceItem = new Lang.Class({
Name: 'DeviceItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(device) {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, { reactive: false });
this.parent({ reactive: false });
let [device_id, device_type, icon, percentage, state, time] = device;
this._box = new St.BoxLayout({ style_class: 'popup-device-menu-item' });
this._label = new St.Label({ text: this._deviceTypeToString(device_type) });
this._icon = new St.Icon({ gicon: Shell.util_icon_from_string(icon),
this._icon = new St.Icon({ gicon: Gio.icon_new_for_string(icon),
icon_type: St.IconType.SYMBOLIC,
style_class: 'popup-menu-icon' });
@ -223,4 +215,4 @@ DeviceItem.prototype = {
return _("Unknown");
}
}
}
});

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const DBus = imports.dbus;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
@ -18,15 +17,12 @@ const VOLUME_ADJUSTMENT_STEP = 0.05; /* Volume adjustment step in % */
const VOLUME_NOTIFY_ID = 1;
function Indicator() {
this._init.apply(this, arguments);
}
Indicator.prototype = {
__proto__: PanelMenu.SystemStatusButton.prototype,
const Indicator = new Lang.Class({
Name: 'VolumeIndicator',
Extends: PanelMenu.SystemStatusButton,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'audio-volume-muted', null);
this.parent('audio-volume-muted', null);
this._control = new Gvc.MixerControl({ name: 'GNOME Shell Volume Control' });
this._control.connect('state-changed', Lang.bind(this, this._onControlStateChanged));
@ -215,4 +211,4 @@ Indicator.prototype = {
if (property == '_output' && !this._output.is_muted)
this.setIcon(this._volumeToIcon(this._output.volume));
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Shell = imports.gi.Shell;
@ -23,11 +23,9 @@ const STANDARD_TRAY_ICON_IMPLEMENTATIONS = {
'ibus-ui-gtk': 'input-method'
};
function StatusIconDispatcher() {
this._init();
}
const StatusIconDispatcher = new Lang.Class({
Name: 'StatusIconDispatcher',
StatusIconDispatcher.prototype = {
_init: function() {
this._traymanager = new Shell.TrayManager();
this._traymanager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
@ -61,5 +59,5 @@ StatusIconDispatcher.prototype = {
else
this.emit('message-icon-removed', icon);
}
};
});
Signals.addSignalMethods(StatusIconDispatcher.prototype);

View File

@ -1,6 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
@ -73,11 +72,9 @@ function makeMessageFromTplEvent(event) {
};
}
function Client() {
this._init();
};
const Client = new Lang.Class({
Name: 'Client',
Client.prototype = {
_init : function() {
// channel path -> ChatSource
this._chatSources = {};
@ -257,7 +254,7 @@ Client.prototype = {
// FIXME: We don't have a 'chat room' icon (bgo #653737) use
// system-users for now as Empathy does.
let source = new ApproverSource(dispatchOp, _("Invitation"),
Shell.util_icon_from_string('system-users'));
Gio.icon_new_for_string('system-users'));
Main.messageTray.add(source);
let notif = new RoomInviteNotification(source, dispatchOp, channel, contacts[0]);
@ -325,8 +322,8 @@ Client.prototype = {
// We got the TpContact
let source = new ApproverSource(dispatchOp, _("Call"), isVideo ?
Shell.util_icon_from_string('camera-web') :
Shell.util_icon_from_string('audio-input-microphone'));
Gio.icon_new_for_string('camera-web') :
Gio.icon_new_for_string('audio-input-microphone'));
Main.messageTray.add(source);
let notif = new AudioVideoNotification(source, dispatchOp, channel, contacts[0], isVideo);
@ -480,17 +477,14 @@ Client.prototype = {
return this._accountSource;
}
};
});
function ChatSource(account, conn, channel, contact, client) {
this._init(account, conn, channel, contact, client);
}
ChatSource.prototype = {
__proto__: MessageTray.Source.prototype,
const ChatSource = new Lang.Class({
Name: 'ChatSource',
Extends: MessageTray.Source,
_init: function(account, conn, channel, contact, client) {
MessageTray.Source.prototype._init.call(this, contact.get_alias());
this.parent(contact.get_alias());
this.isChat = true;
@ -539,9 +533,13 @@ ChatSource.prototype = {
_updateAlias: function() {
let oldAlias = this.title;
this.setTitle(this._contact.get_alias());
this._notification.appendAliasChange(oldAlias, this.title);
this.pushNotification(this._notification);
let newAlias = this._contact.get_alias();
if (oldAlias == newAlias)
return;
this.setTitle(newAlias);
this._notification.appendAliasChange(oldAlias, newAlias);
},
createNotificationIcon: function() {
@ -570,7 +568,7 @@ ChatSource.prototype = {
open: function(notification) {
if (this._client.is_handling_channel(this._channel)) {
// We are handling the channel, try to pass it to Empathy
this._client.delegate_channels_async([this._channel], global.get_current_time(), "", null);
this._client.delegate_channels_async([this._channel], global.get_current_time(), '', null);
}
else {
// We are not the handler, just ask to present the channel
@ -694,7 +692,7 @@ ChatSource.prototype = {
},
notify: function() {
MessageTray.Source.prototype.notify.call(this, this._notification);
this.parent(this._notification);
},
respond: function(text) {
@ -795,17 +793,14 @@ ChatSource.prototype = {
this._shouldAck = false;
}
};
});
function ChatNotification(source) {
this._init(source);
}
ChatNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const ChatNotification = new Lang.Class({
Name: 'ChatNotification',
Extends: MessageTray.Notification,
_init: function(source) {
MessageTray.Notification.prototype._init.call(this, source, source.title, null, { customContent: true });
this.parent(source, source.title, null, { customContent: true });
this.setResident(true);
this._responseEntry = new St.Entry({ style_class: 'chat-response',
@ -896,7 +891,7 @@ ChatNotification.prototype = {
}
let groups = this._contentArea.get_children();
for (let i = 0; i < groups.length; i ++) {
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
if (group.get_children().length == 0)
group.destroy();
@ -934,7 +929,7 @@ ChatNotification.prototype = {
let body = highlighter.actor;
let styles = props.styles;
for (let i = 0; i < styles.length; i ++)
for (let i = 0; i < styles.length; i++)
body.add_style_class_name(styles[i]);
let group = props.group;
@ -1088,17 +1083,14 @@ ChatNotification.prototype = {
this.source.setChatState(Tp.ChannelChatState.ACTIVE);
}
}
};
});
function ApproverSource(dispatchOp, text, gicon) {
this._init(dispatchOp, text, gicon);
}
ApproverSource.prototype = {
__proto__: MessageTray.Source.prototype,
const ApproverSource = new Lang.Class({
Name: 'ApproverSource',
Extends: MessageTray.Source,
_init: function(dispatchOp, text, gicon) {
MessageTray.Source.prototype._init.call(this, text);
this.parent(text);
this._gicon = gicon;
this._setSummaryIcon(this.createNotificationIcon());
@ -1119,7 +1111,7 @@ ApproverSource.prototype = {
this._invalidId = 0;
}
MessageTray.Source.prototype.destroy.call(this);
this.parent();
},
createNotificationIcon: function() {
@ -1127,23 +1119,19 @@ ApproverSource.prototype = {
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
}
});
function RoomInviteNotification(source, dispatchOp, channel, inviter) {
this._init(source, dispatchOp, channel, inviter);
}
RoomInviteNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const RoomInviteNotification = new Lang.Class({
Name: 'RoomInviteNotification',
Extends: MessageTray.Notification,
_init: function(source, dispatchOp, channel, inviter) {
MessageTray.Notification.prototype._init.call(this,
source,
/* translators: argument is a room name like
* room@jabber.org for example. */
_("Invitation to %s").format(channel.get_identifier()),
null,
{ customContent: true });
this.parent(source,
/* translators: argument is a room name like
* room@jabber.org for example. */
_("Invitation to %s").format(channel.get_identifier()),
null,
{ customContent: true });
this.setResident(true);
/* translators: first argument is the name of a contact and the second
@ -1170,15 +1158,12 @@ RoomInviteNotification.prototype = {
this.destroy();
}));
}
};
});
// Audio Video
function AudioVideoNotification(source, dispatchOp, channel, contact, isVideo) {
this._init(source, dispatchOp, channel, contact, isVideo);
}
AudioVideoNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const AudioVideoNotification = new Lang.Class({
Name: 'AudioVideoNotification',
Extends: MessageTray.Notification,
_init: function(source, dispatchOp, channel, contact, isVideo) {
let title = '';
@ -1190,14 +1175,11 @@ AudioVideoNotification.prototype = {
/* translators: argument is a contact name like Alice for example. */
title = _("Call from %s").format(contact.get_alias());
MessageTray.Notification.prototype._init.call(this,
source,
title,
null,
{ customContent: true });
this.parent(this, source, title, null, { customContent: true });
this.setResident(true);
this.addButton('reject', _("Reject"));
/* translators: this is a button label (verb), not a noun */
this.addButton('answer', _("Answer"));
this.connect('action-invoked', Lang.bind(this, function(self, action) {
@ -1216,28 +1198,25 @@ AudioVideoNotification.prototype = {
this.destroy();
}));
}
};
});
// File Transfer
function FileTransferNotification(source, dispatchOp, channel, contact) {
this._init(source, dispatchOp, channel, contact);
}
FileTransferNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const FileTransferNotification = new Lang.Class({
Name: 'FileTransferNotification',
Extends: MessageTray.Notification,
_init: function(source, dispatchOp, channel, contact) {
MessageTray.Notification.prototype._init.call(this,
source,
/* To translators: The first parameter is
* the contact's alias and the second one is the
* file name. The string will be something
* like: "Alice is sending you test.ogg"
*/
_("%s is sending you %s").format(contact.get_alias(),
channel.get_filename()),
null,
{ customContent: true });
this.parent(this,
source,
/* To translators: The first parameter is
* the contact's alias and the second one is the
* file name. The string will be something
* like: "Alice is sending you test.ogg"
*/
_("%s is sending you %s").format(contact.get_alias(),
channel.get_filename()),
null,
{ customContent: true });
this.setResident(true);
this.addButton('decline', _("Decline"));
@ -1259,18 +1238,15 @@ FileTransferNotification.prototype = {
this.destroy();
}));
}
};
});
// A notification source that can embed multiple notifications
function MultiNotificationSource(title, icon) {
this._init(title, icon);
}
MultiNotificationSource.prototype = {
__proto__: MessageTray.Source.prototype,
const MultiNotificationSource = new Lang.Class({
Name: 'MultiNotificationSource',
Extends: MessageTray.Source,
_init: function(title, icon) {
MessageTray.Source.prototype._init.call(this, title);
this.parent(title);
this._icon = icon;
this._setSummaryIcon(this.createNotificationIcon());
@ -1278,7 +1254,7 @@ MultiNotificationSource.prototype = {
},
notify: function(notification) {
MessageTray.Source.prototype.notify.call(this, notification);
this.parent(notification);
this._nbNotifications += 1;
@ -1292,25 +1268,22 @@ MultiNotificationSource.prototype = {
},
createNotificationIcon: function() {
return new St.Icon({ gicon: Shell.util_icon_from_string(this._icon),
return new St.Icon({ gicon: Gio.icon_new_for_string(this._icon),
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
};
});
// Subscription request
function SubscriptionRequestNotification(source, contact) {
this._init(source, contact);
}
SubscriptionRequestNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const SubscriptionRequestNotification = new Lang.Class({
Name: 'SubscriptionRequestNotification',
Extends: MessageTray.Notification,
_init: function(source, contact) {
MessageTray.Notification.prototype._init.call(this, source,
/* To translators: The parameter is the contact's alias */
_("%s would like permission to see when you are online").format(contact.get_alias()),
null, { customContent: true });
this.parent(this, source,
/* To translators: The parameter is the contact's alias */
_("%s would like permission to see when you are online").format(contact.get_alias()),
null, { customContent: true });
this._contact = contact;
this._connection = contact.get_connection();
@ -1384,7 +1357,7 @@ SubscriptionRequestNotification.prototype = {
this._invalidatedId = 0;
}
MessageTray.Notification.prototype.destroy.call(this);
this.parent();
},
_subscriptionStatesChangedCb: function(contact, subscribe, publish, msg) {
@ -1393,12 +1366,7 @@ SubscriptionRequestNotification.prototype = {
if (publish != Tp.SubscriptionState.ASK)
this.destroy();
}
};
function AccountNotification(source, account, connectionError) {
this._init(source, account, connectionError);
}
});
// Messages from empathy/libempathy/empathy-utils.c
// create_errors_to_message_hash()
@ -1453,15 +1421,16 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_INSECURE)]
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_LIMIT_EXCEEDED)]
= _("The length of the server certificate, or the depth of the server certificate chain, exceed the limits imposed by the cryptography library");
AccountNotification.prototype = {
__proto__: MessageTray.Notification.prototype,
const AccountNotification = new Lang.Class({
Name: 'AccountNotification',
Extends: MessageTray.Notification,
_init: function(source, account, connectionError) {
MessageTray.Notification.prototype._init.call(this, source,
/* translators: argument is the account name, like
* name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
this.parent(source,
/* translators: argument is the account name, like
* name@jabber.org for example. */
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
this._label = new St.Label();
this.addActor(this._label);
@ -1537,6 +1506,6 @@ AccountNotification.prototype = {
this._connectionStatusId = 0;
}
MessageTray.Notification.prototype.destroy.call(this);
this.parent();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -202,11 +202,9 @@ function registerSpecialPropertySplitter(name, splitFunction, parameters) {
// time updates; even better is to pay attention to the vertical
// vblank and sync to that when possible.)
//
function ClutterFrameTicker() {
this._init();
}
const ClutterFrameTicker = new Lang.Class({
Name: 'ClutterFrameTicker',
ClutterFrameTicker.prototype = {
FRAME_RATE : 60,
_init : function() {
@ -261,6 +259,6 @@ ClutterFrameTicker.prototype = {
this._startTime = -1;
global.end_work();
}
};
});
Signals.addSignalMethods(ClutterFrameTicker.prototype);

View File

@ -1,7 +1,6 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const AccountsService = imports.gi.AccountsService;
const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
@ -41,15 +40,12 @@ const IMStatus = {
// Copyright (C) 2008,2009 Red Hat, Inc.
function IMStatusItem(label, iconName) {
this._init(label, iconName);
}
IMStatusItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const IMStatusItem = new Lang.Class({
Name: 'IMStatusItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(label, iconName) {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this);
this.parent();
this.actor.add_style_class_name('status-chooser-status-item');
@ -62,19 +58,15 @@ IMStatusItem.prototype = {
this.label = new St.Label({ text: label });
this.addActor(this.label);
}
};
});
function IMUserNameItem() {
this._init();
}
IMUserNameItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const IMUserNameItem = new Lang.Class({
Name: 'IMUserNameItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function() {
PopupMenu.PopupBaseMenuItem.prototype._init.call(this,
{ reactive: false,
style_class: 'status-chooser-user-name' });
this.parent({ reactive: false,
style_class: 'status-chooser-user-name' });
this._wrapper = new Shell.GenericContainer();
this._wrapper.connect('get-preferred-width',
@ -103,19 +95,15 @@ IMUserNameItem.prototype = {
_wrapperAllocate: function(actor, box, flags) {
this.label.allocate(box, flags);
}
};
});
function IMStatusChooserItem() {
this._init();
}
IMStatusChooserItem.prototype = {
__proto__: PopupMenu.PopupBaseMenuItem.prototype,
const IMStatusChooserItem = new Lang.Class({
Name: 'IMStatusChooserItem',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function() {
PopupMenu.PopupBaseMenuItem.prototype._init.call (this,
{ reactive: false,
style_class: 'status-chooser' });
this.parent({ reactive: false,
style_class: 'status-chooser' });
this._iconBin = new St.Button({ style_class: 'status-chooser-user-icon' });
this.addActor(this._iconBin);
@ -158,22 +146,39 @@ IMStatusChooserItem.prototype = {
Lang.bind(this, this._changeIMStatus));
this._presence = new GnomeSession.Presence();
this._presence.getStatus(Lang.bind(this, this._sessionStatusChanged));
this._presence.connect('StatusChanged',
Lang.bind(this, this._sessionStatusChanged));
this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
this._sessionStatusChanged(status);
}));
this._sessionPresenceRestored = false;
this._imPresenceRestored = false;
this._currentPresence = undefined;
this._previousPresence = undefined;
this._accountMgr = Tp.AccountManager.dup()
this._accountMgr = Tp.AccountManager.dup();
this._accountMgr.connect('most-available-presence-changed',
Lang.bind(this, this._IMStatusChanged));
this._accountMgr.connect('account-enabled',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.connect('account-disabled',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.connect('account-removed',
Lang.bind(this, this._IMAccountsChanged));
this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, s, msg] = mgr.get_most_available_presence();
let [presence, status, msg] = mgr.get_most_available_presence();
this._previousPresence = presence;
this._IMStatusChanged(mgr, presence, s, msg);
let savedPresence = global.settings.get_int('saved-im-presence');
this._IMAccountsChanged(mgr);
if (savedPresence == presence) {
this._IMStatusChanged(mgr, presence, status, msg);
} else {
this._setComboboxPresence(savedPresence);
status = this._statusForPresence(savedPresence);
msg = msg ? msg : '';
mgr.set_all_requested_presences(savedPresence, status, msg);
}
}));
this._userManager = AccountsService.UserManager.get_default();
@ -192,6 +197,21 @@ IMStatusChooserItem.prototype = {
}));
},
destroy: function() {
// clean up signal handlers
if (this._userLoadedId != 0) {
this._user.disconnect(this._userLoadedId);
this._userLoadedId = 0;
}
if (this._userChangedId != 0) {
this._user.disconnect(this._userChangedId);
this._userChangedId = 0;
}
this.parent();
},
// Override getColumnWidths()/setColumnWidths() to make the item
// independent from the overall column layout of the menu
getColumnWidths: function() {
@ -260,20 +280,43 @@ IMStatusChooserItem.prototype = {
}
},
_IMAccountsChanged: function(mgr) {
let accounts = mgr.get_valid_accounts().filter(function(account) {
return account.enabled;
});
this._combo.setSensitive(accounts.length > 0);
},
_IMStatusChanged: function(accountMgr, presence, status, message) {
if (!this._imPresenceRestored)
this._imPresenceRestored = true;
if (presence == this._currentPresence)
return;
this._currentPresence = presence;
this._setComboboxPresence(presence);
if (!this._sessionPresenceRestored) {
this._sessionStatusChanged(this._presence.status);
return;
}
if (presence == Tp.ConnectionPresenceType.AVAILABLE)
this._presence.setStatus(GnomeSession.PresenceStatus.AVAILABLE);
this._presence.status = GnomeSession.PresenceStatus.AVAILABLE;
if (!this._expectedPresence || presence != this._expectedPresence)
this._previousPresence = presence;
// We ignore the actual value of _expectedPresence and never safe
// the first presence change after an "automatic" change, assuming
// that it is the response to our request; this is to account for
// mission control falling back to "similar" presences if an account
// type does not implement the requested presence.
if (!this._expectedPresence)
global.settings.set_int('saved-im-presence', presence);
else
this._expectedPresence = undefined;
},
_setComboboxPresence: function(presence) {
let activatedItem;
if (presence == Tp.ConnectionPresenceType.AVAILABLE)
@ -310,13 +353,16 @@ IMStatusChooserItem.prototype = {
return;
status = this._statusForPresence(newPresence);
msg = msg ? msg : "";
msg = msg ? msg : '';
this._accountMgr.set_all_requested_presences(newPresence, status, msg);
},
getIMPresenceForSessionStatus: function(sessionStatus) {
// Restore the last user-set presence when coming back from
// BUSY/IDLE (otherwise the last user-set presence matches
// the current one)
if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE)
return this._previousPresence;
return global.settings.get_int('saved-im-presence');
if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
// Only change presence if the current one is "more present" than
@ -336,7 +382,21 @@ IMStatusChooserItem.prototype = {
return this._currentPresence;
},
_sessionStatusChanged: function(sessionPresence, sessionStatus) {
_sessionStatusChanged: function(sessionStatus) {
if (!this._imPresenceRestored)
return;
if (!this._sessionPresenceRestored) {
let savedStatus = global.settings.get_int('saved-session-presence');
if (sessionStatus != savedStatus) {
this._presence.status = savedStatus;
return;
}
this._sessionPresenceRestored = true;
}
global.settings.set_int('saved-session-presence', sessionStatus);
let [presence, s, msg] = this._accountMgr.get_most_available_presence();
let newPresence, status;
@ -346,23 +406,21 @@ IMStatusChooserItem.prototype = {
return;
status = this._statusForPresence(newPresence);
msg = msg ? msg : "";
msg = msg ? msg : '';
this._expectedPresence = newPresence;
this._accountMgr.set_all_requested_presences(newPresence, status, msg);
}
};
});
function UserMenuButton() {
this._init();
}
UserMenuButton.prototype = {
__proto__: PanelMenu.Button.prototype,
const UserMenuButton = new Lang.Class({
Name: 'UserMenuButton',
Extends: PanelMenu.Button,
_init: function() {
PanelMenu.Button.prototype._init.call(this, 0.0);
this.parent(0.0);
let box = new St.BoxLayout({ name: 'panelUserMenu' });
this.actor.add_actor(box);
@ -375,7 +433,7 @@ UserMenuButton.prototype = {
this._session = new GnomeSession.SessionManager();
this._haveShutdown = true;
this._account_mgr = Tp.AccountManager.dup()
this._accountMgr = Tp.AccountManager.dup();
this._upClient = new UPowerGlib.Client();
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
@ -398,13 +456,9 @@ UserMenuButton.prototype = {
this._idleIcon = new St.Icon({ icon_name: 'user-idle',
style_class: 'popup-menu-icon' });
this._presence.connect('StatusChanged',
Lang.bind(this, this._updateSwitch));
this._presence.getStatus(Lang.bind(this, this._updateSwitch));
this._account_mgr.connect('most-available-presence-changed',
this._accountMgr.connect('most-available-presence-changed',
Lang.bind(this, this._updatePresenceIcon));
this._account_mgr.prepare_async(null, Lang.bind(this,
this._accountMgr.prepare_async(null, Lang.bind(this,
function(mgr) {
let [presence, s, msg] = mgr.get_most_available_presence();
this._updatePresenceIcon(mgr, presence, s, msg);
@ -417,8 +471,16 @@ UserMenuButton.prototype = {
this._updateUserName();
this._createSubMenu();
this._updateSwitch(this._presence.status);
this._presence.connectSignal('StatusChanged', Lang.bind(this, function (proxy, senderName, [status]) {
this._updateSwitch(status);
}));
this._userManager.connect('notify::is-loaded',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('notify::has-multiple-users',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('user-added',
Lang.bind(this, this._updateSwitchUser));
this._userManager.connect('user-removed',
@ -463,7 +525,9 @@ UserMenuButton.prototype = {
_updateSwitchUser: function() {
let allowSwitch = !this._lockdownSettings.get_boolean(DISABLE_USER_SWITCH_KEY);
if (allowSwitch && this._userManager.can_switch ())
if (allowSwitch &&
this._userManager.can_switch() &&
this._userManager.has_multiple_users)
this._loginScreenItem.actor.show();
else
this._loginScreenItem.actor.hide();
@ -517,7 +581,7 @@ UserMenuButton.prototype = {
}
},
_updateSwitch: function(presence, status) {
_updateSwitch: function(status) {
let active = status == GnomeSession.PresenceStatus.AVAILABLE;
this._notificationsSwitch.setToggleState(active);
},
@ -598,7 +662,7 @@ UserMenuButton.prototype = {
} else {
status = GnomeSession.PresenceStatus.BUSY;
let [presence, s, msg] = this._account_mgr.get_most_available_presence();
let [presence, s, msg] = this._accountMgr.get_most_available_presence();
let newPresence = this._statusChooser.getIMPresenceForSessionStatus(status);
if (newPresence != presence &&
newPresence == Tp.ConnectionPresenceType.BUSY)
@ -606,7 +670,7 @@ UserMenuButton.prototype = {
_("Notifications are now disabled, including chat messages. Your online status has been adjusted to let others know that you might not see their messages."));
}
this._presence.setStatus(status);
this._presence.status = status;
},
_onMyAccountActivate: function() {
@ -659,4 +723,4 @@ UserMenuButton.prototype = {
this._session.ShutdownRemote();
}
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
@ -12,13 +12,12 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const Search = imports.ui.search;
const SearchDisplay = imports.ui.searchDisplay;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
function BaseTab(titleActor, pageActor, name, a11yIcon) {
this._init(titleActor, pageActor, name, a11yIcon);
}
const BaseTab = new Lang.Class({
Name: 'BaseTab',
BaseTab.prototype = {
_init: function(titleActor, pageActor, name, a11yIcon) {
this.title = titleActor;
this.page = new St.Bin({ child: pageActor,
@ -74,16 +73,13 @@ BaseTab.prototype = {
_activate: function() {
this.emit('activated');
}
};
});
Signals.addSignalMethods(BaseTab.prototype);
function ViewTab(id, label, pageActor, a11yIcon) {
this._init(id, label, pageActor, a11yIcon);
}
ViewTab.prototype = {
__proto__: BaseTab.prototype,
const ViewTab = new Lang.Class({
Name: 'ViewTab',
Extends: BaseTab,
_init: function(id, label, pageActor, a11yIcon) {
this.id = id;
@ -92,17 +88,14 @@ ViewTab.prototype = {
style_class: 'view-tab-title' });
titleActor.connect('clicked', Lang.bind(this, this._activate));
BaseTab.prototype._init.call(this, titleActor, pageActor, label, a11yIcon);
this.parent(titleActor, pageActor, label, a11yIcon);
}
};
});
function SearchTab() {
this._init();
}
SearchTab.prototype = {
__proto__: BaseTab.prototype,
const SearchTab = new Lang.Class({
Name: 'SearchTab',
Extends: BaseTab,
_init: function() {
this.active = false;
@ -120,6 +113,7 @@ SearchTab.prototype = {
hint_text: _("Type to search..."),
track_hover: true,
can_focus: true });
ShellEntry.addContextMenu(this._entry);
this._text = this._entry.clutter_text;
this._text.connect('key-press-event', Lang.bind(this, this._onKeyPress));
@ -134,11 +128,7 @@ SearchTab.prototype = {
this._iconClickedId = 0;
this._searchResults = new SearchDisplay.SearchResults(this._searchSystem, this._openSearchSystem);
BaseTab.prototype._init.call(this,
this._entry,
this._searchResults.actor,
_("Search"),
'edit-find');
this.parent(this._entry, this._searchResults.actor, _("Search"), 'edit-find');
this._text.connect('text-changed', Lang.bind(this, this._onTextChanged));
this._text.connect('key-press-event', Lang.bind(this, function (o, e) {
@ -164,7 +154,7 @@ SearchTab.prototype = {
},
hide: function() {
BaseTab.prototype.hide.call(this);
this.parent();
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
@ -289,9 +279,11 @@ SearchTab.prototype = {
_onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
let source = event.get_source();
if (source != this._text && this._text.text == '') {
if (source != this._text && this._text.text == '' &&
!Main.layoutManager.keyboardBox.contains(source)) {
// the user clicked outside after activating the entry, but
// with no search term entered - cancel the search
// with no search term entered and no keyboard button pressed
// - cancel the search
this._reset();
}
}
@ -306,14 +298,12 @@ SearchTab.prototype = {
return false;
}
};
});
function ViewSelector() {
this._init();
}
const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
ViewSelector.prototype = {
_init : function() {
this.actor = new St.BoxLayout({ name: 'viewSelector',
vertical: true });
@ -573,5 +563,5 @@ ViewSelector.prototype = {
removeSearchProvider: function(provider) {
this._searchTab.removeSearchProvider(provider);
}
};
});
Signals.addSignalMethods(ViewSelector.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Shell = imports.gi.Shell;
@ -6,41 +6,14 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
function WindowAttentionHandler() {
this._init();
}
const WindowAttentionHandler = new Lang.Class({
Name: 'WindowAttentionHandler',
WindowAttentionHandler.prototype = {
_init : function() {
this._startupIds = {};
this._tracker = Shell.WindowTracker.get_default();
this._tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
global.display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
},
_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.
@ -57,24 +30,25 @@ WindowAttentionHandler.prototype = {
let source = new Source(app, window);
Main.messageTray.add(source);
let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window));
let banner = _("'%s' is ready").format(window.title);
let title = app.get_name();
let notification = new MessageTray.Notification(source, title, banner);
source.notify(notification);
source.signalIDs.push(window.connect('notify::title', Lang.bind(this, function(win) {
notification.update(this._getTitle(app, win), this._getBanner(app, win));
})));
source.signalIDs.push(window.connect('notify::title',
Lang.bind(this, function() {
notification.update(title, banner);
})));
}
};
});
function Source(app, window) {
this._init(app, window);
}
Source.prototype = {
__proto__ : MessageTray.Source.prototype,
const Source = new Lang.Class({
Name: 'WindowAttentionSource',
Extends: MessageTray.Source,
_init: function(app, window) {
MessageTray.Source.prototype._init.call(this, app.get_name());
this.parent(app.get_name());
this._window = window;
this._app = app;
this._setSummaryIcon(this.createNotificationIcon());
@ -102,4 +76,4 @@ Source.prototype = {
Main.activateWindow(this._window);
this.destroy();
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
@ -31,34 +31,40 @@ function getTopInvisibleBorder(metaWindow) {
return outerRect.y - inputRect.y;
}
function WindowDimmer(actor) {
this._init(actor);
}
const WindowDimmer = new Lang.Class({
Name: 'WindowDimmer',
WindowDimmer.prototype = {
_init: function(actor) {
this.effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
this.effect.set_shader_source(getDimShaderSource());
if (Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL)) {
this._effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
this._effect.set_shader_source(getDimShaderSource());
} else {
this._effect = null;
}
this.actor = actor;
},
set dimFraction(fraction) {
this._dimFraction = fraction;
if (this._effect == null)
return;
if (!Meta.prefs_get_attach_modal_dialogs()) {
this.effect.enabled = false;
this._effect.enabled = false;
return;
}
if (fraction > 0.01) {
Shell.shader_effect_set_double_uniform(this.effect, 'height', this.actor.get_height());
Shell.shader_effect_set_double_uniform(this.effect, 'fraction', fraction);
Shell.shader_effect_set_double_uniform(this._effect, 'height', this.actor.get_height());
Shell.shader_effect_set_double_uniform(this._effect, 'fraction', fraction);
if (!this.effect.actor)
this.actor.add_effect(this.effect);
if (!this._effect.actor)
this.actor.add_effect(this._effect);
} else {
if (this.effect.actor)
this.actor.remove_effect(this.effect);
if (this._effect.actor)
this.actor.remove_effect(this._effect);
}
},
@ -67,7 +73,7 @@ WindowDimmer.prototype = {
},
_dimFraction: 0.0
};
});
function getWindowDimmer(actor) {
if (!actor._windowDimmer)
@ -76,15 +82,12 @@ function getWindowDimmer(actor) {
return actor._windowDimmer;
}
function WindowManager() {
this._init();
}
const WindowManager = new Lang.Class({
Name: 'WindowManager',
WindowManager.prototype = {
_init : function() {
this._shellwm = global.window_manager;
this._keyBindingHandlers = [];
this._minimizing = [];
this._maximizing = [];
this._unmaximizing = [];
@ -113,15 +116,24 @@ WindowManager.prototype = {
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));
this.setKeybindingHandler('switch_group', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_windows_backward', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_group_backward', Lang.bind(this, this._startAppSwitcher));
this.setKeybindingHandler('switch_panels', Lang.bind(this, this._startA11ySwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-left',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-right',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-up',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-to-workspace-down',
Lang.bind(this, this._showWorkspaceSwitcher));
Meta.keybindings_set_custom_handler('switch-windows',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-windows-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-group-backward',
Lang.bind(this, this._startAppSwitcher));
Meta.keybindings_set_custom_handler('switch-panels',
Lang.bind(this, this._startA11ySwitcher));
Main.overview.connect('showing', Lang.bind(this, function() {
for (let i = 0; i < this._dimmedWindows.length; i++)
@ -133,16 +145,6 @@ WindowManager.prototype = {
}));
},
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);
},
blockAnimations: function() {
this._animationBlockCount++;
},
@ -152,7 +154,7 @@ WindowManager.prototype = {
},
_shouldAnimate : function(actor) {
if (Main.overview.visible || this._animationsBlocked > 0)
if (Main.overview.visible || this._animationBlockCount > 0)
return false;
if (actor && (actor.meta_window.get_window_type() != Meta.WindowType.NORMAL))
return false;
@ -526,37 +528,41 @@ WindowManager.prototype = {
shellwm.completed_switch_workspace();
},
_startAppSwitcher : function(shellwm, binding, mask, window, backwards) {
_startAppSwitcher : function(display, screen, window, binding) {
/* 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, binding, mask))
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startA11ySwitcher : function(shellwm, binding, mask, window, backwards) {
Main.ctrlAltTabManager.popup(backwards, mask);
_startA11ySwitcher : function(display, screen, window, binding) {
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_mask());
},
_showWorkspaceSwitcher : function(shellwm, binding, mask, window, backwards) {
if (global.screen.n_workspaces == 1)
_showWorkspaceSwitcher : function(display, screen, window, binding) {
if (screen.n_workspaces == 1)
return;
if (this._workspaceSwitcherPopup == null)
this._workspaceSwitcherPopup = new WorkspaceSwitcherPopup.WorkspaceSwitcherPopup();
if (binding == 'switch_to_workspace_up')
if (binding.get_name() == 'switch-to-workspace-up')
this.actionMoveWorkspaceUp();
else if (binding == 'switch_to_workspace_down')
else if (binding.get_name() == 'switch-to-workspace-down')
this.actionMoveWorkspaceDown();
// left/right would effectively act as synonyms for up/down if we enabled them;
// but that could be considered confusing.
// else if (binding == 'switch_to_workspace_left')
// else if (binding.get_name() == 'switch-to-workspace-left')
// this.actionMoveWorkspaceLeft();
// else if (binding == 'switch_to_workspace_right')
// else if (binding.get_name() == 'switch-to-workspace-right')
// this.actionMoveWorkspaceRight();
},
@ -617,4 +623,4 @@ WindowManager.prototype = {
if (!Main.overview.visible)
this._workspaceSwitcherPopup.display(WorkspaceSwitcherPopup.DOWN, indexToActivate);
}
};
});

View File

@ -1,7 +1,7 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GConf = imports.gi.GConf;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@ -28,7 +28,8 @@ const CLOSE_BUTTON_FADE_TIME = 0.1;
const DRAGGING_WINDOW_OPACITY = 100;
const BUTTON_LAYOUT_KEY = '/desktop/gnome/shell/windows/button_layout';
const BUTTON_LAYOUT_SCHEMA = 'org.gnome.shell.overrides';
const BUTTON_LAYOUT_KEY = 'button-layout';
// Define a layout scheme for small window counts. For larger
// counts we fall back to an algorithm. We need more schemes here
@ -55,11 +56,13 @@ function _clamp(value, min, max) {
}
function ScaledPoint(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
}
const ScaledPoint = new Lang.Class({
Name: 'ScaledPoint',
_init: function(x, y, scaleX, scaleY) {
[this.x, this.y, this.scaleX, this.scaleY] = arguments;
},
ScaledPoint.prototype = {
getPosition : function() {
return [this.x, this.y];
},
@ -85,14 +88,12 @@ ScaledPoint.prototype = {
return [_interpolate(this.scaleX, other.scaleX, step),
_interpolate(this.scaleY, other.scaleY, step)];
}
};
});
function WindowClone(realWindow) {
this._init(realWindow);
}
const WindowClone = new Lang.Class({
Name: 'WindowClone',
WindowClone.prototype = {
_init : function(realWindow) {
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
@ -135,8 +136,11 @@ WindowClone.prototype = {
this._realWindowDestroyId = this.realWindow.connect('destroy',
Lang.bind(this, this._disconnectRealWindowSignals));
this.actor.connect('button-release-event',
Lang.bind(this, this._onButtonRelease));
let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', Lang.bind(this, this._onClicked));
clickAction.connect('long-press', Lang.bind(this, this._onLongPress));
this.actor.add_action(clickAction);
this.actor.connect('scroll-event',
Lang.bind(this, this._onScroll));
@ -147,6 +151,7 @@ WindowClone.prototype = {
this._draggable = DND.makeDraggable(this.actor,
{ restoreOnSuccess: true,
manualMode: true,
dragActorMaxSize: WINDOW_DND_SIZE,
dragActorOpacity: DRAGGING_WINDOW_OPACITY });
this._draggable.connect('drag-begin', Lang.bind(this, this._onDragBegin));
@ -345,9 +350,27 @@ WindowClone.prototype = {
this._zoomStep = undefined;
},
_onButtonRelease : function (actor, event) {
_onClicked: function(action, actor) {
this._selected = true;
this.emit('selected', event.get_time());
this.emit('selected', global.get_current_time());
},
_onLongPress: function(action, actor, state) {
// Take advantage of the Clutter policy to consider
// a long-press canceled when the pointer movement
// exceeds dnd-drag-threshold to manually start the drag
if (state == Clutter.LongPressState.CANCEL) {
// A click cancels a long-press before any click handler is
// run - make sure to not start a drag in that case
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() {
if (this._selected)
return;
let [x, y] = action.get_coords();
this._draggable.startDrag(x, y, global.get_current_time());
}));
}
return true;
},
_onDragBegin : function (draggable, time) {
@ -395,7 +418,7 @@ WindowClone.prototype = {
this.emit('drag-end');
}
};
});
Signals.addSignalMethods(WindowClone.prototype);
@ -404,11 +427,9 @@ Signals.addSignalMethods(WindowClone.prototype);
* @parentActor: The actor which will be the parent of all overlay items
* such as app icon and window caption
*/
function WindowOverlay(windowClone, parentActor) {
this._init(windowClone, parentActor);
}
const WindowOverlay = new Lang.Class({
Name: 'WindowOverlay',
WindowOverlay.prototype = {
_init : function(windowClone, parentActor) {
let metaWindow = windowClone.metaWindow;
@ -505,8 +526,8 @@ WindowOverlay.prototype = {
let button = this.closeButton;
let title = this.title;
let gconf = GConf.Client.get_default();
let layout = gconf.get_string(BUTTON_LAYOUT_KEY);
let settings = new Gio.Settings({ schema: BUTTON_LAYOUT_SCHEMA });
let layout = settings.get_string(BUTTON_LAYOUT_KEY);
let rtl = St.Widget.get_default_direction() == St.TextDirection.RTL;
let split = layout.split(":");
@ -619,7 +640,7 @@ WindowOverlay.prototype = {
this._parentActor.queue_relayout();
}
};
});
Signals.addSignalMethods(WindowOverlay.prototype);
const WindowPositionFlags = {
@ -630,11 +651,9 @@ const WindowPositionFlags = {
/**
* @metaWorkspace: a #Meta.Workspace, or null
*/
function Workspace(metaWorkspace, monitorIndex) {
this._init(metaWorkspace, monitorIndex);
}
const Workspace = new Lang.Class({
Name: 'Workspace',
Workspace.prototype = {
_init : function(metaWorkspace, monitorIndex) {
// When dragging a window, we use this slot for reserve space.
this._reservedSlot = null;
@ -1495,6 +1514,6 @@ Workspace.prototype = {
return false;
}
};
});
Signals.addSignalMethods(Workspace.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -15,11 +15,9 @@ const DISPLAY_TIMEOUT = 600;
const UP = -1;
const DOWN = 1;
function WorkspaceSwitcherPopup() {
this._init();
}
const WorkspaceSwitcherPopup = new Lang.Class({
Name: 'WorkspaceSwitcherPopup',
WorkspaceSwitcherPopup.prototype = {
_init : function() {
this.actor = new St.Group({ reactive: true,
x: 0,
@ -158,4 +156,4 @@ WorkspaceSwitcherPopup.prototype = {
onCompleteScope: this
});
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -20,11 +20,14 @@ let MAX_THUMBNAIL_SCALE = 1/8.;
const RESCALE_ANIMATION_TIME = 0.2;
const SLIDE_ANIMATION_TIME = 0.2;
function WindowClone(realWindow) {
this._init(realWindow);
}
// When we create workspaces by dragging, we add a "cut" into the top and
// bottom of each workspace so that the user doesn't have to hit the
// placeholder exactly.
const WORKSPACE_CUT_SIZE = 10;
const WindowClone = new Lang.Class({
Name: 'WindowClone',
WindowClone.prototype = {
_init : function(realWindow) {
this.actor = new Clutter.Clone({ source: realWindow.get_texture(),
reactive: true });
@ -121,7 +124,7 @@ WindowClone.prototype = {
this.emit('drag-end');
}
};
});
Signals.addSignalMethods(WindowClone.prototype);
@ -139,11 +142,9 @@ const ThumbnailState = {
/**
* @metaWorkspace: a #Meta.Workspace
*/
function WorkspaceThumbnail(metaWorkspace) {
this._init(metaWorkspace);
}
const WorkspaceThumbnail = new Lang.Class({
Name: 'WorkspaceThumbnail',
WorkspaceThumbnail.prototype = {
_init : function(metaWorkspace) {
this.metaWorkspace = metaWorkspace;
this.monitorIndex = Main.layoutManager.primaryIndex;
@ -422,6 +423,11 @@ WorkspaceThumbnail.prototype = {
if (this.state > ThumbnailState.NORMAL)
return DND.DragMotionResult.CONTINUE;
let [w, h] = this.actor.get_transformed_size();
// Bubble up if we're in the "workspace cut".
if (y < WORKSPACE_CUT_SIZE || y > h - WORKSPACE_CUT_SIZE)
return DND.DragMotionResult.CONTINUE;
if (source.realWindow && !this._isMyWindow(source.realWindow))
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
@ -459,22 +465,21 @@ WorkspaceThumbnail.prototype = {
return false;
}
};
});
Signals.addSignalMethods(WorkspaceThumbnail.prototype);
function ThumbnailsBox() {
this._init();
}
const ThumbnailsBox = new Lang.Class({
Name: 'ThumbnailsBox',
ThumbnailsBox.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer({ style_class: 'workspace-thumbnails',
request_mode: Clutter.RequestMode.WIDTH_FOR_HEIGHT });
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.actor._delegate = this;
// When we animate the scale, we don't animate the requested size of the thumbnails, rather
// we ask for our final size and then animate within that size. This slightly simplifies the
@ -498,6 +503,10 @@ ThumbnailsBox.prototype = {
this._indicator = indicator;
this.actor.add_actor(indicator);
this._dropPlaceholderPos = -1;
this._dropPlaceholder = new St.Bin({ style_class: 'placeholder' });
this.actor.add_actor(this._dropPlaceholder);
this._targetScale = 0;
this._scale = 0;
this._pendingScaleUpdate = false;
@ -512,6 +521,83 @@ ThumbnailsBox.prototype = {
this._thumbnails = [];
},
// Draggable target interface
handleDragOver : function(source, actor, x, y, time) {
if (!source.realWindow && !source.shellWorkspaceLaunch)
return DND.DragMotionResult.CONTINUE;
let spacing = this.actor.get_theme_node().get_length('spacing');
let thumbHeight = this._porthole.height * this._scale;
let workspace = -1;
let firstThumbY = this._thumbnails[0].actor.y;
for (let i = 0; i < this._thumbnails.length; i ++) {
let targetBase = firstThumbY + (thumbHeight + spacing) * i;
// Allow the reorder target to have a 10px "cut" into
// each side of the thumbnail, to make dragging onto the
// placeholder easier
let targetTop = targetBase - spacing - WORKSPACE_CUT_SIZE;
let targetBottom = targetBase + WORKSPACE_CUT_SIZE;
// Expand the target to include the placeholder, if it exists.
if (i == this._dropPlaceholderPos)
targetBottom += this._dropPlaceholder.get_height();
if (y > targetTop && y <= targetBottom) {
workspace = i;
break;
}
}
this._dropPlaceholderPos = workspace;
this.actor.queue_relayout();
if (workspace == -1)
return DND.DragMotionResult.CONTINUE;
return DND.DragMotionResult.MOVE_DROP;
},
acceptDrop: function(source, actor, x, y, time) {
if (this._dropPlaceholderPos == -1)
return false;
if (!source.realWindow && !source.shellWorkspaceLaunch)
return false;
let isWindow = !!source.realWindow;
// To create a new workspace, we first slide all the windows on workspaces
// below us to the next workspace, leaving a blank workspace for us to recycle.
let newWorkspaceIndex;
[newWorkspaceIndex, this._dropPlaceholderPos] = [this._dropPlaceholderPos, -1];
// Nab all the windows below us.
let windows = global.get_window_actors().filter(function(win) {
if (isWindow)
return win.get_workspace() >= newWorkspaceIndex && win != source;
else
return win.get_workspace() >= newWorkspaceIndex;
});
// ... move them down one.
windows.forEach(function(win) {
win.meta_window.change_workspace_by_index(win.get_workspace() + 1,
true, time);
});
if (isWindow)
// ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
true, time);
else if (source.shellWorkspaceLaunch)
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time });
return true;
},
show: function() {
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
@ -840,20 +926,18 @@ ThumbnailsBox.prototype = {
let y = contentBox.y1;
if (this._dropPlaceholderPos == -1) {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropPlaceholder.hide();
}));
}
for (let i = 0; i < this._thumbnails.length; i++) {
let thumbnail = this._thumbnails[i];
if (i > 0)
y += spacing - Math.round(thumbnail.collapseFraction * spacing);
// We might end up with thumbnailHeight being something like 99.33
// pixels. To make this work and not end up with a gap at the bottom,
// we need some thumbnails to be 99 pixels and some 100 pixels height;
// we compute an actual scale separately for each thumbnail.
let y1 = Math.round(y);
let y2 = Math.round(y + thumbnailHeight);
let roundedVScale = (y2 - y1) / portholeHeight;
let x1, x2;
if (rtl) {
x1 = contentBox.x1 + slideOffset * thumbnail.slidePosition;
@ -863,6 +947,27 @@ ThumbnailsBox.prototype = {
x2 = x1 + thumbnailWidth;
}
if (i == this._dropPlaceholderPos) {
let [minHeight, placeholderHeight] = this._dropPlaceholder.get_preferred_height(-1);
childBox.x1 = x1;
childBox.x2 = x1 + thumbnailWidth;
childBox.y1 = Math.round(y);
childBox.y2 = Math.round(y + placeholderHeight);
this._dropPlaceholder.allocate(childBox, flags);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
this._dropPlaceholder.show();
}));
y += placeholderHeight + spacing;
}
// We might end up with thumbnailHeight being something like 99.33
// pixels. To make this work and not end up with a gap at the bottom,
// we need some thumbnails to be 99 pixels and some 100 pixels height;
// we compute an actual scale separately for each thumbnail.
let y1 = Math.round(y);
let y2 = Math.round(y + thumbnailHeight);
let roundedVScale = (y2 - y1) / portholeHeight;
if (thumbnail.metaWorkspace == indicatorWorkspace)
indicatorY = y1;
@ -917,4 +1022,4 @@ ThumbnailsBox.prototype = {
onCompleteScope: this
});
}
};
});

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -23,11 +23,9 @@ const MAX_WORKSPACES = 16;
const CONTROLS_POP_IN_TIME = 0.1;
function WorkspacesView(workspaces) {
this._init(workspaces);
}
const WorkspacesView = new Lang.Class({
Name: 'WorkspacesView',
WorkspacesView.prototype = {
_init: function(workspaces) {
this.actor = new St.Group({ style_class: 'workspaces-view' });
@ -109,8 +107,6 @@ WorkspacesView.prototype = {
this._scrollAdjustment.connect('notify::value',
Lang.bind(this, this._onScroll));
this._timeoutId = 0;
this._switchWorkspaceNotifyId =
global.window_manager.connect('switch-workspace',
Lang.bind(this, this._activeWorkspaceChanged));
@ -321,10 +317,6 @@ WorkspacesView.prototype = {
if (this._inDrag)
this._dragEnd();
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
if (this._itemDragBeginId > 0) {
Main.overview.disconnect(this._itemDragBeginId);
this._itemDragBeginId = 0;
@ -383,72 +375,10 @@ WorkspacesView.prototype = {
this._extraWorkspaces[i].setReservedSlot(dragEvent.dragActor._delegate);
}
let primary = Main.layoutManager.primaryMonitor;
let activeWorkspaceIndex = global.screen.get_active_workspace_index();
let topWorkspace, bottomWorkspace;
topWorkspace = this._workspaces[activeWorkspaceIndex - 1];
bottomWorkspace = this._workspaces[activeWorkspaceIndex + 1];
let hoverWorkspace = null;
// reactive monitor edges
let topEdge = primary.y;
let switchTop = (dragEvent.y <= topEdge && topWorkspace);
if (switchTop && this._dragOverLastY != topEdge) {
topWorkspace.metaWorkspace.activate(global.get_current_time());
this._dragOverLastY = topEdge;
return DND.DragMotionResult.CONTINUE;
}
let bottomEdge = primary.y + primary.height - 1;
let switchBottom = (dragEvent.y >= bottomEdge && bottomWorkspace);
if (switchBottom && this._dragOverLastY != bottomEdge) {
bottomWorkspace.metaWorkspace.activate(global.get_current_time());
this._dragOverLastY = bottomEdge;
return DND.DragMotionResult.CONTINUE;
}
this._dragOverLastY = dragEvent.y;
let result = DND.DragMotionResult.CONTINUE;
// check hover state of new workspace area / inactive workspaces
if (topWorkspace) {
if (topWorkspace.actor.contains(dragEvent.targetActor)) {
hoverWorkspace = topWorkspace;
result = topWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
}
}
if (bottomWorkspace) {
if (bottomWorkspace.actor.contains(dragEvent.targetActor)) {
hoverWorkspace = bottomWorkspace;
result = bottomWorkspace.handleDragOver(dragEvent.source, dragEvent.dragActor);
}
}
// handle delayed workspace switches
if (hoverWorkspace) {
if (!this._timeoutId)
this._timeoutId = Mainloop.timeout_add_seconds(1,
Lang.bind(this, function() {
hoverWorkspace.metaWorkspace.activate(global.get_current_time());
return false;
}));
} else {
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
}
return result;
return DND.DragMotionResult.CONTINUE;
},
_dragEnd: function() {
if (this._timeoutId) {
Mainloop.source_remove(this._timeoutId);
this._timeoutId = 0;
}
DND.removeDragMonitor(this._dragMonitor);
this._inDrag = false;
@ -520,15 +450,13 @@ WorkspacesView.prototype = {
_getWorkspaceIndexToRemove: function() {
return global.screen.get_active_workspace_index();
}
};
});
Signals.addSignalMethods(WorkspacesView.prototype);
function WorkspacesDisplay() {
this._init();
}
const WorkspacesDisplay = new Lang.Class({
Name: 'WorkspacesDisplay',
WorkspacesDisplay.prototype = {
_init: function() {
this.actor = new Shell.GenericContainer();
this.actor.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
@ -920,5 +848,5 @@ WorkspacesDisplay.prototype = {
break;
}
}
};
});
Signals.addSignalMethods(WorkspacesDisplay.prototype);

View File

@ -1,4 +1,4 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
@ -6,11 +6,9 @@ const Shell = imports.gi.Shell;
const Signals = imports.signals;
const DND = imports.ui.dnd;
function XdndHandler() {
this._init();
}
const XdndHandler = new Lang.Class({
Name: 'XdndHandler',
XdndHandler.prototype = {
_init: function() {
// Used to display a clone of the cursor window when the
// window group is hidden (like it happens in the overview)
@ -125,6 +123,6 @@ XdndHandler.prototype = {
pickedActor = pickedActor.get_parent();
}
}
}
});
Signals.addSignalMethods(XdndHandler.prototype);

View File

@ -2,6 +2,7 @@ af
an
ar
as
ast
be
bg
bn
@ -31,6 +32,7 @@ it
ja
ko
kn
ku
lt
lv
mr

View File

@ -25,6 +25,7 @@ js/ui/polkitAuthenticationAgent.js
js/ui/popupMenu.js
js/ui/runDialog.js
js/ui/searchDisplay.js
js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
js/ui/status/bluetooth.js
@ -44,4 +45,3 @@ src/shell-global.c
src/shell-mobile-providers.c
src/shell-polkit-authentication-agent.c
src/shell-util.c

1630
po/ast.po Normal file

File diff suppressed because it is too large Load Diff

335
po/bg.po
View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-25 08:34+0300\n"
"PO-Revision-Date: 2011-09-25 08:34+0300\n"
"POT-Creation-Date: 2011-10-21 23:34+0300\n"
"PO-Revision-Date: 2011-10-21 23:34+0300\n"
"Last-Translator: Ivaylo Valkov <ivaylo@e-valkov.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@ -184,52 +184,50 @@ msgstr "Коя клавиатура да бъде да се ползва"
msgid "disabled OpenSearch providers"
msgstr "изключени доставчици на OpenSearch"
#: ../js/gdm/loginDialog.js:617
#: ../js/gdm/loginDialog.js:633
msgid "Session..."
msgstr "Сесия…"
#: ../js/gdm/loginDialog.js:785
#: ../js/gdm/loginDialog.js:804
msgctxt "title"
msgid "Sign In"
msgstr "Регистриране"
#. translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead
#: ../js/gdm/loginDialog.js:830
#: ../js/gdm/loginDialog.js:849
msgid "(or swipe finger)"
msgstr "(или се регистрирайте с пръстов отпечатък)"
#: ../js/gdm/loginDialog.js:848
#: ../js/gdm/loginDialog.js:867
msgid "Not listed?"
msgstr "Липсва в списъка?"
#: ../js/gdm/loginDialog.js:1004 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:477 ../js/ui/networkAgent.js:165
#: ../js/ui/polkitAuthenticationAgent.js:171 ../js/ui/status/bluetooth.js:480
#: ../js/gdm/loginDialog.js:1035 ../js/ui/endSessionDialog.js:426
#: ../js/ui/extensionSystem.js:520 ../js/ui/networkAgent.js:148
#: ../js/ui/polkitAuthenticationAgent.js:173 ../js/ui/status/bluetooth.js:480
msgid "Cancel"
msgstr "Отказване"
#: ../js/gdm/loginDialog.js:1009
#: ../js/gdm/loginDialog.js:1040
msgctxt "button"
msgid "Sign In"
msgstr "Регистриране"
#: ../js/gdm/loginDialog.js:1358
#: ../js/gdm/loginDialog.js:1392
msgid "Login Window"
msgstr "Екран за идентификация"
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:514
#: ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:585
#: ../js/gdm/powerMenu.js:116 ../js/ui/userMenu.js:569
#: ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:640
msgid "Suspend"
msgstr "Приспиване"
#: ../js/gdm/powerMenu.js:121 ../js/ui/endSessionDialog.js:89
#: ../js/ui/endSessionDialog.js:97 ../js/ui/endSessionDialog.js:106
#: ../js/gdm/powerMenu.js:121
msgid "Restart"
msgstr "Рестартиране"
#: ../js/gdm/powerMenu.js:126 ../js/ui/endSessionDialog.js:80
#: ../js/ui/endSessionDialog.js:91
#: ../js/gdm/powerMenu.js:126
msgid "Power Off"
msgstr "Изключване"
@ -442,32 +440,32 @@ msgstr "Тази седмица"
msgid "Next week"
msgstr "Следващата седмица"
#: ../js/ui/contactDisplay.js:59 ../js/ui/notificationDaemon.js:444
#: ../js/ui/status/power.js:223 ../src/shell-app.c:355
#: ../js/ui/contactDisplay.js:65 ../js/ui/notificationDaemon.js:459
#: ../js/ui/status/power.js:223 ../src/shell-app.c:353
msgid "Unknown"
msgstr "Неизвестно"
#: ../js/ui/contactDisplay.js:80 ../js/ui/userMenu.js:139
#: ../js/ui/contactDisplay.js:86 ../js/ui/userMenu.js:139
msgid "Available"
msgstr "На линия"
#: ../js/ui/contactDisplay.js:85 ../js/ui/userMenu.js:148
#: ../js/ui/contactDisplay.js:91 ../js/ui/userMenu.js:148
msgid "Away"
msgstr "Отсъстващ"
#: ../js/ui/contactDisplay.js:89 ../js/ui/userMenu.js:142
#: ../js/ui/contactDisplay.js:95 ../js/ui/userMenu.js:142
msgid "Busy"
msgstr "Зает"
#: ../js/ui/contactDisplay.js:93
#: ../js/ui/contactDisplay.js:99
msgid "Offline"
msgstr "Извън мрежата"
#: ../js/ui/contactDisplay.js:140
#: ../js/ui/contactDisplay.js:146
msgid "CONTACTS"
msgstr "КОНТАКТИ"
#: ../js/ui/dash.js:172 ../js/ui/messageTray.js:1204
#: ../js/ui/dash.js:174 ../js/ui/messageTray.js:1206
msgid "Remove"
msgstr "Изтриване"
@ -532,10 +530,12 @@ msgstr "СКОРО ОТВАРЯНИ"
#: ../js/ui/endSessionDialog.js:60
#, c-format
msgctxt "title"
msgid "Log Out %s"
msgstr "Изход на „%s“"
#: ../js/ui/endSessionDialog.js:61 ../js/ui/endSessionDialog.js:75
#: ../js/ui/endSessionDialog.js:61
msgctxt "title"
msgid "Log Out"
msgstr "Изход"
@ -564,6 +564,16 @@ msgstr[1] "Ще излезете от системата автоматично
msgid "Logging out of the system."
msgstr "Излизане от системата."
#: ../js/ui/endSessionDialog.js:75
msgctxt "button"
msgid "Log Out"
msgstr "Изход"
#: ../js/ui/endSessionDialog.js:80
msgctxt "title"
msgid "Power Off"
msgstr "Изключване"
#: ../js/ui/endSessionDialog.js:81
msgid "Click Power Off to quit these applications and power off the system."
msgstr ""
@ -581,6 +591,21 @@ msgstr[1] "Системата ще се изключи автоматично с
msgid "Powering off the system."
msgstr "Изключване на системата."
#: ../js/ui/endSessionDialog.js:89 ../js/ui/endSessionDialog.js:106
msgctxt "button"
msgid "Restart"
msgstr "Рестартиране"
#: ../js/ui/endSessionDialog.js:91
msgctxt "button"
msgid "Power Off"
msgstr "Изключване"
#: ../js/ui/endSessionDialog.js:97
msgctxt "title"
msgid "Restart"
msgstr "Рестартиране"
#: ../js/ui/endSessionDialog.js:98
msgid "Click Restart to quit these applications and restart the system."
msgstr ""
@ -598,105 +623,119 @@ msgstr[1] "Системата ще се рестартира автоматич
msgid "Restarting the system."
msgstr "Рестартиране на системата."
#: ../js/ui/extensionSystem.js:481
#: ../js/ui/extensionSystem.js:524
msgid "Install"
msgstr "Инсталиране"
#: ../js/ui/extensionSystem.js:485
#: ../js/ui/extensionSystem.js:528
#, c-format
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Да се изтегли и инсталира ли „%s“ от from extensions.gnome.org?"
#: ../js/ui/keyboard.js:517 ../js/ui/status/power.js:211
#: ../js/ui/keyboard.js:325
msgid "tray"
msgstr "област за уведомяване"
#: ../js/ui/keyboard.js:547 ../js/ui/status/power.js:211
msgid "Keyboard"
msgstr "Клавиатура"
#: ../js/ui/lookingGlass.js:645
#: ../js/ui/lookingGlass.js:664
msgid "No extensions installed"
msgstr "Няма инсталирани разширения"
#: ../js/ui/lookingGlass.js:691
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:719
#, c-format
msgid "%s has not emitted any errors."
msgstr "Разширението %s не е обозначило никави грешки."
#: ../js/ui/lookingGlass.js:725
msgid "Hide Errors"
msgstr "Скриване на грешките"
#: ../js/ui/lookingGlass.js:729 ../js/ui/lookingGlass.js:779
msgid "Show Errors"
msgstr "Показване на грешките"
#: ../js/ui/lookingGlass.js:738
msgid "Enabled"
msgstr "Включено"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:693 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:740 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Изключено"
#: ../js/ui/lookingGlass.js:695
#: ../js/ui/lookingGlass.js:742
msgid "Error"
msgstr "Грешка"
#: ../js/ui/lookingGlass.js:697
#: ../js/ui/lookingGlass.js:744
msgid "Out of date"
msgstr "Остаряло"
#: ../js/ui/lookingGlass.js:699
#: ../js/ui/lookingGlass.js:746
msgid "Downloading"
msgstr "Изтегляне"
#: ../js/ui/lookingGlass.js:724
#: ../js/ui/lookingGlass.js:767
msgid "View Source"
msgstr "Преглед на изходния код"
#: ../js/ui/lookingGlass.js:730
#: ../js/ui/lookingGlass.js:773
msgid "Web Page"
msgstr "Домашна страница"
#: ../js/ui/messageTray.js:1197
#: ../js/ui/messageTray.js:1199
msgid "Open"
msgstr "Отваряне"
#: ../js/ui/messageTray.js:2405
#: ../js/ui/messageTray.js:2408
msgid "System Information"
msgstr "Информация за системата"
#: ../js/ui/networkAgent.js:145
msgid "Show password"
msgstr "Показване на парола"
#: ../js/ui/networkAgent.js:160
#: ../js/ui/networkAgent.js:143
msgid "Connect"
msgstr "Свързване"
#. Cisco LEAP
#: ../js/ui/networkAgent.js:255 ../js/ui/networkAgent.js:267
#: ../js/ui/networkAgent.js:294 ../js/ui/networkAgent.js:314
#: ../js/ui/networkAgent.js:324
#: ../js/ui/networkAgent.js:238 ../js/ui/networkAgent.js:250
#: ../js/ui/networkAgent.js:277 ../js/ui/networkAgent.js:297
#: ../js/ui/networkAgent.js:307
msgid "Password: "
msgstr "Парола: "
#. static WEP
#: ../js/ui/networkAgent.js:260
#: ../js/ui/networkAgent.js:243
msgid "Key: "
msgstr "Ключ: "
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: ../js/ui/networkAgent.js:292 ../js/ui/networkAgent.js:310
#: ../js/ui/networkAgent.js:275 ../js/ui/networkAgent.js:293
msgid "Username: "
msgstr "Потребител: "
#: ../js/ui/networkAgent.js:298
#: ../js/ui/networkAgent.js:281
msgid "Identity: "
msgstr "Самоличност: "
#: ../js/ui/networkAgent.js:300
#: ../js/ui/networkAgent.js:283
msgid "Private key password: "
msgstr "Парола за частният ключ: "
#: ../js/ui/networkAgent.js:312
#: ../js/ui/networkAgent.js:295
msgid "Service: "
msgstr "Услуга: "
#: ../js/ui/networkAgent.js:341
#: ../js/ui/networkAgent.js:324
msgid "Authentication required by wireless network"
msgstr "Изисква се удостоверяване за безжична мрежа"
#: ../js/ui/networkAgent.js:342
#: ../js/ui/networkAgent.js:325
#, c-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -705,35 +744,35 @@ msgstr ""
"За достъп до безжичната мрежа „%s“ са необходими пароли или криптирани "
"ключове."
#: ../js/ui/networkAgent.js:346
#: ../js/ui/networkAgent.js:329
msgid "Wired 802.1X authentication"
msgstr "Жична идентификация 802.1Х"
#: ../js/ui/networkAgent.js:348
#: ../js/ui/networkAgent.js:331
msgid "Network name: "
msgstr "Име на мрежата: "
#: ../js/ui/networkAgent.js:353
#: ../js/ui/networkAgent.js:336
msgid "DSL authentication"
msgstr "Удостоверяване за DSL"
#: ../js/ui/networkAgent.js:360
#: ../js/ui/networkAgent.js:343
msgid "PIN code required"
msgstr "Необходим е PIN"
#: ../js/ui/networkAgent.js:361
#: ../js/ui/networkAgent.js:344
msgid "PIN code is needed for the mobile broadband device"
msgstr "Мобилното устройство изисква ПИН"
#: ../js/ui/networkAgent.js:362
#: ../js/ui/networkAgent.js:345
msgid "PIN: "
msgstr "ПИН: "
#: ../js/ui/networkAgent.js:368
#: ../js/ui/networkAgent.js:351
msgid "Mobile broadband network password"
msgstr "Парола за мобилна широколентова връзка"
#: ../js/ui/networkAgent.js:369
#: ../js/ui/networkAgent.js:352
#, c-format
msgid "A password is required to connect to '%s'."
msgstr "За свързване към „%s“ се изисква парола."
@ -789,15 +828,15 @@ msgstr "Свързване към…"
msgid "PLACES & DEVICES"
msgstr "МЕСТА И УСТРОЙСТВА"
#: ../js/ui/polkitAuthenticationAgent.js:72
#: ../js/ui/polkitAuthenticationAgent.js:73
msgid "Authentication Required"
msgstr "Необходимо е удостоверяване"
#: ../js/ui/polkitAuthenticationAgent.js:106
#: ../js/ui/polkitAuthenticationAgent.js:107
msgid "Administrator"
msgstr "Администратор"
#: ../js/ui/polkitAuthenticationAgent.js:175
#: ../js/ui/polkitAuthenticationAgent.js:177
msgid "Authenticate"
msgstr "Удостоверяване"
@ -805,11 +844,11 @@ msgstr "Удостоверяване"
#. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password),
#. * for instance.
#: ../js/ui/polkitAuthenticationAgent.js:256
#: ../js/ui/polkitAuthenticationAgent.js:258
msgid "Sorry, that didn't work. Please try again."
msgstr "Действието не беше успешно. Опитайте отново."
#: ../js/ui/polkitAuthenticationAgent.js:268
#: ../js/ui/polkitAuthenticationAgent.js:270
msgid "Password:"
msgstr "Парола:"
@ -822,7 +861,7 @@ msgstr "Парола:"
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:208
#: ../js/ui/runDialog.js:209
msgid "Please enter a command:"
msgstr "Въведете команда:"
@ -834,6 +873,22 @@ msgstr "Търсене…"
msgid "No matching results."
msgstr "Няма съвпадения."
#: ../js/ui/shellEntry.js:30
msgid "Copy"
msgstr "Копиране"
#: ../js/ui/shellEntry.js:35
msgid "Paste"
msgstr "Поставяне"
#: ../js/ui/shellEntry.js:81
msgid "Show Text"
msgstr "Показване на текста"
#: ../js/ui/shellEntry.js:83
msgid "Hide Text"
msgstr "Скриване на текста"
#: ../js/ui/shellMountOperation.js:285
msgid "Wrong password, please try again"
msgstr "Грешна парола. Опитайте отново."
@ -967,7 +1022,7 @@ msgstr "Винаги позволяване на достъп"
msgid "Grant this time only"
msgstr "Позволяване само този път"
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1196
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1204
msgid "Reject"
msgstr "Отхвърляне"
@ -1236,39 +1291,39 @@ msgid "Invitation"
msgstr "Покана"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:325
#: ../js/ui/telepathyClient.js:327
msgid "Call"
msgstr "Разговор"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:353
#: ../js/ui/telepathyClient.js:357
msgid "File Transfer"
msgstr "Обмен на файлове"
#: ../js/ui/telepathyClient.js:434
#: ../js/ui/telepathyClient.js:438
msgid "Subscription request"
msgstr "Искане за записване"
#: ../js/ui/telepathyClient.js:470
#: ../js/ui/telepathyClient.js:474
msgid "Connection error"
msgstr "Грешка при свързване"
#: ../js/ui/telepathyClient.js:733
#: ../js/ui/telepathyClient.js:741
#, c-format
msgid "%s is online."
msgstr "%s е на линия."
#: ../js/ui/telepathyClient.js:738
#: ../js/ui/telepathyClient.js:746
#, c-format
msgid "%s is offline."
msgstr "%s не е на линия."
#: ../js/ui/telepathyClient.js:741
#: ../js/ui/telepathyClient.js:749
#, c-format
msgid "%s is away."
msgstr "%s отсъства."
#: ../js/ui/telepathyClient.js:744
#: ../js/ui/telepathyClient.js:752
#, c-format
msgid "%s is busy."
msgstr "%s е зает."
@ -1276,35 +1331,35 @@ msgstr "%s е зает."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:978
#: ../js/ui/telepathyClient.js:986
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Изпратено в <b>%X</b> на <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:984
#: ../js/ui/telepathyClient.js:992
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Изпратено на <b>%3$d %2$B</b>, <b>%1$A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:989
#: ../js/ui/telepathyClient.js:997
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Изпратено на <b>%3$d %2$B %4$Y</b>, <b>%1$A</b>"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:1031
#: ../js/ui/telepathyClient.js:1039
#, c-format
msgid "%s is now known as %s"
msgstr "%s в момента е познат като %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1140
#: ../js/ui/telepathyClient.js:1148
#, c-format
msgid "Invitation to %s"
msgstr "Покана за присъединяване към %s"
@ -1312,34 +1367,35 @@ msgstr "Покана за присъединяване към %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1148
#: ../js/ui/telepathyClient.js:1156
#, c-format
msgid "%s is inviting you to join %s"
msgstr "%s ви кани да се присъедините към %s"
#: ../js/ui/telepathyClient.js:1150 ../js/ui/telepathyClient.js:1239
#: ../js/ui/telepathyClient.js:1343
#: ../js/ui/telepathyClient.js:1158 ../js/ui/telepathyClient.js:1248
#: ../js/ui/telepathyClient.js:1352
msgid "Decline"
msgstr "Отклоняване"
#: ../js/ui/telepathyClient.js:1151 ../js/ui/telepathyClient.js:1240
#: ../js/ui/telepathyClient.js:1344
#: ../js/ui/telepathyClient.js:1159 ../js/ui/telepathyClient.js:1249
#: ../js/ui/telepathyClient.js:1353
msgid "Accept"
msgstr "Приемане"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1184
#: ../js/ui/telepathyClient.js:1192
#, c-format
msgid "Video call from %s"
msgstr "Видео разговор от %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1187
#: ../js/ui/telepathyClient.js:1195
#, c-format
msgid "Call from %s"
msgstr "Повикване от %s"
#: ../js/ui/telepathyClient.js:1197
#. translators: this is a button label (verb), not a noun
#: ../js/ui/telepathyClient.js:1206
msgid "Answer"
msgstr "Отговор"
@ -1348,109 +1404,109 @@ msgstr "Отговор"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1233
#: ../js/ui/telepathyClient.js:1242
#, c-format
msgid "%s is sending you %s"
msgstr "%s ви праща „%s“"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1308
#: ../js/ui/telepathyClient.js:1317
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s иска разрешение да вижда дали сте в мрежата"
#: ../js/ui/telepathyClient.js:1406
#: ../js/ui/telepathyClient.js:1415
msgid "Network error"
msgstr "Мрежова грешка"
#: ../js/ui/telepathyClient.js:1408
#: ../js/ui/telepathyClient.js:1417
msgid "Authentication failed"
msgstr "Неуспешно идентифициране"
#: ../js/ui/telepathyClient.js:1410
#: ../js/ui/telepathyClient.js:1419
msgid "Encryption error"
msgstr "Грешка в шифрирането"
#: ../js/ui/telepathyClient.js:1412
#: ../js/ui/telepathyClient.js:1421
msgid "Certificate not provided"
msgstr "Не е предоставен сертификат"
#: ../js/ui/telepathyClient.js:1414
#: ../js/ui/telepathyClient.js:1423
msgid "Certificate untrusted"
msgstr "Сертификатът не е доверен"
#: ../js/ui/telepathyClient.js:1416
#: ../js/ui/telepathyClient.js:1425
msgid "Certificate expired"
msgstr "Сертификатът е изтекъл"
#: ../js/ui/telepathyClient.js:1418
#: ../js/ui/telepathyClient.js:1427
msgid "Certificate not activated"
msgstr "Сертификатът не е влязъл в сила"
#: ../js/ui/telepathyClient.js:1420
#: ../js/ui/telepathyClient.js:1429
msgid "Certificate hostname mismatch"
msgstr "Несъвпадане на името с това в сертификата"
#: ../js/ui/telepathyClient.js:1422
#: ../js/ui/telepathyClient.js:1431
msgid "Certificate fingerprint mismatch"
msgstr "Несъвпадане на отпечатъка на сертификата"
#: ../js/ui/telepathyClient.js:1424
#: ../js/ui/telepathyClient.js:1433
msgid "Certificate self-signed"
msgstr "Сертификатът е самоподписан"
#: ../js/ui/telepathyClient.js:1426
#: ../js/ui/telepathyClient.js:1435
msgid "Status is set to offline"
msgstr "Състоянието е „Извън мрежата“."
#: ../js/ui/telepathyClient.js:1428
#: ../js/ui/telepathyClient.js:1437
msgid "Encryption is not available"
msgstr "Не е налично шифриране"
#: ../js/ui/telepathyClient.js:1430
#: ../js/ui/telepathyClient.js:1439
msgid "Certificate is invalid"
msgstr "Сертификатът е неправилен"
#: ../js/ui/telepathyClient.js:1432
#: ../js/ui/telepathyClient.js:1441
msgid "Connection has been refused"
msgstr "Връзката е отказана"
#: ../js/ui/telepathyClient.js:1434
#: ../js/ui/telepathyClient.js:1443
msgid "Connection can't be established"
msgstr "Не може да се установи връзка"
#: ../js/ui/telepathyClient.js:1436
#: ../js/ui/telepathyClient.js:1445
msgid "Connection has been lost"
msgstr "Връзката прекъсна"
#: ../js/ui/telepathyClient.js:1438
#: ../js/ui/telepathyClient.js:1447
msgid "This resource is already connected to the server"
msgstr "Ресурсът вече е свързан към сървъра"
#: ../js/ui/telepathyClient.js:1440
#: ../js/ui/telepathyClient.js:1449
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr "Връзката бе заместена от нова връзка, използваща същия ресурс"
#: ../js/ui/telepathyClient.js:1442
#: ../js/ui/telepathyClient.js:1451
msgid "The account already exists on the server"
msgstr "На сървъра вече има регистрация с такова име."
#: ../js/ui/telepathyClient.js:1444
#: ../js/ui/telepathyClient.js:1453
msgid "Server is currently too busy to handle the connection"
msgstr ""
"В момента сървърът е твърде натоварен, за да обработи заявката за свързване"
#: ../js/ui/telepathyClient.js:1446
#: ../js/ui/telepathyClient.js:1455
msgid "Certificate has been revoked"
msgstr "Сертификатът е анулиран"
#: ../js/ui/telepathyClient.js:1448
#: ../js/ui/telepathyClient.js:1457
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr "Сертификатът използва несигурен шифър или слаб алгоритъм за шифриране"
#: ../js/ui/telepathyClient.js:1450
#: ../js/ui/telepathyClient.js:1459
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1460,20 +1516,20 @@ msgstr ""
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1459
#: ../js/ui/telepathyClient.js:1468
#, c-format
msgid "Connection to %s failed"
msgstr "Връзката е към „%s“ е неуспешна"
#: ../js/ui/telepathyClient.js:1468
#: ../js/ui/telepathyClient.js:1477
msgid "Reconnect"
msgstr "Ново свързване"
#: ../js/ui/telepathyClient.js:1469
#: ../js/ui/telepathyClient.js:1478
msgid "Edit account"
msgstr "Редактиране на регистрацията"
#: ../js/ui/telepathyClient.js:1515
#: ../js/ui/telepathyClient.js:1524
msgid "Unknown reason"
msgstr "Неизвестна причина"
@ -1489,39 +1545,39 @@ msgstr "Бездействие"
msgid "Unavailable"
msgstr "Недостъпно"
#: ../js/ui/userMenu.js:512 ../js/ui/userMenu.js:516 ../js/ui/userMenu.js:586
#: ../js/ui/userMenu.js:567 ../js/ui/userMenu.js:571 ../js/ui/userMenu.js:641
msgid "Power Off..."
msgstr "Изключване..."
#: ../js/ui/userMenu.js:548
#: ../js/ui/userMenu.js:603
msgid "Notifications"
msgstr "Известяване"
#: ../js/ui/userMenu.js:556
#: ../js/ui/userMenu.js:611
msgid "Online Accounts"
msgstr "Мрежови регистрации"
#: ../js/ui/userMenu.js:560
#: ../js/ui/userMenu.js:615
msgid "System Settings"
msgstr "Настройки на системата"
#: ../js/ui/userMenu.js:567
#: ../js/ui/userMenu.js:622
msgid "Lock Screen"
msgstr "Заключване на екрана"
#: ../js/ui/userMenu.js:572
#: ../js/ui/userMenu.js:627
msgid "Switch User"
msgstr "Смяна на потребител"
#: ../js/ui/userMenu.js:577
#: ../js/ui/userMenu.js:632
msgid "Log Out..."
msgstr "Изход…"
#: ../js/ui/userMenu.js:605
#: ../js/ui/userMenu.js:660
msgid "Your chat status will be set to busy"
msgstr "Състоянието ви ще се зададе да е „Зает“"
#: ../js/ui/userMenu.js:606
#: ../js/ui/userMenu.js:661
msgid ""
"Notifications are now disabled, including chat messages. Your online status "
"has been adjusted to let others know that you might not see their messages."
@ -1534,20 +1590,15 @@ msgstr ""
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: ../js/ui/viewSelector.js:120
#: ../js/ui/viewSelector.js:121
msgid "Type to search..."
msgstr "Търсене на написаното…"
#: ../js/ui/viewSelector.js:140 ../src/shell-util.c:261
#: ../js/ui/viewSelector.js:142 ../src/shell-util.c:244
msgid "Search"
msgstr "Търсене"
#: ../js/ui/windowAttentionHandler.js:39
#, c-format
msgid "%s has finished starting"
msgstr "Програмата „%s“ стартира успешно"
#: ../js/ui/windowAttentionHandler.js:41
#: ../js/ui/windowAttentionHandler.js:35
#, c-format
msgid "'%s' is ready"
msgstr "Програмата „%s“ е готова за употреба"
@ -1582,7 +1633,7 @@ msgstr "Показване на версията"
msgid "Mode used by GDM for login screen"
msgstr "Режим използван от GDM за екрана за влизане"
#: ../src/shell-app.c:581
#: ../src/shell-app.c:579
#, c-format
msgid "Failed to launch '%s'"
msgstr "Неуспех при стартиране на „%s“"
@ -1599,13 +1650,15 @@ msgstr "Стандартно"
msgid "Authentication dialog was dismissed by the user"
msgstr "Прозорецът за упълномощаване беше затворен от потребителя"
#: ../src/shell-util.c:100
msgid "Home Folder"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:89
msgid "Home"
msgstr "Домашна папка"
#. Translators: this is the same string as the one found in
#. * nautilus
#: ../src/shell-util.c:115
#: ../src/shell-util.c:98
msgid "File System"
msgstr "Файлова система"
@ -1614,7 +1667,7 @@ msgstr "Файлова система"
#. * example, "Trash: some-directory". It means that the
#. * directory called "some-directory" is in the trash.
#.
#: ../src/shell-util.c:311
#: ../src/shell-util.c:294
#, c-format
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"

139
po/ca.po
View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-22 19:53+0200\n"
"PO-Revision-Date: 2011-09-22 19:53+0200\n"
"POT-Creation-Date: 2011-10-04 23:29+0200\n"
"PO-Revision-Date: 2011-10-04 23:30+0200\n"
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
"Language-Team: català; valencià <tradgnome@softcatala.org>\n"
"Language: ca\n"
@ -604,7 +604,11 @@ msgstr "Instal·la"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» de extensions.gnome.org?"
#: ../js/ui/keyboard.js:517 ../js/ui/status/power.js:211
#: ../js/ui/keyboard.js:308
msgid "tray"
msgstr "safata"
#: ../js/ui/keyboard.js:530 ../js/ui/status/power.js:211
msgid "Keyboard"
msgstr "Teclat"
@ -634,11 +638,11 @@ msgstr "Fora d'hora"
msgid "Downloading"
msgstr "S'està baixant"
#: ../js/ui/lookingGlass.js:724
#: ../js/ui/lookingGlass.js:720
msgid "View Source"
msgstr "Mostra el codi font"
#: ../js/ui/lookingGlass.js:730
#: ../js/ui/lookingGlass.js:726
msgid "Web Page"
msgstr "Pàgina web"
@ -646,7 +650,7 @@ msgstr "Pàgina web"
msgid "Open"
msgstr "Obre"
#: ../js/ui/messageTray.js:2379
#: ../js/ui/messageTray.js:2406
msgid "System Information"
msgstr "Informació de l'ordinador"
@ -815,7 +819,7 @@ msgstr "Contrasenya:"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches.
#: ../js/ui/popupMenu.js:727
#: ../js/ui/popupMenu.js:731
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
@ -964,7 +968,7 @@ msgstr "Permet l'accés sempre"
msgid "Grant this time only"
msgstr "Permet-ho només ara"
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1196
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1200
msgid "Reject"
msgstr "Rebutja"
@ -1233,39 +1237,39 @@ msgid "Invitation"
msgstr "Invitació"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:325
#: ../js/ui/telepathyClient.js:327
msgid "Call"
msgstr "Trucada"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:353
#: ../js/ui/telepathyClient.js:357
msgid "File Transfer"
msgstr "Transferència de fitxers"
#: ../js/ui/telepathyClient.js:434
#: ../js/ui/telepathyClient.js:438
msgid "Subscription request"
msgstr "Teniu una petició de subscripció"
#: ../js/ui/telepathyClient.js:470
#: ../js/ui/telepathyClient.js:474
msgid "Connection error"
msgstr "S'ha produït un error de connexió"
#: ../js/ui/telepathyClient.js:733
#: ../js/ui/telepathyClient.js:737
#, c-format
msgid "%s is online."
msgstr "%s és en línia."
#: ../js/ui/telepathyClient.js:738
#: ../js/ui/telepathyClient.js:742
#, c-format
msgid "%s is offline."
msgstr "%s no hi és."
#: ../js/ui/telepathyClient.js:741
#: ../js/ui/telepathyClient.js:745
#, c-format
msgid "%s is away."
msgstr "%s és lluny."
#: ../js/ui/telepathyClient.js:744
#: ../js/ui/telepathyClient.js:748
#, c-format
msgid "%s is busy."
msgstr "%s està ocupat."
@ -1273,35 +1277,35 @@ msgstr "%s està ocupat."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:978
#: ../js/ui/telepathyClient.js:982
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviat a les <b>%X</b> del <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:984
#: ../js/ui/telepathyClient.js:988
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviat el <b>%A %d de %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:989
#: ../js/ui/telepathyClient.js:993
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviat el <b>%A %d de %B</b> de %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:1031
#: ../js/ui/telepathyClient.js:1035
#, c-format
msgid "%s is now known as %s"
msgstr "En/na %s ara es diu %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1140
#: ../js/ui/telepathyClient.js:1144
#, c-format
msgid "Invitation to %s"
msgstr "Us han convidat a entrar a %s"
@ -1309,34 +1313,34 @@ msgstr "Us han convidat a entrar a %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1148
#: ../js/ui/telepathyClient.js:1152
#, c-format
msgid "%s is inviting you to join %s"
msgstr "En/na %s us convida a entrar a %s"
#: ../js/ui/telepathyClient.js:1150 ../js/ui/telepathyClient.js:1239
#: ../js/ui/telepathyClient.js:1343
#: ../js/ui/telepathyClient.js:1154 ../js/ui/telepathyClient.js:1243
#: ../js/ui/telepathyClient.js:1347
msgid "Decline"
msgstr "Declina"
#: ../js/ui/telepathyClient.js:1151 ../js/ui/telepathyClient.js:1240
#: ../js/ui/telepathyClient.js:1344
#: ../js/ui/telepathyClient.js:1155 ../js/ui/telepathyClient.js:1244
#: ../js/ui/telepathyClient.js:1348
msgid "Accept"
msgstr "Accepta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1184
#: ../js/ui/telepathyClient.js:1188
#, c-format
msgid "Video call from %s"
msgstr "Videotrucada de %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1187
#: ../js/ui/telepathyClient.js:1191
#, c-format
msgid "Call from %s"
msgstr "Trucada de %s"
#: ../js/ui/telepathyClient.js:1197
#: ../js/ui/telepathyClient.js:1201
msgid "Answer"
msgstr "Contesta"
@ -1345,112 +1349,112 @@ msgstr "Contesta"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1233
#: ../js/ui/telepathyClient.js:1237
#, c-format
msgid "%s is sending you %s"
msgstr "En/na %s us envia %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1308
#: ../js/ui/telepathyClient.js:1312
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vol poder saber quan esteu en línia"
#: ../js/ui/telepathyClient.js:1406
#: ../js/ui/telepathyClient.js:1410
msgid "Network error"
msgstr "Error de la xarxa"
#: ../js/ui/telepathyClient.js:1408
#: ../js/ui/telepathyClient.js:1412
msgid "Authentication failed"
msgstr "Ha fallat l'autenticació"
#: ../js/ui/telepathyClient.js:1410
#: ../js/ui/telepathyClient.js:1414
msgid "Encryption error"
msgstr "Error d'encriptació"
#: ../js/ui/telepathyClient.js:1412
#: ../js/ui/telepathyClient.js:1416
msgid "Certificate not provided"
msgstr "No s'ha proporcionat el certificat"
#: ../js/ui/telepathyClient.js:1414
#: ../js/ui/telepathyClient.js:1418
msgid "Certificate untrusted"
msgstr "El certificat no és de confiança"
#: ../js/ui/telepathyClient.js:1416
#: ../js/ui/telepathyClient.js:1420
msgid "Certificate expired"
msgstr "El certificat ha vençut"
#: ../js/ui/telepathyClient.js:1418
#: ../js/ui/telepathyClient.js:1422
msgid "Certificate not activated"
msgstr "El certificat no està activat"
#: ../js/ui/telepathyClient.js:1420
#: ../js/ui/telepathyClient.js:1424
msgid "Certificate hostname mismatch"
msgstr "No coincideix el nom de la màquina del certificat"
#: ../js/ui/telepathyClient.js:1422
#: ../js/ui/telepathyClient.js:1426
msgid "Certificate fingerprint mismatch"
msgstr "No coincideix l'empremta digital del certificat"
#: ../js/ui/telepathyClient.js:1424
#: ../js/ui/telepathyClient.js:1428
msgid "Certificate self-signed"
msgstr "Certificat signat per un mateix"
#: ../js/ui/telepathyClient.js:1426
#: ../js/ui/telepathyClient.js:1430
msgid "Status is set to offline"
msgstr "S'ha establert l'estat a fora de línia"
#: ../js/ui/telepathyClient.js:1428
#: ../js/ui/telepathyClient.js:1432
msgid "Encryption is not available"
msgstr "L'encriptació no està disponible"
#: ../js/ui/telepathyClient.js:1430
#: ../js/ui/telepathyClient.js:1434
msgid "Certificate is invalid"
msgstr "El certificat no és vàlid"
#: ../js/ui/telepathyClient.js:1432
#: ../js/ui/telepathyClient.js:1436
msgid "Connection has been refused"
msgstr "S'ha rebutjat la connexió"
#: ../js/ui/telepathyClient.js:1434
#: ../js/ui/telepathyClient.js:1438
msgid "Connection can't be established"
msgstr "No es pot establir la connexió"
#: ../js/ui/telepathyClient.js:1436
#: ../js/ui/telepathyClient.js:1440
msgid "Connection has been lost"
msgstr "S'ha perdut la connexió"
#: ../js/ui/telepathyClient.js:1438
#: ../js/ui/telepathyClient.js:1442
msgid "This resource is already connected to the server"
msgstr "Aquest recurs ja està connectat al servidor"
#: ../js/ui/telepathyClient.js:1440
#: ../js/ui/telepathyClient.js:1444
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"S'ha reemplaçat la connexió per una altra de nova fent servir el mateix "
"recurs"
#: ../js/ui/telepathyClient.js:1442
#: ../js/ui/telepathyClient.js:1446
msgid "The account already exists on the server"
msgstr "Ja existeix aquest compte al servidor"
#: ../js/ui/telepathyClient.js:1444
#: ../js/ui/telepathyClient.js:1448
msgid "Server is currently too busy to handle the connection"
msgstr "El servidor està massa ocupat per gestionar la connexió"
#: ../js/ui/telepathyClient.js:1446
#: ../js/ui/telepathyClient.js:1450
msgid "Certificate has been revoked"
msgstr "S'ha revocat el certificat"
#: ../js/ui/telepathyClient.js:1448
#: ../js/ui/telepathyClient.js:1452
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"El certificat utilitza un algorisme criptògraf no segur o la seva fortalesa "
"criptogràfica és feble"
#: ../js/ui/telepathyClient.js:1450
#: ../js/ui/telepathyClient.js:1454
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1460,20 +1464,20 @@ msgstr ""
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1459
#: ../js/ui/telepathyClient.js:1463
#, c-format
msgid "Connection to %s failed"
msgstr "Ha fallat la connexió a %s"
#: ../js/ui/telepathyClient.js:1468
#: ../js/ui/telepathyClient.js:1472
msgid "Reconnect"
msgstr "Torna a connectar"
#: ../js/ui/telepathyClient.js:1469
#: ../js/ui/telepathyClient.js:1473
msgid "Edit account"
msgstr "Edita el compte"
#: ../js/ui/telepathyClient.js:1515
#: ../js/ui/telepathyClient.js:1519
msgid "Unknown reason"
msgstr "Motiu desconegut"
@ -1542,12 +1546,7 @@ msgstr "Teclegeu per cercar..."
msgid "Search"
msgstr "Cerca"
#: ../js/ui/windowAttentionHandler.js:39
#, c-format
msgid "%s has finished starting"
msgstr "S'ha acabat d'iniciar %s"
#: ../js/ui/windowAttentionHandler.js:41
#: ../js/ui/windowAttentionHandler.js:35
#, c-format
msgid "'%s' is ready"
msgstr "«%s» ja està a punt"
@ -1619,6 +1618,18 @@ msgstr "Sistema de fitxers"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "%s has not emitted any errors."
#~ msgstr "%s no ha emès cap error."
#~ msgid "Hide Errors"
#~ msgstr "Amaga els errors"
#~ msgid "Show Errors"
#~ msgstr "Mostra els errors"
#~ msgid "%s has finished starting"
#~ msgstr "S'ha acabat d'iniciar %s"
#~ msgid "If true, display onscreen keyboard."
#~ msgstr "Si és «true» (cert) mostra el teclat en pantalla."

View File

@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: HEAD\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-09-26 14:26+0200\n"
"PO-Revision-Date: 2011-09-22 19:53+0200\n"
"POT-Creation-Date: 2011-10-01 16:04+0200\n"
"PO-Revision-Date: 2011-10-01 16:03+0200\n"
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
"Language-Team: català; valencià <tradgnome@softcatala.org>\n"
"Language: ca-XV\n"
@ -604,7 +604,7 @@ msgstr "Instal·la"
msgid "Download and install '%s' from extensions.gnome.org?"
msgstr "Voleu baixar i instal·lar «%s» d'extensions.gnome.org?"
#: ../js/ui/keyboard.js:517 ../js/ui/status/power.js:211
#: ../js/ui/keyboard.js:529 ../js/ui/status/power.js:211
msgid "Keyboard"
msgstr "Teclat"
@ -612,33 +612,47 @@ msgstr "Teclat"
msgid "No extensions installed"
msgstr "No hi ha cap extensió instal·lada"
#: ../js/ui/lookingGlass.js:691
#. Translators: argument is an extension UUID.
#: ../js/ui/lookingGlass.js:700
#, c-format
msgid "%s has not emitted any errors."
msgstr "%s no ha emés cap error."
#: ../js/ui/lookingGlass.js:706
msgid "Hide Errors"
msgstr "Amaga els errors"
#: ../js/ui/lookingGlass.js:710 ../js/ui/lookingGlass.js:760
msgid "Show Errors"
msgstr "Mostra els errors"
#: ../js/ui/lookingGlass.js:719
msgid "Enabled"
msgstr "Habilitat"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:693 ../src/gvc/gvc-mixer-control.c:1093
#: ../js/ui/lookingGlass.js:721 ../src/gvc/gvc-mixer-control.c:1093
msgid "Disabled"
msgstr "Inhabilitat"
#: ../js/ui/lookingGlass.js:695
#: ../js/ui/lookingGlass.js:723
msgid "Error"
msgstr "Error"
#: ../js/ui/lookingGlass.js:697
#: ../js/ui/lookingGlass.js:725
msgid "Out of date"
msgstr "Fora d'hora"
#: ../js/ui/lookingGlass.js:699
#: ../js/ui/lookingGlass.js:727
msgid "Downloading"
msgstr "S'està baixant"
#: ../js/ui/lookingGlass.js:724
#: ../js/ui/lookingGlass.js:748
msgid "View Source"
msgstr "Mostra el codi font"
#: ../js/ui/lookingGlass.js:730
#: ../js/ui/lookingGlass.js:754
msgid "Web Page"
msgstr "Pàgina web"
@ -646,7 +660,7 @@ msgstr "Pàgina web"
msgid "Open"
msgstr "Obri"
#: ../js/ui/messageTray.js:2405
#: ../js/ui/messageTray.js:2406
msgid "System Information"
msgstr "Informació de l'ordinador"
@ -964,7 +978,7 @@ msgstr "Permet l'accés sempre"
msgid "Grant this time only"
msgstr "Permet-ho només ara"
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1196
#: ../js/ui/status/bluetooth.js:392 ../js/ui/telepathyClient.js:1200
msgid "Reject"
msgstr "Rebutja"
@ -1233,39 +1247,39 @@ msgid "Invitation"
msgstr "Invitació"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:325
#: ../js/ui/telepathyClient.js:327
msgid "Call"
msgstr "Trucada"
#. We got the TpContact
#: ../js/ui/telepathyClient.js:353
#: ../js/ui/telepathyClient.js:357
msgid "File Transfer"
msgstr "Transferència de fitxers"
#: ../js/ui/telepathyClient.js:434
#: ../js/ui/telepathyClient.js:438
msgid "Subscription request"
msgstr "Teniu una petició de subscripció"
#: ../js/ui/telepathyClient.js:470
#: ../js/ui/telepathyClient.js:474
msgid "Connection error"
msgstr "S'ha produït un error de connexió"
#: ../js/ui/telepathyClient.js:733
#: ../js/ui/telepathyClient.js:737
#, c-format
msgid "%s is online."
msgstr "%s és en línia."
#: ../js/ui/telepathyClient.js:738
#: ../js/ui/telepathyClient.js:742
#, c-format
msgid "%s is offline."
msgstr "%s no hi és."
#: ../js/ui/telepathyClient.js:741
#: ../js/ui/telepathyClient.js:745
#, c-format
msgid "%s is away."
msgstr "%s és lluny."
#: ../js/ui/telepathyClient.js:744
#: ../js/ui/telepathyClient.js:748
#, c-format
msgid "%s is busy."
msgstr "%s està ocupat."
@ -1273,35 +1287,35 @@ msgstr "%s està ocupat."
#. Translators: this is a time format string followed by a date.
#. If applicable, replace %X with a strftime format valid for your
#. locale, without seconds.
#: ../js/ui/telepathyClient.js:978
#: ../js/ui/telepathyClient.js:982
#, no-c-format
msgid "Sent at <b>%X</b> on <b>%A</b>"
msgstr "Enviat a les <b>%X</b> del <b>%A</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25",
#. shown when you get a chat message in the same year.
#: ../js/ui/telepathyClient.js:984
#: ../js/ui/telepathyClient.js:988
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>"
msgstr "Enviat el <b>%A %d de %B</b>"
#. Translators: this is a time format in the style of "Wednesday, May 25, 2012",
#. shown when you get a chat message in a different year.
#: ../js/ui/telepathyClient.js:989
#: ../js/ui/telepathyClient.js:993
#, no-c-format
msgid "Sent on <b>%A</b>, <b>%B %d</b>, %Y"
msgstr "Enviat el <b>%A %d de %B</b> de %Y"
#. Translators: this is the other person changing their old IM name to their new
#. IM name.
#: ../js/ui/telepathyClient.js:1031
#: ../js/ui/telepathyClient.js:1035
#, c-format
msgid "%s is now known as %s"
msgstr "En/na %s ara es diu %s"
#. translators: argument is a room name like
#. * room@jabber.org for example.
#: ../js/ui/telepathyClient.js:1140
#: ../js/ui/telepathyClient.js:1144
#, c-format
msgid "Invitation to %s"
msgstr "Vos han convidat a entrar a %s"
@ -1309,34 +1323,34 @@ msgstr "Vos han convidat a entrar a %s"
#. translators: first argument is the name of a contact and the second
#. * one the name of a room. "Alice is inviting you to join room@jabber.org
#. * for example.
#: ../js/ui/telepathyClient.js:1148
#: ../js/ui/telepathyClient.js:1152
#, c-format
msgid "%s is inviting you to join %s"
msgstr "En/na %s vos convida a entrar a %s"
#: ../js/ui/telepathyClient.js:1150 ../js/ui/telepathyClient.js:1239
#: ../js/ui/telepathyClient.js:1343
#: ../js/ui/telepathyClient.js:1154 ../js/ui/telepathyClient.js:1243
#: ../js/ui/telepathyClient.js:1347
msgid "Decline"
msgstr "Declina"
#: ../js/ui/telepathyClient.js:1151 ../js/ui/telepathyClient.js:1240
#: ../js/ui/telepathyClient.js:1344
#: ../js/ui/telepathyClient.js:1155 ../js/ui/telepathyClient.js:1244
#: ../js/ui/telepathyClient.js:1348
msgid "Accept"
msgstr "Accepta"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1184
#: ../js/ui/telepathyClient.js:1188
#, c-format
msgid "Video call from %s"
msgstr "Videotrucada de %s"
#. translators: argument is a contact name like Alice for example.
#: ../js/ui/telepathyClient.js:1187
#: ../js/ui/telepathyClient.js:1191
#, c-format
msgid "Call from %s"
msgstr "Trucada de %s"
#: ../js/ui/telepathyClient.js:1197
#: ../js/ui/telepathyClient.js:1201
msgid "Answer"
msgstr "Contesta"
@ -1345,112 +1359,112 @@ msgstr "Contesta"
#. * file name. The string will be something
#. * like: "Alice is sending you test.ogg"
#.
#: ../js/ui/telepathyClient.js:1233
#: ../js/ui/telepathyClient.js:1237
#, c-format
msgid "%s is sending you %s"
msgstr "En/na %s vos envia %s"
#. To translators: The parameter is the contact's alias
#: ../js/ui/telepathyClient.js:1308
#: ../js/ui/telepathyClient.js:1312
#, c-format
msgid "%s would like permission to see when you are online"
msgstr "%s vol poder saber quan esteu en línia"
#: ../js/ui/telepathyClient.js:1406
#: ../js/ui/telepathyClient.js:1410
msgid "Network error"
msgstr "Error de la xarxa"
#: ../js/ui/telepathyClient.js:1408
#: ../js/ui/telepathyClient.js:1412
msgid "Authentication failed"
msgstr "Ha fallat l'autenticació"
#: ../js/ui/telepathyClient.js:1410
#: ../js/ui/telepathyClient.js:1414
msgid "Encryption error"
msgstr "Error d'encriptació"
#: ../js/ui/telepathyClient.js:1412
#: ../js/ui/telepathyClient.js:1416
msgid "Certificate not provided"
msgstr "No s'ha proporcionat el certificat"
#: ../js/ui/telepathyClient.js:1414
#: ../js/ui/telepathyClient.js:1418
msgid "Certificate untrusted"
msgstr "El certificat no és de confiança"
#: ../js/ui/telepathyClient.js:1416
#: ../js/ui/telepathyClient.js:1420
msgid "Certificate expired"
msgstr "El certificat ha vençut"
#: ../js/ui/telepathyClient.js:1418
#: ../js/ui/telepathyClient.js:1422
msgid "Certificate not activated"
msgstr "El certificat no està activat"
#: ../js/ui/telepathyClient.js:1420
#: ../js/ui/telepathyClient.js:1424
msgid "Certificate hostname mismatch"
msgstr "No coincideix el nom de la màquina del certificat"
#: ../js/ui/telepathyClient.js:1422
#: ../js/ui/telepathyClient.js:1426
msgid "Certificate fingerprint mismatch"
msgstr "No coincideix l'empremta digital del certificat"
#: ../js/ui/telepathyClient.js:1424
#: ../js/ui/telepathyClient.js:1428
msgid "Certificate self-signed"
msgstr "Certificat signat per un mateix"
#: ../js/ui/telepathyClient.js:1426
#: ../js/ui/telepathyClient.js:1430
msgid "Status is set to offline"
msgstr "S'ha establit l'estat a fora de línia"
#: ../js/ui/telepathyClient.js:1428
#: ../js/ui/telepathyClient.js:1432
msgid "Encryption is not available"
msgstr "L'encriptació no està disponible"
#: ../js/ui/telepathyClient.js:1430
#: ../js/ui/telepathyClient.js:1434
msgid "Certificate is invalid"
msgstr "El certificat no és vàlid"
#: ../js/ui/telepathyClient.js:1432
#: ../js/ui/telepathyClient.js:1436
msgid "Connection has been refused"
msgstr "S'ha rebutjat la connexió"
#: ../js/ui/telepathyClient.js:1434
#: ../js/ui/telepathyClient.js:1438
msgid "Connection can't be established"
msgstr "No es pot establir la connexió"
#: ../js/ui/telepathyClient.js:1436
#: ../js/ui/telepathyClient.js:1440
msgid "Connection has been lost"
msgstr "S'ha perdut la connexió"
#: ../js/ui/telepathyClient.js:1438
#: ../js/ui/telepathyClient.js:1442
msgid "This resource is already connected to the server"
msgstr "Este recurs ja està connectat al servidor"
#: ../js/ui/telepathyClient.js:1440
#: ../js/ui/telepathyClient.js:1444
msgid ""
"Connection has been replaced by a new connection using the same resource"
msgstr ""
"S'ha reemplaçat la connexió per una altra de nova fent servir el mateix "
"recurs"
#: ../js/ui/telepathyClient.js:1442
#: ../js/ui/telepathyClient.js:1446
msgid "The account already exists on the server"
msgstr "Ja existeix este compte al servidor"
#: ../js/ui/telepathyClient.js:1444
#: ../js/ui/telepathyClient.js:1448
msgid "Server is currently too busy to handle the connection"
msgstr "El servidor està massa ocupat per gestionar la connexió"
#: ../js/ui/telepathyClient.js:1446
#: ../js/ui/telepathyClient.js:1450
msgid "Certificate has been revoked"
msgstr "S'ha revocat el certificat"
#: ../js/ui/telepathyClient.js:1448
#: ../js/ui/telepathyClient.js:1452
msgid ""
"Certificate uses an insecure cipher algorithm or is cryptographically weak"
msgstr ""
"El certificat utilitza un algorisme criptògraf no segur o la seua fortalesa "
"criptogràfica és feble"
#: ../js/ui/telepathyClient.js:1450
#: ../js/ui/telepathyClient.js:1454
msgid ""
"The length of the server certificate, or the depth of the server certificate "
"chain, exceed the limits imposed by the cryptography library"
@ -1460,20 +1474,20 @@ msgstr ""
#. translators: argument is the account name, like
#. * name@jabber.org for example.
#: ../js/ui/telepathyClient.js:1459
#: ../js/ui/telepathyClient.js:1463
#, c-format
msgid "Connection to %s failed"
msgstr "Ha fallat la connexió a %s"
#: ../js/ui/telepathyClient.js:1468
#: ../js/ui/telepathyClient.js:1472
msgid "Reconnect"
msgstr "Torna a connectar"
#: ../js/ui/telepathyClient.js:1469
#: ../js/ui/telepathyClient.js:1473
msgid "Edit account"
msgstr "Edita el compte"
#: ../js/ui/telepathyClient.js:1515
#: ../js/ui/telepathyClient.js:1519
msgid "Unknown reason"
msgstr "Motiu desconegut"
@ -1542,12 +1556,7 @@ msgstr "Teclegeu per cercar..."
msgid "Search"
msgstr "Cerca"
#: ../js/ui/windowAttentionHandler.js:39
#, c-format
msgid "%s has finished starting"
msgstr "S'ha acabat d'iniciar %s"
#: ../js/ui/windowAttentionHandler.js:41
#: ../js/ui/windowAttentionHandler.js:35
#, c-format
msgid "'%s' is ready"
msgstr "«%s» ja està a punt"
@ -1619,6 +1628,9 @@ msgstr "Sistema de fitxers"
msgid "%1$s: %2$s"
msgstr "%1$s: %2$s"
#~ msgid "%s has finished starting"
#~ msgstr "S'ha acabat d'iniciar %s"
#~ msgid "If true, display onscreen keyboard."
#~ msgstr "Si és «true» (cert) mostra el teclat en pantalla."

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