Compare commits

...

302 Commits

Author SHA1 Message Date
c1300ddbbc Bump version to 3.2.0
Update NEWS
2011-09-26 16:39:21 -04:00
8bd5b1e696 st: Fix crash in theme-node-transition
Setting up the framebuffers for transitions may fail, in which case
the material used for drawing is left uninitialized, so trying to
access it results in a crash.
Instead bail out in this case, which means that we won't paint
anything during the transition - still, drawing errors are better
than crashes ...

https://bugzilla.gnome.org/show_bug.cgi?id=659676
2011-09-26 19:52:36 +02:00
40c5db397d messageTray: unset this._clickedSummaryItem if we are hiding the summary box pointer and don't have a new clicked summary item
This ensures that this._clickedSummaryItem is always unset correctly.

Because we disconnect the signals that have _adjustSummaryBoxPointerPosition()
as a callback when unsetting this._clickedSummaryItem, we no longer call
setPosition() on this._summaryBoxPointer after it is hidden. Calling
setPosition() shows the box pointer again, which previously resulted in
an empty box pointer staying behind when a notification associated with
a tray icon was clicked.

https://bugzilla.gnome.org/show_bug.cgi?id=659862
2011-09-26 13:30:46 -04:00
8b52919b4d Updated Telugu Translation 2011-09-26 22:46:26 +05:30
2859f23038 Fixed some strings in Brazilian Portuguese translation 2011-09-26 10:36:54 -03:00
00384ccb47 telepathyClient: call delay on context when approving a FT or call
Not doing so is considered as a bug as we don't accept the context right away.
It leads to tp-glib returning directly from the AddDispatchOperation() D-Bus
call and so automatically approve the channel if the Shell is the only
approver running.

https://bugzilla.gnome.org/show_bug.cgi?id=660084
2011-09-26 14:49:21 +02:00
0191cc589a Updated Finnish translation 2011-09-26 15:43:09 +03:00
dae6db9b51 [l10n]Updated Catalan (Valencian) translation 2011-09-26 14:26:05 +02:00
4d912c9feb Updated Japanese translation 2011-09-26 11:59:08 +09:00
07c4b46466 Update Czech translation 2011-09-26 02:00:30 +02:00
e9cdce49a3 Updated Russian translation 2011-09-26 01:18:09 +04:00
84c3ce8778 Updated Latvian translation. 2011-09-25 21:55:16 +03:00
d5a32a7fe4 Updated Japanese translation 2011-09-26 01:04:14 +09:00
cc4dfda21b Updated Indonesian translation 2011-09-25 15:41:58 +07:00
703b37aa7b Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-09-25 14:52:31 +08:00
b433de9022 Updated Bulgarian translation 2011-09-25 08:34:54 +03:00
0c1a22ff95 Updated Slovak translation 2011-09-24 22:57:48 +02:00
4d526e40c3 [l10n] Updated German translation 2011-09-24 20:46:15 +02:00
4586c7b36b Fix display of dates in the Hungarian translation 2011-09-24 19:18:51 +02:00
3d60b73b60 Updated Lithuanian translation 2011-09-24 15:41:38 +03:00
4ef5cd8ef6 Updated Hungarian translation 2011-09-24 01:46:46 +02:00
6959bd19f1 Updated Basque language 2011-09-23 18:19:56 +02:00
17e4ce5ea8 Updated French translation 2011-09-23 18:08:57 +02:00
33094b4988 messageTray: fix notification/keyboard interaction
If the pointer moves from the notification into the keyboard, don't
treat that as moving out of the tray.

https://bugzilla.gnome.org/show_bug.cgi?id=658603
2011-09-23 07:56:45 -04:00
a8fdcffd44 messageTray: move the summary box pointer up when the keyboard shows
If the keyboard is shown when a summary boxpointer is visible (eg,
when opening a chat source), animate the boxpointer up with the tray.

https://bugzilla.gnome.org/show_bug.cgi?id=658603
2011-09-23 07:55:47 -04:00
5adb5411fa keyboard: fix D-Bus name acquisition flags to totally block Antler
We never want the antler keyboard to run if gnome-shell is running, so
grab org.gnome.Caribou.Keyboard without the "allow replacement" flag.

https://bugzilla.gnome.org/show_bug.cgi?id=659865
2011-09-23 07:53:51 -04:00
ff0d11c89c Updated Hebrew translation. 2011-09-23 08:51:57 +03:00
5f6dce2b5c popup-menu: Fix allocation in RTL locales
Commit ed7d4928e5 fixed some width-for-height cases in popup menu items,
but did not consider RTL locales. Fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=659827
2011-09-22 21:52:26 +02:00
a7405e8b39 Updated translation for Afrikaans (af) not including latest strings since freeze 2011-09-22 21:20:29 +02:00
d87c520bad Updated Esperanto translation 2011-09-22 20:29:31 +02:00
24959f8d34 Updated Esperanto translation 2011-09-22 20:26:25 +02:00
6d1432e166 [l10n]Updated Catalan translation 2011-09-22 19:54:11 +02:00
2c7ba2c125 Updated Korean translation 2011-09-23 02:33:19 +09:00
a0ba664c64 messageTray: only update an icon when necessary on notification update
This avoids unnecessarily removing and resetting the icon in the notifications.

This fixes the new chat notification sliding down and up slightly when new
messages are received.

https://bugzilla.gnome.org/show_bug.cgi?id=659768
2011-09-22 13:25:35 -04:00
131da5f523 telepathyClient: update the avatar correctly when it changes
Previously, when the avatar changed, we would not update the summary icon
for the source at all and would only update the notification icon when the
next message was received. Instead, we should update both immediately upon
recieving the signal that the avatar has changed.

https://bugzilla.gnome.org/show_bug.cgi?id=659768
2011-09-22 13:25:35 -04:00
7c6144450a Updated Slovenian translation 2011-09-22 18:06:45 +02:00
4c7369db16 build: Switch to stable cogl/clutter branches for now 2011-09-22 16:35:45 +02:00
f4355de896 Updated Telugu Translation 2011-09-22 19:56:35 +05:30
4a3db9f44d Updated Danish translation 2011-09-22 16:07:11 +02:00
6c0a9ff9cc Updated Brazilian Portuguese translation. Reviewed by Djavan Fagundes <djavanf@gnome.org>. 2011-09-22 09:59:50 -03:00
57b1695fcf keyboard: don't try to move windows out of the way of the keyboard
This code was never tested very well, and has several problems
currently (windows creeping down and to the right, windows snapping to
a different location after you move them). To be fixed in 3.4.

https://bugzilla.gnome.org/show_bug.cgi?id=659643
2011-09-22 07:55:20 -04:00
045c6546cc Add Assamese translation 2011-09-22 12:19:02 +02:00
ce5bd954bf Add Assamese translation 2011-09-22 12:18:08 +02:00
6ef00a4a3b Updated Spanish translation 2011-09-22 11:47:37 +02:00
569d9718a0 Updated Norwegian bokmål translation 2011-09-22 10:10:41 +02:00
00a3a8697f [l10n] Updated German translation 2011-09-22 08:50:50 +02:00
c93444e390 Updated Swedish translation 2011-09-22 06:38:15 +02:00
5e5788ab14 update Punjabi Translation 2011-09-22 06:16:06 +05:30
abf57e6362 Updated Portuguese translation 2011-09-22 00:35:36 +01:00
74c2074d5a Updated Galician translations 2011-09-21 22:51:32 +02:00
b74606312e Updated Polish translation 2011-09-21 22:05:00 +02:00
0c849df4d5 Updated Belarusian translation. 2011-09-21 22:18:23 +03:00
38690d4a09 autorun: mark string as translatable 2011-09-21 21:10:50 +02:00
b64c237cb3 Updated Polish translation 2011-09-21 20:39:04 +02:00
3fbee8e027 configure.ac: switch to tar-ustar
tar-ustar is the GNOME standard and has some small advantages
over the default tar-v7, like support for long file names.
2011-09-21 12:33:11 -04:00
a68e6e3c63 Updated Danish translation 2011-09-21 17:57:09 +02:00
db5a72774d configure: Require gjs 1.29.18 for GC stuff 2011-09-21 10:04:36 -04:00
966f90f24a Updated Hungarian translation 2011-09-21 03:08:49 +02:00
eaa664c023 Updated Portuguese translation 2011-09-21 00:45:47 +01:00
e9282c3987 Bump version to 3.1.92
Update NEWS
2011-09-20 17:16:24 -04:00
ed1f8ed339 Add missing test to Makefile.am 2011-09-20 17:15:41 -04:00
5d0d637eb8 Updated Serbian translation 2011-09-20 22:14:58 +02:00
7e70dfdf4c messageTray: Fix line wrapping
Clutter 1.4 had a bug where it would wrap when it wasn't supposed to, and we
were unknowingly relying on it. Explicitly pass the available width/height
to get a perfect allocation.

https://bugzilla.gnome.org/show_bug.cgi?id=659633
2011-09-20 16:06:06 -04:00
3f61f39ae3 dash: Adjust placeholder size to icon size
The placeholder looks odd near small icons and causes the dash to get wider
when visible and narrower when hidden.

https://bugzilla.gnome.org/show_bug.cgi?id=659210
2011-09-20 21:01:25 +01:00
371f623a3e Updated Latvian translation. 2011-09-20 22:15:44 +03:00
566d566f26 alt-tab: Do not hardcode ALT modifier
While we allow for arbitrary modifiers in keybindings, both the
alt-tab and ctrl-alt-tab popups close when ALT is not present in
the modifier mask, resulting in ALT being de-facto hardcoded.
Instead, pass the actual modifier mask when invoking the popups.

https://bugzilla.gnome.org/show_bug.cgi?id=645200
2011-09-20 21:07:19 +02:00
fb30822860 windowManager: shade the actor, not the texture
Applying the "dim window" effect to the MetaWindowActor has two avantages:
first it avoids triggering bugs where ClutterOffscreenEffect doesn't handle
clone paint correctly. Second, it avoids showing the window as dimmed in
alt-Tab and the overview, which is weird.

The small downside of this is that the shadow becomes slightly gray when
the window dimmed, which is wrong - if we switched from blending with gray
to a combination of desaturation and darkening, this problem wouldn't
happen.

Revert out the addition of startY to the shader, since we don't need it
and fix the application of alpha, since we need to handle alpha correctly
for the shadow.

https://bugzilla.gnome.org/show_bug.cgi?id=659634
2011-09-20 14:56:25 -04:00
526a53bdd4 shell-network-agent: Do not handle VPN secrets
VPN secrets are currently unhandled by the UI code. To avoid
lengthy timeouts, bail out early with an error, so NetworkManager
falls back to the nm-applet agent directly.

https://bugzilla.gnome.org/show_bug.cgi?id=658484
2011-09-20 20:05:21 +02:00
3833124d66 apps: Uniquify application instances explicitly by id
Commit 0af108211c introduced a
regression where applications that appear in multiple categories were
duplicated in the "All Apps" list, because we switched from
uniquifying on desktop file ID to the GMenuTreeEntry.

Switch back to keeping the set of apps based on ID.  To flesh this
out, we keep the ShellApp instance for a given ID around forever, and
when we're loading new contents, we replace the GMenuTreeEntry inside
the app. That means callers still get new data.

We still keep around the running app list, though we could just
recompute it from the app list now.

https://bugzilla.gnome.org/show_bug.cgi?id=659351
2011-09-20 13:56:53 -04:00
e5e1b52abf apps: Unify code for apps/settings loading more
The apps and settings loading code duplicated the part to traverse a
GMenuTree.  Unify this by adding a new function to return a flattened
set.

This will also be useful for a future change to how we store apps -
this way we can look at both the current set of apps and the new set.

https://bugzilla.gnome.org/show_bug.cgi?id=659351
2011-09-20 13:56:53 -04:00
82fc66305d Clear the active network when removing the active access point
When the active AP disappears, it is possible to receive the
"access-point-removed" signal before the "notify::active-ap" (as
dbus-glib + libnm-glib property notifications are not reliable).
In that case, we would remove the AP from the network object, thus
an attempt to update the UI would create an item for an empty
network.

https://bugzilla.gnome.org/show_bug.cgi?id=658150
2011-09-20 19:01:23 +02:00
05e0d5066f Don't create AP items for empty networks
Current code is sometime attempting to create menu items for wifi
networks that have no visible AP. I have no idea why this is
happening, but it should fix the symptoms and avoid exceptions.

https://bugzilla.gnome.org/show_bug.cgi?id=658150
2011-09-20 19:01:01 +02:00
ce2dc84e49 Updated Slovenian translation 2011-09-20 13:08:28 +02:00
eb14ed32ea Updated Russian translation 2011-09-20 12:02:47 +04:00
f97987d0d8 Updated Norwegian bokmål translation 2011-09-20 09:16:33 +02:00
d23d9c3b05 update Punjabi Translation 2011-09-20 07:22:39 +05:30
3ebf6e3bea autorun: don't use a custom size for the hotplug icon
Instead, just use the default MessageTray.Source icon size (24px).

https://bugzilla.gnome.org/show_bug.cgi?id=658004
2011-09-19 20:53:50 -04:00
9f41f5c740 l10n: Updated Italian translation 2011-09-20 00:17:09 +02:00
ae00f86887 panel: allow padding around panel buttons to shrink
for narrow screens (eg, portrait orientation)

https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-19 17:43:54 -04:00
ab67c0f8b0 userMenu: fix line wrapping
The previous wrapping code hardcoded a width in pixels, making it
non-text-zoom-friendly. Specify a CSS width in pts, and fix the
userMenu code to completely opt out of the popupMenu column behavior.
Hack PopupComboBoxMenuItem slightly to deal with the fact that the
pop-up no longer gets setColumnWidth'ed.

https://bugzilla.gnome.org/show_bug.cgi?id=652837
2011-09-19 17:36:13 -04:00
ed7d4928e5 popupMenu: fix a few width-for-height cases
specifically, non-columned menus, and span==-1

https://bugzilla.gnome.org/show_bug.cgi?id=652837
2011-09-19 17:36:13 -04:00
f23239a923 status/keyboard: use correct style class name to fix menu highlight
The keyboard status item doesn't derive from SystemStatusButton, since
it doesn't use an icon. But this meant it wasn't getting the right
class name, and so was using the full-width menu title highlight
rather than the small one. Fix that.
2011-09-19 17:36:13 -04:00
d949920e68 status/keyboard: fix function naming style 2011-09-19 17:36:13 -04:00
a1def85c18 Updated Latvian translation. 2011-09-19 23:30:31 +03:00
dc624f65e4 user-menu: Fix spacing in combobox item
At some time an additional container was added which broke the
existing CSS rule.
2011-09-19 22:06:31 +02:00
361652d028 popup-menu: Use correct St.Align values
It is not St.Align.CENTER, but St.Align.MIDDLE - in contrast to
St.TextAlign, where it *is* CENTER. Yay consistency!
2011-09-19 22:06:31 +02:00
92024b7e54 network-agent: Allow entries to activate default action
Currently entries' 'activate' signal is ignored, so hitting enter
does not have any effect, even if all required information has been
entered.
Instead, connect to the 'activate' signal so that hitting enter
behaves as if the "OK" button had been pressed.

https://bugzilla.gnome.org/show_bug.cgi?id=659133
2011-09-19 21:26:32 +02:00
4e4ce0dd21 network-agent: Focus the first reactive entry
Currently network dialogs don't focus password entries, which means
that rather than entering their password directly, users first have
to click the entry (or tab around the dialog).
Instead, put keyboard focus on the first entry that requires user
input.

https://bugzilla.gnome.org/show_bug.cgi?id=659133
2011-09-19 21:26:32 +02:00
bc0c490ec3 polkit-agent: Remove hack to focus password entry
As dialog buttons used to "steal" the initial key focus, the polkit
dialog delayed focusing the password entry. With buttons no longer
overwriting the manually set focus, this is no longer necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=659133
2011-09-19 21:26:32 +02:00
6d92af17fd modal-dialog: Don't let buttons steal manually-set focus
ModalDialog provides a method to set the initial focus. However,
when adding buttons, the initial focus is always set to the last
button, thus overwriting a previously set manual focus.
Instead, only set the initial key focus if setInitialKeyFocus()
has not been called manually before.

https://bugzilla.gnome.org/show_bug.cgi?id=659133
2011-09-19 21:26:32 +02:00
2140a498a2 StTable: Silence row_span warning for now
This seems to be very noisy and generally harmless so
silence it up for now.

https://bugzilla.gnome.org/show_bug.cgi?id=658939
2011-09-19 21:25:07 +02:00
28349d362c Updated Belarusian translation. 2011-09-19 21:59:18 +03:00
e7af9f98e3 [l10n] Updated German translation 2011-09-19 20:17:24 +02:00
dd6053c5e1 [l10n] Updated German translation 2011-09-19 20:14:48 +02:00
37726a4cb6 app: Don't abort if a .desktop file has no Exec= key
Seen in the wild in nautilus-pastebin-configurator.desktop.
2011-09-19 14:13:20 -04:00
4352cc231e modalDialog: Don't use a for...in loop for iterating over arrays.
for...in loops do not guarantee that the indexes iterate in order. As a
consequence, buttons may appear in an undesired order.
2011-09-19 13:42:47 -04:00
824220356f popup-menu: Add 'sensitive' flag to item parameters
A menu action may not make sense at any time, so add API to mark
an item insensitive to indicate that its action is currently
unavailable, but may become activatable at a later point.

https://bugzilla.gnome.org/show_bug.cgi?id=659270
2011-09-19 18:54:15 +02:00
247ad9d7ab scroll-view-sizing: Add tests for padding / borders
Add tests to verify that the fade works fine with borders and
padding.

https://bugzilla.gnome.org/show_bug.cgi?id=659159
2011-09-19 18:51:07 +02:00
09fe12d0c1 st-scroll-view-fade: Pass a precomputed fade area to the shader
Instead of doing complex computations in the shader just pass in the correct
fade area (taking padding, scrollbars and rtl into account) and just work
with that in the shader.

That fixes a bug where we would fade the scrollbar when padding is present.

https://bugzilla.gnome.org/show_bug.cgi?id=659159
2011-09-19 18:51:01 +02:00
127ef8383b windowManager: Incorporate invisible borders into window dimming effect
Without this, the dim "fade" will start at the top of the untrimmed actor. With
a large enough draggable_border_width setting, this will show no fade at all.

https://bugzilla.gnome.org/show_bug.cgi?id=659302
2011-09-19 12:39:48 -04:00
82eccb566c windowManager: Use an off-screen buffer for window dimming
The way the window dimmer shader is applied will cause rendering errors with
the rounded corners, invisible borders or shaped textures since it doesn't deal
well with the multitexturing used by the MetaShapedTexture. Use an off-screen
buffer to flatten the texture before being applied.

https://bugzilla.gnome.org/show_bug.cgi?id=659302
2011-09-19 12:39:41 -04:00
543b29efe7 userMenu: Update the user information if the object is already loaded
Any time we get a cached user object from the AccountsService, it will
already be loaded.

https://bugzilla.gnome.org/show_bug.cgi?id=658605
2011-09-19 10:50:54 -04:00
0f4ce5dd4e altTab: Fix icon scrolling
Don't depend on the primary monitor position for determining whether we should
scroll, just use our own container's size.

https://bugzilla.gnome.org/show_bug.cgi?id=658239
2011-09-19 10:50:54 -04:00
c23919df15 Silently add chat source in the MessageTray
We don't want the tray bar to open/close quickly when adding a chat because
it happens when user opens the chat from Empathy. The notification will
popup on incoming message anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=657249
2011-09-19 16:19:26 +02:00
2b2a8b4747 ctrlAltTab: don't allow more than one popup
In a normal user session you can't have more than one
popup, because the popup is modal and we don't allow
the popup to show up when there are other modals.

In a GDM session, however, the login dialog is modal, and
we want a popup, so we don't have that same check.

This commit changes the ctrlAltTab manager code to not
allow multiple popups.

https://bugzilla.gnome.org/show_bug.cgi?id=659177
2011-09-19 10:17:19 -04:00
2e48dbf6ee main: Let SWITCH_PANELS keybinding through at login screen
Users depend on being able to switch focus between the panel
and the login screen using ctrl-alt-tab.

Because the login screen has no overview, we were short circuiting
some code that needs to get run to support ctrl-alt-tab.

This commit changes the short-circuit code to only run for user
sessions.

https://bugzilla.gnome.org/show_bug.cgi?id=659177
2011-09-19 10:17:18 -04:00
207917ba45 Updated Slovenian translation 2011-09-19 16:15:44 +02:00
f824b97f3a Updated Polish translation 2011-09-19 15:07:04 +02:00
a5ff2fc68f Updated Spanish translation 2011-09-19 14:57:34 +02:00
4906806c0b Updated Gujarati Translations 2011-09-19 18:10:00 +05:30
d98336a906 updated Tamil translation 2011-09-19 17:51:28 +05:30
9ddd11cdb8 Updated Galician translations 2011-09-19 13:44:45 +02:00
554ad4ef05 keyboard: switch to using the correct gsettings key for enable/disable
https://bugzilla.gnome.org/show_bug.cgi?id=612662
2011-09-19 07:34:02 -04:00
45d8550044 Updated Galician translations 2011-09-19 13:18:59 +02:00
f2b44c1494 Updated Persian translation 2011-09-19 14:37:17 +04:30
bdb28e87a9 Updated Persian translation 2011-09-19 14:35:13 +04:30
8b9592e53e Updated Slovak translation 2011-09-19 11:30:12 +02:00
84f89648a6 Update Simplified Chinese translation. 2011-09-19 09:25:48 +00:00
1174992099 Updated Spanish translation 2011-09-19 10:35:57 +02:00
391a220dc1 gdm: add optional logo to user list
This commit adds the ability to set a small logo
at the login screen for administrators and
distributions.

https://bugzilla.gnome.org/show_bug.cgi?id=658062
2011-09-19 00:08:55 -04:00
43f1d0578b gdm: add fingerprint support
This commit adds the ability to log in with a fingerprint instead
of a password (assuming the user is enrolled and fingerprint
isn't disabled via gsettings)

https://bugzilla.gnome.org/show_bug.cgi?id=657823
2011-09-18 23:32:03 -04:00
d3e35028ca Updated Hungarian translation 2011-09-19 02:00:57 +02:00
61c7d87003 Updated Hungarian translation 2011-09-19 02:00:57 +02:00
20f2fa84a4 Updated Swedish translation 2011-09-18 19:35:23 +02:00
17e269b96c Updated Latvian translation. 2011-09-18 20:16:21 +03:00
6a57ac92ba Updated Spanish translation 2011-09-18 17:23:31 +02:00
07ad03556f Updated POTFILES.in 2011-09-18 14:09:01 +02:00
04c33230c8 Updated Bulgarian translation 2011-09-18 11:40:55 +03:00
083dac630f updated Tamil translation 2011-09-18 14:05:50 +05:30
6375724196 Updated Vietnamese translation 2011-09-18 15:59:43 +10:00
922957c1ae po/vi: import from Damned Lies 2011-09-18 15:34:15 +10:00
cbf7d0e738 vi/po: removed redudant %d 2011-09-18 15:30:50 +10:00
fb81efeecf theme/gdm: shrink entry
commit 8424236daa
set the entry to a specific size to prevent it from
growing for long passwords.

The size is a little too long though, since it makes
the dialog pop out horizontally when showing the entry.

This commit drops it down a few em.

https://bugzilla.gnome.org/show_bug.cgi?id=659370
2011-09-17 23:40:20 -04:00
8466198626 loginDialog: subtract padding when drawing focus line
If there's no scrollbar in the user list it grows as the
user arrows around.  This is because it wasn't taking
padding into account when computing its destination size.

https://bugzilla.gnome.org/show_bug.cgi?id=658469
2011-09-17 23:25:31 -04:00
33718ef7a5 panel: drop dead code
The _userMenu variable never gets initialized anymore,
so remove some code that only gets run when it's defined.

https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-17 23:23:15 -04:00
a94a62764d gdm: add a power button
Making users have to log in to power off the machine isn't a good idea.

This commit adds a power menu similar to the one in the fallback greeter
which offers 3 items:

- Suspend
- Restart
- Power off

https://bugzilla.gnome.org/show_bug.cgi?id=657822
2011-09-17 23:16:20 -04:00
12c98df3db Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-09-18 08:35:10 +08:00
81909a406f Updated reduced Finnish translation 2011-09-17 22:29:36 +03:00
d291aaa4f2 Updated Galician translations 2011-09-17 21:21:38 +02:00
da36d87e46 Updated Punjabi Translation 2011-09-18 00:42:12 +05:30
42bc09a7ef Updated Polish translation 2011-09-17 20:55:43 +02:00
d0defc592e Updated Belarusian translation. 2011-09-17 20:15:11 +03:00
700f7fbaf3 gdm: replace 'gdm-password' with a constant
It's a little messy to have 'gdm-password' strung all
through the code, so this commit defines a constant up
top and uses that instead.

https://bugzilla.gnome.org/show_bug.cgi?id=657823
2011-09-17 12:53:54 -04:00
74f2d02ac3 Updated Slovenian translation 2011-09-17 18:15:01 +02:00
c865d96f4b Update Simplified Chinese translation. 2011-09-17 16:04:56 +00:00
cd7b9e108c user-menu: Explain why disabling notifications changes IM status
While the current behavior of setting the IM status to "busy" while
notifications are disabled makes sense, as incoming messages are
very likely to be missed, it is not immediately obvious.
Display a transient notification to explain the behavior to the user.

https://bugzilla.gnome.org/show_bug.cgi?id=652718
2011-09-17 17:18:29 +02:00
f54b82f64c global: Initiate *full* GC at idle
While I've been trying to make the GC kick in more often, I've decided
it's a better tradeoff to aggressively GC at "leisure", for multiple
reasons.

We can and should revisit this at a later time, but basically:

* The shell doesn't generate *that* much JS data - garbage collection
  is very fast here.
* Long periods without GC mean we're not calling free() when we
  could, which in turn makes heap fragmentation much worse.
* Ensuring the GC runs at idle makes it much less likely we'll take
  a random large GC hit in the middle of an animation.

https://bugzilla.gnome.org/show_bug.cgi?id=659254
2011-09-17 10:16:35 -04:00
36bfe8c533 memory: Add display of elapsed seconds since a garbage collection
This is useful information for debugging.

https://bugzilla.gnome.org/show_bug.cgi?id=659254
2011-09-17 10:16:35 -04:00
a40d063cb8 Updated Russian translation 2011-09-17 14:14:52 +04:00
ac88a88bfb Updated Norwegian bokmål translation 2011-09-17 11:47:14 +02:00
d89c9b4556 Updated Japanese translation 2011-09-17 13:07:50 +09:00
a07056f5e2 l10n: Updated Italian translation 2011-09-17 02:01:56 +02:00
f91bea3ea5 Updated Portuguese translation 2011-09-17 01:00:25 +01:00
9fbd79316a panel: merge statusBox into rightBox
Simplify the layout in rightBox by getting rid of statusBox, and just
putting everything into rightBox directly.

Simplify the handling of the user menu by adding it like it was a
status icon rather than special-casing it. Rename the "tray_icon"
variables to "status_area" to reflect this better.

https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-16 14:15:49 -04:00
6d89d0b02a panel: remove legacyBox, mix legacy icons in with regular
Legacy trayicons are mostly gone, so remove some of the special-casing
for them to simplify things.

Also, fix panel.addToStatusArea() to interpret its "position" relative
to tray_icon_order, not relative to the existing contents of
statusBox, so that the order that extension icons appear in does not
depend on the order they are loaded in.

https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-16 14:15:49 -04:00
0febcbfa2a userMenu: belatedly rename CSS to match the new filename
https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-16 14:15:48 -04:00
f2f2898fe3 panel: fix part of the panel-corner-highlighting hack
The underline highlights on the panel menu items normally have a 100ms
transition between highlighted and unhighlighted, but the panel corner
graphics can't do that, so we hacked the Activities button and user
menu to have no transition. But in gdm mode, the user menu isn't the
rightmost item any more. Fix this by modifying the CSS from the code
instead.

https://bugzilla.gnome.org/show_bug.cgi?id=651299
2011-09-16 14:15:48 -04:00
f65826b3ba network: Don't notify on connection lost
The design is for applications to do this, basically.  Web browsers,
Evolution, Empathy already display something on network status change.

Note though we need an application API in GIO to monitor network state;
see https://bugzilla.gnome.org/show_bug.cgi?id=620932

https://bugzilla.gnome.org/show_bug.cgi?id=658954
2011-09-16 13:57:14 -04:00
a869007180 calendar: Improve Layout
- align event header with buttons
 - button hovers stretch across fully like menus
 - better padding for month
 - day hover is lighter

https://bugzilla.gnome.org/show_bug.cgi?id=641135
2011-09-16 19:22:12 +02:00
b5fa48f485 status: don't show 'Show Keyboard Layout' on the login screen
It does not make a great amount of sense to have this function
on the login screen. And worse, it does not work, since the greeter
is currently a modal dialog, so interaction with the opening
window is impossible.

https://bugzilla.gnome.org/show_bug.cgi?id=659164
2011-09-16 09:45:11 -04:00
36d564526c build: Fix rule to create .service files
It was always taking the first .service.in file to create all .service
files: org.gnome.Shell.CalendarServer.service.in was the only one being
used.

https://bugzilla.gnome.org/show_bug.cgi?id=659194
2011-09-16 09:21:14 +02:00
063f34b5d3 browser-plugin: Add support for BROWSER_PLUGIN_DIR environment variable
This makes it easy to override where the plugin should be installed.

This is based on what totem does.

https://bugzilla.gnome.org/show_bug.cgi?id=659123
2011-09-16 00:17:59 +02:00
9486ca5975 Updated Slovenian translation 2011-09-15 22:44:09 +02:00
63ead272a9 Updated Slovenian translation 2011-09-15 22:37:02 +02:00
9dfa2ad84e app-display: Remove AppIconMenu::popup
The signal is just duplicating the parent class' ::open-state-changed
signal, so remove it.
2011-09-15 22:01:58 +02:00
523e431ece tests: Add transition test
https://bugzilla.gnome.org/show_bug.cgi?id=658092
2011-09-15 13:27:12 -04:00
768c4a0dd5 Updated Punjabi Translation 2011-09-15 20:49:58 +05:30
fd25cf30ff messageTray: fix a warning
Check for click in keyboardBox rather than Main.keyboard.actor, since
the latter won't exist when the keyboard is hidden.

https://bugzilla.gnome.org/show_bug.cgi?id=658598
2011-09-15 08:34:29 -04:00
1d14488a4f telepathyClient: notify only once per account for connection error
https://bugzilla.gnome.org/show_bug.cgi?id=659050
2011-09-15 10:10:22 +02:00
6e32c97c43 Updated Bulgarian translation 2011-09-15 07:16:02 +03:00
020fe35d98 Bump version to 3.1.91.1
Update NEW
2011-09-14 18:55:52 -04:00
e0cf946611 Switch to dist-xz
'xz' is now the default tarball format for GNOME, so build
our tarballs that way.
2011-09-14 18:55:52 -04:00
a42ae6fe3a tests/Makefile.am: add missing file to DISTCHECK 2011-09-14 18:55:52 -04:00
196ab6a7c3 Updated Galician translations 2011-09-14 23:08:17 +02:00
f3235882f3 Updated Spanish translation 2011-09-14 21:34:46 +02:00
0518d69b72 panel: Fix corner highlight
The style of the top bar's corners is bound to the style of the
corresponding button; we used to hardcode this association, but
as the login mode does have a different layout, the button is now
determined programmatically.
Unfortunately, some containers take the text direction into account
when ordering their children, while some don't, so the current
code returned the wrong button in RTL locales.

https://bugzilla.gnome.org/show_bug.cgi?id=658983
2011-09-14 21:26:58 +02:00
c9ba94d4d8 Updated Belarusian translation. 2011-09-14 22:03:24 +03:00
50e4a40bb2 Updated French translation
Contributed by Luc Guillemin, Luc Pionchon, Bruno Brouard and Claude
Paroz
2011-09-14 18:35:53 +02:00
351421c158 updated Tamil translation 2011-09-14 21:16:19 +05:30
c3ac2df9ca Updated Polish translation 2011-09-14 16:45:06 +02:00
7c4f632e06 Updated Brazilian Portuguese translation. Reviewed by Henrique P. Machado <hpmachado@gnome.org> and myself. 2011-09-14 11:17:31 -03:00
a4eb3c17eb end-session-dialog: Use correct plural forms for timeouts
All end-session dialogs need to use ngettext for their timeout
strings, fix this.

https://bugzilla.gnome.org/show_bug.cgi?id=639987
2011-09-14 15:43:22 +02:00
e81cee3949 network-status: Remove colloquialism in string
s/You're/You are/

https://bugzilla.gnome.org/show_bug.cgi?id=645037
2011-09-14 15:43:22 +02:00
e943dcafa4 power-status: Mark number with percentage for translation
Some locales expect the percentage sign before the number while
others use a different character, so mark it for translation.

https://bugzilla.gnome.org/show_bug.cgi?id=644097
2011-09-14 15:43:21 +02:00
a324c390f0 Updated Spanish translation 2011-09-14 11:57:09 +02:00
1cf64b5471 workspace: Fix activating windows from xdnd operations
Commit e5bc3a2ba8 changed the hierarchy of WindowClone, which
broke activating windows on hover during xdnd operations. To
avoid intrusive changes, just hide the new actor from picks so
that DND operations pick the actor actually meant to represent
the corresponding window.

https://bugzilla.gnome.org/show_bug.cgi?id=658640
2011-09-14 10:00:46 +02:00
234a4f3a1b hindi update 2011-09-14 10:30:21 +05:30
e69d561e8e updated Tamil translation 2011-09-14 05:41:44 +05:30
b8f2abcbfa Updated Polish translation 2011-09-14 00:47:39 +02:00
189617dfb2 Updated POTFILES.in 2011-09-14 00:43:08 +02:00
c4bfb1e400 l10n: Updated Italian translation 2011-09-14 00:09:48 +02:00
7db92ad5d9 extensionSystem: Add an explicit approval dialog
Pop up a dialog when trying to install an extension so that users are aware
they are installing one. This is a security precaution in the case that an XSS
exploit has been found on the website, which could cause someone to inject a
<script> tag and silently install an extension.

https://bugzilla.gnome.org/show_bug.cgi?id=658612
2011-09-13 12:34:49 -04:00
fa593a3e15 extensionSystem: Use the system cert list
libsoup won't check for a valid cert by default, so copy some logic from
glib-networking to check against the system cert list. Additionally, allow a
fallback for developers, ~/.local/share/extensions.gnome.org.crt, for easy
local development of the website.

https://bugzilla.gnome.org/show_bug.cgi?id=658870
2011-09-13 12:34:48 -04:00
8424236daa theme/gdm: Set a width to the prompt entry
Otherwise it'll keep growing.

https://bugzilla.gnome.org/show_bug.cgi?id=658921
2011-09-13 12:18:45 -04:00
5c14be28f3 updated Tamil translation 2011-09-13 17:39:29 +05:30
9ef80f6ac6 update Simplified Chinese (zh_CN) translation 2011-09-13 11:59:04 +08:00
daf81b5cae Updated Korean translation 2011-09-13 12:06:53 +09:00
7b407dda91 browser-plugin: some buildsys fixes
* fix installation folder

* include headers files

* add Makefile to AC_CONFIG_FILES
2011-09-12 16:23:40 -04:00
4c50293f06 Updated Norwegian bokmål translation 2011-09-12 20:53:27 +02:00
02b8804b96 extensionSystem: Always enable an extension for a user
When the user installs an extension, we always enable it. Change the
'enabled-extensions' key, if necessary, to reflect this.

https://bugzilla.gnome.org/show_bug.cgi?id=658612
2011-09-12 14:37:20 -04:00
7928f90cf6 extensionSystem: Add "UninstallExtension" DBus method
For those who like their system pure, this provides the ability to purge a
pesky extension and its precious place on your disk space, and in your
"Local Extension" list.

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

Conflicts:

	js/ui/extensionSystem.js
2011-09-12 14:37:20 -04:00
d5e6ea6ebd extensionSystem: Replace manifest system with a more direct approach
For security reasons, we shouldn't allow the Shell to download and install
any extension URL.

https://bugzilla.gnome.org/show_bug.cgi?id=658612
2011-09-12 14:37:20 -04:00
52273b6c03 Move sweettooth-plugin into gnome-shell tree, rebrand
This is a direct import from http://github.com/magcius/sweettooth-plugin .
All the source code is the same, as it had no branding. Everything else is
just renaming and modifying the "build system" to work with gnome-shell's
existing one.

https://bugzilla.gnome.org/show_bug.cgi?id=658070
2011-09-12 14:37:20 -04:00
b3d663b758 Updated Swedish translation 2011-09-12 20:27:17 +02:00
c0028694d4 Updated Latvian translation. 2011-09-11 21:40:52 +03:00
3b0110849c Updated British English translation 2011-09-11 15:02:51 +01:00
7b1deba590 Network: destroy notifications when the connection completes
When you finish reconnecting, we should remove any Connection Lost
or Connection Failed notification.

https://bugzilla.gnome.org/show_bug.cgi?id=658049
2011-09-11 12:36:16 +02:00
7a91f318f0 Updated Portuguese translation 2011-09-11 10:46:18 +01:00
2dfde89008 Updated Indonesian translation 2011-09-11 16:03:45 +07:00
23146c00ba Updated Spanish translation 2011-09-11 10:44:36 +02:00
cdd95fbbdc update PunjabiTranslation 2011-09-10 15:12:37 +05:30
01064af20e Updated Spanish translation 2011-09-10 11:12:45 +02:00
01a9c3fc8e Updated Spanish translation 2011-09-10 10:52:26 +02:00
c1734b279b Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-09-10 15:02:02 +08:00
b00dc31b55 Updated galician translations 2011-09-10 03:37:32 +02:00
c5f8c8c77b Updated Polish translation 2011-09-09 22:55:08 +02:00
9361c7223d Add context to ambiguous strings in login dialog
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=658414
2011-09-09 22:46:23 +02:00
b43cc22704 Make maintainer mode enabled by default
See http://blogs.gnome.org/desrt/2011/09/08/am_maintainer_mode-is-not-cool/
2011-09-09 16:14:58 +01:00
8af4fd64c1 telepathyClient: Fix undefined variable
https://bugzilla.gnome.org/show_bug.cgi?id=658624
2011-09-09 10:50:11 -04:00
5b39b87199 Fix up a11y settings handling
Somebody changed the type of the atk-bridge-location key
from s to ay. Without telling affected parties :-(

https://bugzilla.gnome.org/show_bug.cgi?id=658562
2011-09-08 18:38:29 -04:00
092338a4c7 keyboard: hide the keyboard when unfocusing a shell entry
Previously we explicitly didn't do this, although I can't figure out
why now... definitely seems to work more smoothly this way.

https://bugzilla.gnome.org/show_bug.cgi?id=658591
2011-09-08 15:51:22 -04:00
7907b19e28 l10n: Updated Italian translation 2011-09-08 21:36:34 +02:00
5790309e88 Updated Polish translation 2011-09-08 20:57:25 +02:00
9496b64c86 messageTray: hide the summary box pointer if all its notifications are destroyed
This ensures that we don't show an animation of an empty blob being hidden when
clicking an action button causes the notification to be destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=658525
2011-09-08 14:27:39 -04:00
f7fb6b2160 messageTray: store notifications and signal ids in an array of objects in SummaryItem
The code is cleaner that way. It also allows us to find the notification object
after the notification actor is destroyed and disconnect the signals.
2011-09-08 14:27:39 -04:00
98649f9397 apps: handle 'app-state-changed' move in shell-app-usage
commit 0af108211c moved which
object the app-state-changed signal is emitted from.

This commit updates shell-app-usage.c to keep up with the times.

https://bugzilla.gnome.org/show_bug.cgi?id=658503
2011-09-08 10:20:06 -04:00
45a1ceaa54 gdm: hide session list if only one session
The session list is supposed to hide itself if

1) the user is already logged in
2) there is only one xsession file installed

There was a bug causing 2) not to work.
This commit fixes that bug.

https://bugzilla.gnome.org/show_bug.cgi?id=658423
2011-09-08 10:15:25 -04:00
6496205081 tests: add a unit test for Misc.findUrls()
https://bugzilla.gnome.org/show_bug.cgi?id=636252
2011-09-08 09:09:12 -04:00
e2898bea5c findUrl: be pickier about what can precede a URL
findUrl() was seeing strings like "You have 1 new message in
foo@example.com/Inbox" and finding the URL
"[http://]example.com/Inbox". Require that URLs either start at the
start of the string, or are preceded by whitespace or an open
paren/quote/etc.

(Since JS doesn't have look-behind assertions like perl does, we have
to actually match the URL-preceding character in the regex, and then
adjust the result findUrl returns accordingly.)

https://bugzilla.gnome.org/show_bug.cgi?id=636252
2011-09-08 09:07:03 -04:00
563221698c findUrl: don't match non-:// URLs
Although "x:5" could theoretically be a URL with scheme "x" and path
"5", it probably isn't. Only URLify strings that use the "authority"
syntax ("foo://"). (No one ever types out "mailto:" URLs in ordinary
text, so we don't want to match those either.)

https://bugzilla.gnome.org/show_bug.cgi?id=636252
2011-09-08 09:06:39 -04:00
92a85071bc findUrl: document the URL-matching regex
Explode the regex onto multiple lines, and add comments explaining the
pieces. Also, change ()s to (?:)s (non-capturing groups) where
appropriate, and replace the UTF-8 characters with \u escapes so that
they actually work.

https://bugzilla.gnome.org/show_bug.cgi?id=636252
2011-09-08 09:02:15 -04:00
9ae8d90be4 ShellStack: make this an StWidget
Base ShellStack on StContainer rather than ClutterGroup, so that it
has StWidget-y features (and so we don't have to "cheat" in
shell_stack_allocate()). Implement navigate_focus() to only ever pass
focus into the top-most child, since doing otherwise would be
surprising.

https://bugzilla.gnome.org/show_bug.cgi?id=646934
2011-09-08 08:49:55 -04:00
caade78e79 popupMenu: do height-for-width negotiation
https://bugzilla.gnome.org/show_bug.cgi?id=652837
2011-09-08 08:47:10 -04:00
4f22c61b16 Update Finnish translation. 2011-09-08 14:52:42 +03:00
5e220e9e47 Updated galician translations 2011-09-08 00:15:22 +02:00
857cb9c501 shell-util: Hide week_start string from xgettext
The translation is taken from GTK+, so translations in the gnome-shell
domain are pointless - hide the string, so that it is not extracted
by xgettext.
2011-09-07 23:55:01 +02:00
09fa5d98c2 network-agent: Add missing parameter
_getMobileSecrets() expects the connection type to be passed, so
do that.

https://bugzilla.gnome.org/show_bug.cgi?id=658492
2011-09-07 22:23:53 +02:00
268fe464de Updated Slovenian translation 2011-09-07 20:51:01 +02:00
27095d1a02 Added Oriya language into the list. 2011-09-07 18:54:09 +05:30
dd061fed38 Updated Oriya Translation 2011-09-07 18:52:05 +05:30
7ddaa8968a Bump version to 3.1.91
Update NEWS
2011-09-06 21:59:21 -04:00
cec1557d04 Updated Belarusian translation. 2011-09-07 01:54:05 +03:00
84a49a5eef Updated Persian translation 2011-09-07 01:34:50 +04:30
06ea16bdbf Updated Norwegian bokmål translation 2011-09-06 22:11:17 +02:00
361d38f93b jhbuild moduleset: use glib branch glib-2-30 2011-09-06 15:49:33 -04:00
016e384fa1 lookingGlass: fix to not overlap the keyboard
When the keyboard is configured, make lg shorter (if necessary) to
avoid overlapping it.

Also, make a few simplifications to lg's layout code. In particular,
move it into panelBox, to simplify its interactions with the panel.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
ef57c9ff83 layout: fix keyboard in modal dialogs
Fix the keyboard in modal dialogs (such as the run dialog) by raising
it above the ModalDialog lightbox so you can use it to type.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
627fff967f layout: separate keyboard and tray
The keyboard and tray need to animate together, but they sometimes
need to be in different stacking layers (eg, from the screensaver you
want access to the keyboard, but not the tray). So remove _bottomBox
and just keep trayBox and keyboardBox lined up manually.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
e79c093d80 layout: add chrome actors directly to uiGroup
Rather than having a single chrome layer and putting all of the chrome
into that, put the chrome actors directly into uiGroup, so that they
can be stacked independently of one another relative to other actors.

(This requires making uiGroup a ShellGenericContainer, so we can use
skip_paint to avoid painting non-visibleInFullscreen chrome when we're
in fullscreen.)

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
cbb3831c7b shell-generic-container: document signals
In particular, document that you can ignore the get-preferred-*
signals if and only if you have a fixed width/height specified by some
other means.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
9752fda1f6 keyboard: create and destroy this.actor
Rather than having Main.keyboard.actor always exist, and creating and
destroying only its contents, create and destroy that actor as well.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
d99f08b9c4 layout: fix a few keyboard show/hide bugs
https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
bf0bcaa306 layout: fix initial struts
The struts were being set while the panel was offscreen (starting its
slide-in animation), and then belatedly getting fixed the next time
something else caused a chrome update. Fix this by setting them before
the animation, and freezing them during the animation.

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
a199c1290b main: add back layoutManager.init() call that was accidentally removed
Fixes the chrome to update when entering/leaving the overview again

https://bugzilla.gnome.org/show_bug.cgi?id=657986
2011-09-06 14:33:02 -04:00
28bb0c1fb2 altTab: make thumbnails scroll to right if needed at first Alt+Shift+Above_Tab
Force an allocation at thumbnails creation so we can figure out whether we
need to scroll when selecting.

We also need to show() the whole AltTabPopup before calling _select() so that,
when computing the scrolling offset, the widgets already have their styles
loaded. Otherwise we will miss the switcher list item container's spacing.

https://bugzilla.gnome.org/show_bug.cgi?id=655069
2011-09-06 19:28:51 +01:00
49259b3d19 Updated Spanish translation 2011-09-06 20:04:43 +02:00
a5d0ac7955 user-menu: Rename "Do Not Disturb" to "Notifications"
At least for the foreseeable future, the gnome-session desktop
presence won't be used for anything but suppressing (non-urgent)
notifications. To clarify this behavior, rename the "Do Not Disturb"
switch to "Notifications" (and adjust the switch logic accordingly).

https://bugzilla.gnome.org/show_bug.cgi?id=652718
2011-09-06 17:19:08 +02:00
f326dde09c Updated Japanese translation 2011-09-06 16:32:51 +09:00
3b6d907577 appDisplay: Do not show NoDisplay directories either
https://bugzilla.gnome.org/show_bug.cgi?id=658176
2011-09-05 22:16:02 -04:00
0af108211c apps: Ensure running apps override new .desktop file data
This patch fixes the "apps vanish from alt-TAB bug".

If a "package system" rips away and possibly replaces .desktop files
at some random time, we have historically used inotify to detect this
and reread state (in a racy way, but...).  In GNOME 2, this was
generally not too problematic because the menu widget was totally
separate from the list of windows - and the data they operate on was
disjoint as well.

In GNOME 3 we unify these, and this creates architectural problems
because the windows are tied to the app.

What this patch tries to do is, when rereading the application state,
if we have a running application, we keep that app around instead of
making a new instance.  This ensures we preserve any state such as the
set of open windows.

This requires moving the running state into ShellAppSystem.  Adjust
callers as necessary, and while we're at it drop the unused "contexts"
stuff.

This is just a somewhat quick band-aid; a REAL fix would require us
having low-level control over application installation.  As long as
we're on top of random broken tar+wget wrappers, it will be gross.

A slight future improvement to this patch would add an explicit
"merge" between the old and new data.  I think probably we always keep
around the ShellApp corresponding to a given ID, but replace its
GMenuTreeEntry.

https://bugzilla.gnome.org/show_bug.cgi?id=657990
2011-09-05 17:29:41 -04:00
902e78d910 Updated Danish translation 2011-09-05 23:12:52 +02:00
885e194c25 run-js-test: fix
Needs to explicitly initialize the ShellGlobal now

https://bugzilla.gnome.org/show_bug.cgi?id=649631
2011-09-05 12:23:59 -04:00
d99a2f19a5 Revert "volume: Increase maximum by 50% for outputs with decibel support"
This reverts commit bdd805a3ee.

Conflicts:

	js/ui/status/volume.js

https://bugzilla.gnome.org/show_bug.cgi?id=657607
2011-09-05 11:48:37 +01:00
152a7fd1ef Updated galician translations 2011-09-04 20:01:33 +02:00
6ceb6545ee Updated Belarusian translation. 2011-09-04 19:01:55 +03:00
a167b16860 update PunjabiTranslation 2011-09-04 19:09:33 +05:30
595be5083c overview: Add API to remove search providers
As extensions are now expected to provide a "disable" function,
they need to remove search providers they added. Implement the
removal functionality and add a public removeSearchProvider()
method.

https://bugzilla.gnome.org/show_bug.cgi?id=657548
2011-09-04 13:28:08 +02:00
8b796e745d overview: Add public API to add search providers
Add a addSearchProvider() method, so extensions don't have to access the
view selector directly, which is now a private property of the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=658113
2011-09-04 13:28:08 +02:00
d5314736de updated Tamil translation 2011-09-04 12:00:52 +05:30
a517ab964e Updated Tamil translation 2011-09-04 12:00:52 +05:30
b6c0a2c197 Updated Lithuanian translation 2011-09-04 00:10:59 +03:00
0151c92a92 Added Norwegian bokmål translation 2011-09-03 13:58:46 +02:00
a39440fff5 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-09-03 19:17:06 +08:00
5af7e9f6fe Updated Russian translation 2011-09-03 10:52:34 +04:00
b8d9273a7c messageTray: Don't try to URL highlight an invisible actor
https://bugzilla.gnome.org/show_bug.cgi?id=656142
2011-09-02 17:23:14 -04:00
77c4cbb974 Updated Belarusian translation. 2011-09-02 21:39:24 +03:00
8adc193d73 user-menu: Keep track of current presence
We keep track of presence changes by connecting to the
Tp.AccountManager:most-available-presence-changed signal.
However, if multiple accounts are in use, telepathy may
lie to us and emit the signal even when the most available
presence is unchanged.
Work around this by keeping track of the current presence
ourselves.

https://bugzilla.gnome.org/show_bug.cgi?id=657703
2011-09-02 18:13:09 +02:00
86aa4fe0a9 popup-menu: Allow updating combobox items with scroll wheel
Rather than opening the combobox menu, allow using the scroll wheel
to cycle through the visible items.

https://bugzilla.gnome.org/show_bug.cgi?id=657973
2011-09-02 18:08:54 +02:00
8c9eb6702d Switch default browser to Epiphany
1) This is the official GNOME browser.  The default favorite apps
   are just some random picks, and anyone who wants to
   switch can obviously use patches.
2) mozilla.desktop isn't actually even upstream in Firefox, so this
   devolves to patches Fedora/Ubuntu carry to make one, meaning
   that others have to patch the app list anyways.

https://bugzilla.gnome.org/show_bug.cgi?id=650616
2011-09-02 11:55:44 -04:00
b245ee6212 Fix bus name in error message
Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
2011-09-02 11:54:56 -04:00
98fa71ba18 main: grab the keyboard D-Bus interface at startup
https://bugzilla.gnome.org/show_bug.cgi?id=658065
2011-09-02 11:41:02 -04:00
22dcb46bff [l10n] Updated German translation 2011-09-02 16:55:32 +02:00
3aa904da0a workspacesView: Only connect to nWorkspacesChanged after we've lazily inited
We lazily init this._workspaces, so we shouldn't try to run any code that uses
it until after it's been created.

https://bugzilla.gnome.org/show_bug.cgi?id=658007
2011-09-01 16:25:03 -04:00
794f773620 Updated Spanish translation 2011-09-01 19:41:53 +02:00
bbba77c275 Updated Swedish translation 2011-09-01 16:07:09 +02:00
88f2bbba61 telepathyClient: don't try to translate concatenations of strings
xgettext doesn't recognize it

https://bugzilla.gnome.org/show_bug.cgi?id=657759
2011-09-01 09:20:11 -04:00
cc8d4e4ab3 Added Norwegian bokmål translation 2011-09-01 08:07:11 +02:00
32a11bd8c7 Added Norwegian bokmål translation 2011-09-01 08:07:11 +02:00
55c82a389c Updated galician translations 2011-08-31 22:27:58 +02:00
a1aa58bb64 Bump version to 3.1.90.1
Update NEWS
2011-08-31 11:48:43 -04:00
82ffe233dc Updated Spanish translation 2011-08-30 21:36:47 +02:00
9e16bb85e3 autorun: use the new "media-removable" icon
gnome-icon-theme recently added this icon for removable devices.

https://bugzilla.gnome.org/show_bug.cgi?id=657757
2011-08-30 15:30:10 -04:00
887b41bce3 Updated Spanish translation 2011-08-30 21:24:52 +02:00
63eef286c9 Fixed and updated Russian translation 2011-08-30 20:32:22 +04:00
14e8cba2b1 Add some (element-type) annotations to appease g-i master 2011-08-30 12:07:43 -04:00
3418e6e85e Add support for asynchronous search providers
Some search providers may want to change their results, or may not
want to block on an external service to get their results (DBus, etc.)
Set up an infrastructure to allow search providers to add their search
results at a later time.

Based on a patch by Jasper St. Pierre and Seif Lotfy.

https://bugzilla.gnome.org/show_bug.cgi?id=655220
2011-08-30 11:55:28 -04:00
8f0c980d3c Updated POTFILES.in 2011-08-30 17:39:09 +02:00
c86f3b8d48 build: Make caribou depend on libgee
https://bugzilla.gnome.org/show_bug.cgi?id=657697
2011-08-30 15:14:22 +02:00
8cf6b4c728 don't translate IM status
They are well-known strings defined in the Telepathy spec and so shouldn't be
translated.

https://bugzilla.gnome.org/show_bug.cgi?id=657696
2011-08-30 14:36:02 +02:00
612b9e9faf Fix batch import for loginDialog
Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Signed-off-by: Adel Gadllah <adel.gadllah@gmail.com>
2011-08-30 13:58:02 +02:00
c2c4c26f72 Don't crash displaying contacts with no alias
If a folks individual has no alias we crash when passing in NULL
to strstr(). Fix this by checking for non-null first.
2011-08-30 11:13:35 +02:00
be4d504e27 userMenu: Don't show the default avatar over a newly selected one
When we replace the default avatar image with a real image, we need
to remove the default avatar image.

https://bugzilla.gnome.org/show_bug.cgi?id=657657
2011-08-29 20:12:16 -04:00
138 changed files with 38941 additions and 15770 deletions

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 tests po man
SUBDIRS = data js src browser-plugin tests po man
EXTRA_DIST = \
.project \

170
NEWS
View File

@ -1,3 +1,173 @@
3.2.0
=====
* Prevent the fallback on-screen keyboard from showing up while
GNOME Shell is running [Dan, #659865]
* Disable code to reposition windows around the on-screen keyboard;
it wasn't finished or working properly. [Dan; #659643]
* Fix interaction between on-screen keyboard and notifications
[Dan; #658603]
* Fix menu-sizing problems in right-to-left locales. [Florian; #659827]
* Update chat icons in the message tray when an avatar image changes
[Marina; #659768]
* Fix problem with empty notification bubbles being left [Marina; #659862]
* Fix problem with chat notifications bouncing when new messages come in.
[Marina; #659768]
* Fix bug that was causing SIP calls to automatically be accepted in some
circumstances [Guillaume; #660084]
* Fix string that should have been marked translatable [Frédéric]
* Fix a crash that could happen during CSS transitions [Florian; #659676]
* Build fixes [Colin, Florian]
Contributors:
Guillaume Desmottes, Florian Müllner, Frédéric Péters, Colin Walters,
Dan Winship, Marina Zhurakhinskaya
Translations:
Friedel Wolff [af], Nilamdyuti Goswami [as], Ihar Hrachyshka [be],
Ivaylo Valkov [bg], Gil Forcada [ca], Carles Ferrando [ca@valencia],
Petr Kovar [cz], Mario Blättermann [de], Kris Thomsen [dk],
Tiffany Antopolski, Kristjan Schmidt [eo], Daniel Mustieles [es],
Inaki Larranaga Murgoitio [eu], Tommi Vainikainen [fi], Bruno Brouard [fr],
Fran Dieguez [gl], Yaron Shahrabani [he], Gabor Kelemen [hu],
Andika Triwidada [id], Jiro Matsuzawa [ja], Changwoo Ryu [ko],
Rudolfs Mazurs [lv], Aurimas Černius [lt], Kjartan Maraas [nb],
A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt], Djavan Fagundes,
Rodolfo Ribeiro Gomes, Gabriel F. Vilar [pt_BR], Yuri Myasoedov [ru],
Daniel Nylander [se], Martin Srebotnjak [sl], Michal Štrba [sv],
Krishnababu Krothapalli, Praveen Illa [te], Cheng-Chia Tseng [zh_KH, zh_TW]
3.1.92
======
* Login screen
- Add the ability to set a logo at the top of the user list [Ray; #658062]
- Add fingerprint reader support [Ray; #657823]
- Add a power button offering the choice of Suspend/Restart/Power off
[Ray; #657822]
- Remove the option to view the current keyboad layout [Matthias; #659164]
- Make Control-Alt-Tab work for full keyboard access [Ray; #659177]
* Frequently initiate a full garbage collection; Spidermonkey isn't very good
at tracking the amount of resources we have allocated so this hopefully will
improve memory usage without affecting performance too much [Colin; #659254]
* Stop adding a notification when the network connection is lost
[Colin; #658954]
* When disabling notifications; display a notification
"Your chat status will be set to busy" [Florian; #652718]
* Fix keynav in network dialogs [Florian; #659133]
* Improve calendar styling [Sean; #641135, #651299]
* Shrink padding around panel buttons for narrow screens [Dan; #651299]
* Allow enabling the onscreen keyboard through the accessibility menu
[Dan; #612662]
* Fix problem that was causing VPN secret dialogs to be delayed before showing
[Florian; #658484]
* Make custom-keybindings for the window switcher that don't use alt
work correctly [Florian; #645200]
* Fix duplicate application icons in the Activities Overview [Colin; #659351]
* Bug fixes for dimming windows with attached modal dialogs
[Jasper, Owen; #659302, 659634]
* Add build-time support for BROWSER_PLUGIN_DIR environment variable
[Vincent; #659123]
* Build fixes [Vincent; #659194]
* Code cleanups and test cases
[Adel, Dan, Florian, Jasper; #651299, #658092, #658939]
* Misc bug fixes
[Adel, Colin, Cosimo, Dan, Florian, Giovanni, Jasper, Ray, Xavier;
#651299, #652837, #657249, #658004, #658150, #658239, #658469, #658598,
#658605, #659050, #659159, #659210, #659270, #659370, #659633]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Xavier Claessens, Matthias Clasen,
Rui Matos, Florian Müllner, Jasper St. Pierre, Owen Taylor,
Vincent Untz, Colin Walters, Sean Wilson, Dan Winship
Translations:
Ihar Hrachyshka [be], Alexander Shopov, Ivaylo Valkov [bg],
Mario Blättermann [de], Jorge González, Daniel Mustieles [es],
Arash Mousavi [fa], Ville-Pekka Vainio [fi], Fran Dieguez [gl],
Sweta Kothari [gu], Gabor Kelemen [hu], Jiro Matsuzawa [ja],
Luca Ferretti [it], Rudolfs Mazurs [lv], Kjartan Maraas [nb], A S Alam [pa],
Piotr Drąg [pl], Duarte Loreto [pt], Yuri Myasoedov [ru],
Daniel Nylander [se], Matej Urbančič [sl], Miroslav Nikolić [sr, sr@latin],
Michal Štrba [sv], Tirumurti Vasudevan [ta], Phương Lê Hoàng [vi],
Aron Xu [zh_CN], Chao-Hsiung Liao [zh_HK, zh_TW]
3.1.91.1
========
* Add a browser plugin - this plugin, tied to extensions.gnome.org,
allows users to download and install shell extensions, and enable,
disable, and uninstall extensions they already have installed.
[Jasper; #658070, #658612]
* Improve adding links to URLs in notifications [Dan; #636252]
* Remove "connection lost" notifications after reconnecting [Giovanni; #658049]
* Hide the onscreen keyboard when leaving a text entry [Dan; #658591]
* Fixes for translated strings [Florian; #639987, #644097, #645037]
* Bug fixes for network menu [Florian; #658492]
* Code cleanup [Dan; #646934]
* Build fixes [Javier, Rico]
* Misc bug fixes [Emmanuele, Florian, Jasper, Marina, Matthias, Ray;
#652837, #658423, #658503, #658525, #658562, #658624, #658640, #658983]
Conributors:
Emmanuele Bassi, Giovanni Campagna, Matthias Clasen, Javier Jardón,
Florian Muellner, Jasper St. Pierre, Ray Strode, Rico Tzschichholz,
Dan Winship, Marina Zhurakhinskaya
Translations:
Ihar Hrachyshka [be], Bruce Cowan [en_GB], Jorge González,
Daniel Mustieles [es], Timo Jyrinki [fi], Bruno Brouard, Luc Guillemin,
Claude Paroz, Luc Pionchon [fr], Fran Dieguez [gl], Rajesh Ranjan [hi],
Andika Triwidada [id], Luca Ferretti [it], Changwoo Ryu [ko],
Rudolfs Mazurs [lt], Kjartan Maraas [nb], Manoj Kumar Giri [or],
A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt], Henrique P. Machado,
Gabriel F. Vilar [pt_BR], Daniel Nylander [se], Matej Urbančič [sl],
Tirumurti Vasudevan [ta], Yinghua Wang [zh_CN],
Chao-Hsiung Liao [zh_HK, zh_TW]
3.1.91
======
* Fix problem with applications vanishing from alt-Tab when
desktop files change. [Colin; #657990]
* Fix interaction of on-screen keyboard with run-dialog and
Looking Glass console [Dan; #657986]
* Add public API for adding and removing search providers
[Philippe; #657548, #658113]
* Allow changing IM status with scroll wheel [Florian; #657973]
* Limit volume slider to 100% [Bastien; #657607]
* Change "Do Not Disturb" to "Notifications" in user menu [Florian; #652718]
* Switch browser in default favorites to Epiphany [Colin; #650616]
* Misc bug fixes [Dan, Florian, Jasper, Marc-Antoine, Rui;
#649631, #655069, #656142, #657703, #657759, #658007, #658065, #658176]
Contributors:
Rui Matos, Florian Müllner, Philippe Normand, Marc-Antoine Perennou,
Jasper St. Pierre, Colin Walters, Dan Winship
Translations:
Ihar Hrachyshka [be], Mario Blättermann [de], Kris Thomsen [da],
Jorge González [es], Arash Mousavi [fa], Fran Dieguez [gl],
Takayuki Kusano [ja],Aurimas Černius [lt], Kjartan Maraas [nb], A S Alam [pa],
Stas Solovey [ru], Daniel Nylander [se], Tirumurti Vasudevan [ta],
Chao-Hsiung Liao [zh_HK, zh_TW]
3.1.90.1
========
* Fix typo that was breaking the "Login Screen" mode [Marc-Antoine]
* Fix build with new gobject-introspection [Dan]
* Use a better icon for removable devices [Cosimo; #657757]
* Add support for asynchronous search provides [Philippe, Jasper, Seif; #655220]
* Misc bug fixes [Alex, Guillaume, Jasper; #657657, #657696]
* Misc build fixes [Adel; #657697]
Contributors:
Cosimo Cecchi, Guillaume Desmottes, Adel Gadllah, Alexander Larsson, Seif Lotfy,
Philippe Normand, Marc-Antoine Perennou, Jasper St. Pierre, Dan Winship
Translations:
Jorge González, Daniel Mustieles [es], Stas Solovey [ru]
3.1.90
======
* Add an on-screen keyboard that uses Caribou as a backend

View File

@ -0,0 +1,21 @@
mozillalibdir = $(BROWSER_PLUGIN_DIR)
mozillalib_LTLIBRARIES = libgnome-shell-browser-plugin.la
libgnome_shell_browser_plugin_la_LDFLAGS = -module -avoid-version -no-undefined
libgnome_shell_browser_plugin_la_LIBADD = \
$(BROWSER_PLUGIN_LIBS)
libgnome_shell_browser_plugin_la_SOURCES = \
browser-plugin.c \
npapi/npapi.h \
npapi/npfunctions.h \
npapi/npruntime.h \
npapi/nptypes.h
libgnome_shell_browser_plugin_la_CFLAGS = \
$(BROWSER_PLUGIN_CFLAGS) \
-DG_DISABLE_DEPRECATED \
-DG_LOG_DOMAIN=\"GnomeShellBrowserPlugin\"

17
browser-plugin/README Normal file
View File

@ -0,0 +1,17 @@
The GNOME Shell Browser Plugin provides integration with gnome-shell and the
corresponding extensions repository, codenamed "SweetTooth". The plugin allows
the extensions repository to provide good integration, letting the website
know which extensions are enabled and disabled, and allowing the website to
enable, disable and install them.
Bugs should be reported at http://bugzilla.gnome.org against the 'gnome-shell'
product.
License
=======
The GNOME Shell Browser Plugin, like GNOME Shell itself is distributed under
the GNU General Public License, version 2 or later. The plugin also contains
header files from the "NPAPI SDK" project, tri-licensed under MPL 1.1, GPL 2.0
and LGPL 2.1. These headers are third-party sources and can be retrieved from:
http://code.google.com/p/npapi-sdk/

View File

@ -0,0 +1,824 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2011 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors:
* Jasper St. Pierre <jstpierre@mecheye.net>
* Giovanni Campagna <scampa.giovanni@gmail.com>
*/
#include <string.h>
#define XP_UNIX 1
#include "npapi/npapi.h"
#include "npapi/npruntime.h"
#include "npapi/npfunctions.h"
#include <glib.h>
#include <gio/gio.h>
#include <json-glib/json-glib.h>
#define ORIGIN "extensions.gnome.org"
#define PLUGIN_NAME "Gnome Shell Integration"
#define PLUGIN_DESCRIPTION "This plugin provides integration with Gnome Shell " \
"for live extension enabling and disabling. " \
"It can be used only by extensions.gnome.org"
#define PLUGIN_MIME_STRING "application/x-gnome-shell-integration::Gnome Shell Integration Dummy Content-Type";
#define PLUGIN_API_VERSION 1
typedef struct {
GDBusProxy *proxy;
} PluginData;
/* =============== public entry points =================== */
static NPNetscapeFuncs funcs;
static inline gchar *
get_string_property (NPP instance,
NPObject *obj,
const char *name)
{
NPVariant result = { NPVariantType_Void };
NPString result_str;
gchar *result_copy;
result_copy = NULL;
if (!funcs.getproperty (instance, obj,
funcs.getstringidentifier (name),
&result))
goto out;
if (!NPVARIANT_IS_STRING (result))
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);
out:
funcs.releasevariantvalue (&result);
return result_copy;
}
static gboolean
check_origin_and_protocol (NPP instance)
{
gboolean ret = FALSE;
NPError error;
NPObject *window = NULL;
NPVariant document = { NPVariantType_Void };
NPVariant location = { NPVariantType_Void };
gchar *hostname = NULL;
gchar *protocol = NULL;
error = funcs.getvalue (instance, NPNVWindowNPObject, &window);
if (error != NPERR_NO_ERROR)
goto out;
if (!funcs.getproperty (instance, window,
funcs.getstringidentifier ("document"),
&document))
goto out;
if (!NPVARIANT_IS_OBJECT (document))
goto out;
if (!funcs.getproperty (instance, NPVARIANT_TO_OBJECT (document),
funcs.getstringidentifier ("location"),
&location))
goto out;
if (!NPVARIANT_IS_OBJECT (document))
goto out;
hostname = get_string_property (instance,
NPVARIANT_TO_OBJECT (location),
"hostname");
if (g_strcmp0 (hostname, ORIGIN))
{
g_debug ("origin does not match, is %s",
hostname);
goto out;
}
protocol = get_string_property (instance,
NPVARIANT_TO_OBJECT (location),
"protocol");
if (g_strcmp0 (protocol, "https:") != 0)
{
g_debug ("protocol does not match, is %s",
protocol);
goto out;
}
ret = TRUE;
out:
g_free (protocol);
g_free (hostname);
funcs.releasevariantvalue (&location);
funcs.releasevariantvalue (&document);
if (window != NULL)
funcs.releaseobject (window);
return ret;
}
NPError
NP_Initialize(NPNetscapeFuncs *pfuncs, NPPluginFuncs *plugin)
{
/* global initialization routine, called once when plugin
is loaded */
g_debug ("plugin loaded");
memcpy (&funcs, pfuncs, sizeof (funcs));
plugin->size = sizeof(NPPluginFuncs);
plugin->newp = NPP_New;
plugin->destroy = NPP_Destroy;
plugin->getvalue = NPP_GetValue;
return NPERR_NO_ERROR;
}
NPError
NP_Shutdown(void)
{
return NPERR_NO_ERROR;
}
const char*
NP_GetMIMEDescription(void)
{
return PLUGIN_MIME_STRING;
}
NPError
NP_GetValue(void *instance,
NPPVariable variable,
void *value)
{
switch (variable) {
case NPPVpluginNameString:
*(char**)value = PLUGIN_NAME;
break;
case NPPVpluginDescriptionString:
*(char**)value = PLUGIN_DESCRIPTION;
break;
default:
;
}
return NPERR_NO_ERROR;
}
NPError
NPP_New(NPMIMEType mimetype,
NPP instance,
uint16_t mode,
int16_t argc,
char **argn,
char **argv,
NPSavedData *saved)
{
/* instance initialization function */
PluginData *data;
GError *error = NULL;
g_debug ("plugin created");
if (!check_origin_and_protocol (instance))
return NPERR_GENERIC_ERROR;
data = g_slice_new (PluginData);
instance->pdata = data;
data->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
NULL, /* interface info */
"org.gnome.Shell",
"/org/gnome/Shell",
"org.gnome.Shell",
NULL, /* GCancellable */
&error);
if (!data->proxy)
{
/* ignore error if the shell is not running, otherwise warn */
if (error->domain != G_DBUS_ERROR ||
error->code != G_DBUS_ERROR_NAME_HAS_NO_OWNER)
{
g_warning ("Failed to set up Shell proxy: %s", error->message);
}
g_clear_error (&error);
return NPERR_GENERIC_ERROR;
}
g_debug ("plugin created successfully");
return NPERR_NO_ERROR;
}
NPError
NPP_Destroy(NPP instance,
NPSavedData **saved)
{
/* instance finalization function */
PluginData *data = instance->pdata;
g_debug ("plugin destroyed");
g_object_unref (data->proxy);
g_slice_free (PluginData, data);
return NPERR_NO_ERROR;
}
/* =================== scripting interface =================== */
typedef struct {
NPObject parent;
NPP instance;
GDBusProxy *proxy;
NPObject *listener;
gint signal_id;
} PluginObject;
static void
on_shell_signal (GDBusProxy *proxy,
gchar *sender_name,
gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
PluginObject *obj = user_data;
if (strcmp (signal_name, "ExtensionStatusChanged") == 0)
{
gchar *uuid;
gint32 status;
gchar *error;
NPVariant args[3];
NPVariant result;
g_variant_get (parameters, "(sis)", &uuid, &status, &error);
STRINGZ_TO_NPVARIANT (uuid, args[0]);
INT32_TO_NPVARIANT (status, args[1]);
STRINGZ_TO_NPVARIANT (error, args[2]);
funcs.invokeDefault (obj->instance, obj->listener,
args, 3, &result);
funcs.releasevariantvalue (&result);
g_free (uuid);
g_free (error);
}
}
static NPObject *
plugin_object_allocate (NPP instance,
NPClass *klass)
{
PluginData *data = instance->pdata;
PluginObject *obj = g_slice_new0 (PluginObject);
obj->instance = instance;
obj->proxy = g_object_ref (data->proxy);
obj->signal_id = g_signal_connect (obj->proxy, "g-signal",
G_CALLBACK (on_shell_signal), obj);
g_debug ("plugin object created");
return (NPObject*)obj;
}
static void
plugin_object_deallocate (NPObject *npobj)
{
PluginObject *obj = (PluginObject*)npobj;
g_signal_handler_disconnect (obj->proxy, obj->signal_id);
g_object_unref (obj->proxy);
if (obj->listener)
funcs.releaseobject (obj->listener);
g_debug ("plugin object destroyed");
g_slice_free (PluginObject, obj);
}
static NPIdentifier api_version_id;
static NPIdentifier shell_version_id;
static NPIdentifier get_info_id;
static NPIdentifier list_extensions_id;
static NPIdentifier enable_extension_id;
static NPIdentifier install_extension_id;
static NPIdentifier uninstall_extension_id;
static NPIdentifier onextension_changed_id;
static NPIdentifier get_errors_id;
static bool
plugin_object_has_method (NPObject *npobj,
NPIdentifier name)
{
return (name == get_info_id ||
name == list_extensions_id ||
name == enable_extension_id ||
name == install_extension_id ||
name == uninstall_extension_id ||
name == get_errors_id);
}
static inline gboolean
uuid_is_valid (const gchar *uuid)
{
gsize i;
for (i = 0; uuid[i]; i ++)
{
gchar c = uuid[i];
if (c < 32 || c >= 127)
return FALSE;
switch (c)
{
case '&':
case '<':
case '>':
case '/':
case '\\':
return FALSE;
default:
break;
}
}
return TRUE;
}
static gboolean
jsonify_variant (GVariant *variant,
NPVariant *result)
{
gboolean ret;
GVariant *real_value;
JsonNode *root;
JsonGenerator *generator;
gsize json_length;
gchar *json;
gchar *buffer;
ret = TRUE;
/* DBus methods can return multiple values,
* but we're only interested in the first. */
g_variant_get (variant, "(@*)", &real_value);
root = json_gvariant_serialize (real_value);
generator = json_generator_new ();
json_generator_set_root (generator, root);
json = json_generator_to_data (generator, &json_length);
buffer = funcs.memalloc (json_length + 1);
if (!buffer)
{
ret = FALSE;
goto out;
}
strcpy (buffer, json);
STRINGN_TO_NPVARIANT (buffer, json_length, *result);
out:
g_variant_unref (variant);
g_variant_unref (real_value);
json_node_free (root);
g_free (json);
return ret;
}
static gboolean
plugin_list_extensions (PluginObject *obj,
NPVariant *result)
{
GError *error = NULL;
GVariant *res;
res = g_dbus_proxy_call_sync (obj->proxy,
"ListExtensions",
NULL, /* parameters */
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
&error);
if (!res)
{
g_warning ("Failed to retrieve extension list: %s", error->message);
g_error_free (error);
return FALSE;
}
return jsonify_variant (res, result);
}
static gboolean
plugin_enable_extension (PluginObject *obj,
NPString uuid,
gboolean enabled)
{
const gchar *uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str))
return FALSE;
g_dbus_proxy_call (obj->proxy,
(enabled ? "EnableExtension" : "DisableExtension"),
g_variant_new ("(s)", uuid_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
NULL, /* callback */
NULL /* user_data */);
return TRUE;
}
static gboolean
plugin_install_extension (PluginObject *obj,
NPString uuid,
NPString version_tag)
{
const gchar *uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str))
return FALSE;
g_dbus_proxy_call (obj->proxy,
"InstallRemoteExtension",
g_variant_new ("(ss)",
uuid_str,
version_tag.UTF8Characters),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
NULL, /* callback */
NULL /* user_data */);
return TRUE;
}
static gboolean
plugin_uninstall_extension (PluginObject *obj,
NPString uuid,
NPVariant *result)
{
GError *error = NULL;
GVariant *res;
const gchar *uuid_str;
uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str))
return FALSE;
res = g_dbus_proxy_call_sync (obj->proxy,
"UninstallExtension",
g_variant_new ("(s)",
uuid_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
&error);
if (!res)
{
g_warning ("Failed to uninstall extension: %s", error->message);
g_error_free (error);
return FALSE;
}
return jsonify_variant (res, result);
}
static gboolean
plugin_get_info (PluginObject *obj,
NPString uuid,
NPVariant *result)
{
GError *error = NULL;
GVariant *res;
const gchar *uuid_str;
uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str))
return FALSE;
res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionInfo",
g_variant_new ("(s)", uuid_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
&error);
if (!res)
{
g_warning ("Failed to retrieve extension metadata: %s", error->message);
g_error_free (error);
return FALSE;
}
return jsonify_variant (res, result);
}
static gboolean
plugin_get_errors (PluginObject *obj,
NPString uuid,
NPVariant *result)
{
GError *error = NULL;
GVariant *res;
const gchar *uuid_str;
uuid_str = uuid.UTF8Characters;
if (!uuid_is_valid (uuid_str))
return FALSE;
res = g_dbus_proxy_call_sync (obj->proxy,
"GetExtensionErrors",
g_variant_new ("(s)", uuid_str),
G_DBUS_CALL_FLAGS_NONE,
-1, /* timeout */
NULL, /* cancellable */
&error);
if (!res)
{
g_warning ("Failed to retrieve errors: %s", error->message);
g_error_free (error);
return FALSE;
}
return jsonify_variant (res, result);
}
static int
plugin_get_api_version (PluginObject *obj,
NPVariant *result)
{
INT32_TO_NPVARIANT (PLUGIN_API_VERSION, *result);
return TRUE;
}
static gboolean
plugin_get_shell_version (PluginObject *obj,
NPVariant *result)
{
GVariant *res;
const gchar *version;
gsize length;
gchar *buffer;
gboolean ret;
ret = TRUE;
res = g_dbus_proxy_get_cached_property (obj->proxy,
"ShellVersion");
if (res == NULL)
{
g_warning ("Failed to grab shell version.");
version = "-1";
}
else
{
g_variant_get (res, "&s", &version);
}
length = strlen (version);
buffer = funcs.memalloc (length + 1);
if (!buffer)
{
ret = FALSE;
goto out;
}
strcpy (buffer, version);
STRINGN_TO_NPVARIANT (buffer, length, *result);
out:
g_variant_unref (res);
return ret;
}
static bool
plugin_object_invoke (NPObject *npobj,
NPIdentifier name,
const NPVariant *args,
uint32_t argc,
NPVariant *result)
{
PluginObject *obj;
g_debug ("invoking plugin object method");
obj = (PluginObject*) npobj;
VOID_TO_NPVARIANT (*result);
if (!plugin_object_has_method (npobj, name))
return FALSE;
if (name == list_extensions_id)
return plugin_list_extensions (obj, result);
else if (name == get_info_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_get_info (obj, NPVARIANT_TO_STRING(args[0]), result);
}
else if (name == enable_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
if (!NPVARIANT_IS_BOOLEAN(args[1])) return FALSE;
return plugin_enable_extension (obj,
NPVARIANT_TO_STRING(args[0]),
NPVARIANT_TO_BOOLEAN(args[1]));
}
else if (name == install_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
if (!NPVARIANT_IS_STRING(args[1])) return FALSE;
return plugin_install_extension (obj,
NPVARIANT_TO_STRING(args[0]),
NPVARIANT_TO_STRING(args[1]));
}
else if (name == uninstall_extension_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_uninstall_extension (obj,
NPVARIANT_TO_STRING(args[0]),
result);
}
else if (name == get_errors_id)
{
if (!NPVARIANT_IS_STRING(args[0])) return FALSE;
return plugin_get_errors (obj,
NPVARIANT_TO_STRING(args[0]),
result);
}
return TRUE;
}
static bool
plugin_object_has_property (NPObject *npobj,
NPIdentifier name)
{
return (name == onextension_changed_id ||
name == api_version_id ||
name == shell_version_id);
}
static bool
plugin_object_get_property (NPObject *npobj,
NPIdentifier name,
NPVariant *result)
{
PluginObject *obj;
if (!plugin_object_has_property (npobj, name))
return FALSE;
obj = (PluginObject*) npobj;
if (name == api_version_id)
return plugin_get_api_version (obj, result);
else if (name == shell_version_id)
return plugin_get_shell_version (obj, result);
else if (name == onextension_changed_id)
{
if (obj->listener)
OBJECT_TO_NPVARIANT (obj->listener, *result);
else
NULL_TO_NPVARIANT (*result);
}
return TRUE;
}
static bool
plugin_object_set_property (NPObject *npobj,
NPIdentifier name,
const NPVariant *value)
{
PluginObject *obj;
if (!plugin_object_has_property (npobj, name))
return FALSE;
if (name == onextension_changed_id)
{
obj = (PluginObject*) npobj;
if (obj->listener)
funcs.releaseobject (obj->listener);
obj->listener = NULL;
if (NPVARIANT_IS_OBJECT (*value))
{
obj->listener = NPVARIANT_TO_OBJECT (*value);
funcs.retainobject (obj->listener);
return TRUE;
}
else if (NPVARIANT_IS_NULL (*value))
return TRUE;
}
return FALSE;
}
static NPClass plugin_class = {
NP_CLASS_STRUCT_VERSION,
plugin_object_allocate,
plugin_object_deallocate,
NULL, /* invalidate */
plugin_object_has_method,
plugin_object_invoke,
NULL, /* invoke default */
plugin_object_has_property,
plugin_object_get_property,
plugin_object_set_property,
NULL, /* remove property */
NULL, /* enumerate */
NULL, /* construct */
};
static void
init_methods_and_properties (void)
{
/* this is the JS public API; it is manipulated through NPIdentifiers for speed */
api_version_id = funcs.getstringidentifier ("apiVersion");
shell_version_id = funcs.getstringidentifier ("shellVersion");
get_info_id = funcs.getstringidentifier ("getExtensionInfo");
list_extensions_id = funcs.getstringidentifier ("listExtensions");
enable_extension_id = funcs.getstringidentifier ("setExtensionEnabled");
install_extension_id = funcs.getstringidentifier ("installExtension");
uninstall_extension_id = funcs.getstringidentifier ("uninstallExtension");
get_errors_id = funcs.getstringidentifier ("getExtensionErrors");
onextension_changed_id = funcs.getstringidentifier ("onchange");
}
NPError
NPP_GetValue(NPP instance,
NPPVariable variable,
void *value)
{
g_debug ("NPP_GetValue called");
switch (variable) {
case NPPVpluginScriptableNPObject:
g_debug ("creating scriptable object");
init_methods_and_properties ();
*(NPObject**)value = funcs.createobject (instance, &plugin_class);
break;
default:
;
}
return NPERR_NO_ERROR;
}

View File

@ -0,0 +1,893 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef npapi_h_
#define npapi_h_
#if defined(__OS2__)
#pragma pack(1)
#endif
#include "nptypes.h"
#if defined(__OS2__) || defined(OS2)
#ifndef XP_OS2
#define XP_OS2 1
#endif
#endif
#if defined(_WIN32) && !defined(__SYMBIAN32__)
#include <windef.h>
#ifndef XP_WIN
#define XP_WIN 1
#endif
#endif
#if defined(__SYMBIAN32__)
#ifndef XP_SYMBIAN
#define XP_SYMBIAN 1
#undef XP_WIN
#endif
#endif
#if defined(__APPLE_CC__) && !defined(XP_UNIX)
#ifndef XP_MACOSX
#define XP_MACOSX 1
#endif
#endif
#if defined(XP_MACOSX) && defined(__LP64__)
#define NP_NO_QUICKDRAW
#define NP_NO_CARBON
#endif
#if defined(XP_MACOSX)
#include <ApplicationServices/ApplicationServices.h>
#include <OpenGL/OpenGL.h>
#ifndef NP_NO_CARBON
#include <Carbon/Carbon.h>
#endif
#endif
#if defined(XP_UNIX)
#include <stdio.h>
#if defined(MOZ_X11)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
#endif
#if defined(XP_SYMBIAN)
#include <QEvent>
#include <QRegion>
#endif
/*----------------------------------------------------------------------*/
/* Plugin Version Constants */
/*----------------------------------------------------------------------*/
#define NP_VERSION_MAJOR 0
#define NP_VERSION_MINOR 27
/* The OS/2 version of Netscape uses RC_DATA to define the
mime types, file extensions, etc that are required.
Use a vertical bar to separate types, end types with \0.
FileVersion and ProductVersion are 32bit ints, all other
entries are strings that MUST be terminated with a \0.
AN EXAMPLE:
RCDATA NP_INFO_ProductVersion { 1,0,0,1,}
RCDATA NP_INFO_MIMEType { "video/x-video|",
"video/x-flick\0" }
RCDATA NP_INFO_FileExtents { "avi|",
"flc\0" }
RCDATA NP_INFO_FileOpenName{ "MMOS2 video player(*.avi)|",
"MMOS2 Flc/Fli player(*.flc)\0" }
RCDATA NP_INFO_FileVersion { 1,0,0,1 }
RCDATA NP_INFO_CompanyName { "Netscape Communications\0" }
RCDATA NP_INFO_FileDescription { "NPAVI32 Extension DLL\0"
RCDATA NP_INFO_InternalName { "NPAVI32\0" )
RCDATA NP_INFO_LegalCopyright { "Copyright Netscape Communications \251 1996\0"
RCDATA NP_INFO_OriginalFilename { "NVAPI32.DLL" }
RCDATA NP_INFO_ProductName { "NPAVI32 Dynamic Link Library\0" }
*/
/* RC_DATA types for version info - required */
#define NP_INFO_ProductVersion 1
#define NP_INFO_MIMEType 2
#define NP_INFO_FileOpenName 3
#define NP_INFO_FileExtents 4
/* RC_DATA types for version info - used if found */
#define NP_INFO_FileDescription 5
#define NP_INFO_ProductName 6
/* RC_DATA types for version info - optional */
#define NP_INFO_CompanyName 7
#define NP_INFO_FileVersion 8
#define NP_INFO_InternalName 9
#define NP_INFO_LegalCopyright 10
#define NP_INFO_OriginalFilename 11
#ifndef RC_INVOKED
/*----------------------------------------------------------------------*/
/* Definition of Basic Types */
/*----------------------------------------------------------------------*/
typedef unsigned char NPBool;
typedef int16_t NPError;
typedef int16_t NPReason;
typedef char* NPMIMEType;
/*----------------------------------------------------------------------*/
/* Structures and definitions */
/*----------------------------------------------------------------------*/
#if !defined(__LP64__)
#if defined(XP_MACOSX)
#pragma options align=mac68k
#endif
#endif /* __LP64__ */
/*
* NPP is a plug-in's opaque instance handle
*/
typedef struct _NPP
{
void* pdata; /* plug-in private data */
void* ndata; /* netscape private data */
} NPP_t;
typedef NPP_t* NPP;
typedef struct _NPStream
{
void* pdata; /* plug-in private data */
void* ndata; /* netscape private data */
const char* url;
uint32_t end;
uint32_t lastmodified;
void* notifyData;
const char* headers; /* Response headers from host.
* Exists only for >= NPVERS_HAS_RESPONSE_HEADERS.
* Used for HTTP only; NULL for non-HTTP.
* Available from NPP_NewStream onwards.
* Plugin should copy this data before storing it.
* Includes HTTP status line and all headers,
* preferably verbatim as received from server,
* headers formatted as in HTTP ("Header: Value"),
* and newlines (\n, NOT \r\n) separating lines.
* Terminated by \n\0 (NOT \n\n\0). */
} NPStream;
typedef struct _NPByteRange
{
int32_t offset; /* negative offset means from the end */
uint32_t length;
struct _NPByteRange* next;
} NPByteRange;
typedef struct _NPSavedData
{
int32_t len;
void* buf;
} NPSavedData;
typedef struct _NPRect
{
uint16_t top;
uint16_t left;
uint16_t bottom;
uint16_t right;
} NPRect;
typedef struct _NPSize
{
int32_t width;
int32_t height;
} NPSize;
typedef enum {
NPFocusNext = 0,
NPFocusPrevious = 1
} NPFocusDirection;
/* Return values for NPP_HandleEvent */
#define kNPEventNotHandled 0
#define kNPEventHandled 1
/* Exact meaning must be spec'd in event model. */
#define kNPEventStartIME 2
#if defined(XP_UNIX)
/*
* Unix specific structures and definitions
*/
/*
* Callback Structures.
*
* These are used to pass additional platform specific information.
*/
enum {
NP_SETWINDOW = 1,
NP_PRINT
};
typedef struct
{
int32_t type;
} NPAnyCallbackStruct;
typedef struct
{
int32_t type;
#if defined(MOZ_X11)
Display* display;
Visual* visual;
Colormap colormap;
unsigned int depth;
#endif
} NPSetWindowCallbackStruct;
typedef struct
{
int32_t type;
FILE* fp;
} NPPrintCallbackStruct;
#endif /* XP_UNIX */
#if defined(XP_MACOSX)
typedef enum {
#ifndef NP_NO_QUICKDRAW
NPDrawingModelQuickDraw = 0,
#endif
NPDrawingModelCoreGraphics = 1,
NPDrawingModelOpenGL = 2,
NPDrawingModelCoreAnimation = 3,
NPDrawingModelInvalidatingCoreAnimation = 4
} NPDrawingModel;
typedef enum {
#ifndef NP_NO_CARBON
NPEventModelCarbon = 0,
#endif
NPEventModelCocoa = 1
} NPEventModel;
#endif
/*
* The following masks are applied on certain platforms to NPNV and
* NPPV selectors that pass around pointers to COM interfaces. Newer
* compilers on some platforms may generate vtables that are not
* compatible with older compilers. To prevent older plugins from
* not understanding a new browser's ABI, these masks change the
* values of those selectors on those platforms. To remain backwards
* compatible with different versions of the browser, plugins can
* use these masks to dynamically determine and use the correct C++
* ABI that the browser is expecting. This does not apply to Windows
* as Microsoft's COM ABI will likely not change.
*/
#define NP_ABI_GCC3_MASK 0x10000000
/*
* gcc 3.x generated vtables on UNIX and OSX are incompatible with
* previous compilers.
*/
#if (defined(XP_UNIX) && defined(__GNUC__) && (__GNUC__ >= 3))
#define _NP_ABI_MIXIN_FOR_GCC3 NP_ABI_GCC3_MASK
#else
#define _NP_ABI_MIXIN_FOR_GCC3 0
#endif
#if defined(XP_MACOSX)
#define NP_ABI_MACHO_MASK 0x01000000
#define _NP_ABI_MIXIN_FOR_MACHO NP_ABI_MACHO_MASK
#else
#define _NP_ABI_MIXIN_FOR_MACHO 0
#endif
#define NP_ABI_MASK (_NP_ABI_MIXIN_FOR_GCC3 | _NP_ABI_MIXIN_FOR_MACHO)
/*
* List of variable names for which NPP_GetValue shall be implemented
*/
typedef enum {
NPPVpluginNameString = 1,
NPPVpluginDescriptionString,
NPPVpluginWindowBool,
NPPVpluginTransparentBool,
NPPVjavaClass,
NPPVpluginWindowSize,
NPPVpluginTimerInterval,
NPPVpluginScriptableInstance = (10 | NP_ABI_MASK),
NPPVpluginScriptableIID = 11,
NPPVjavascriptPushCallerBool = 12,
NPPVpluginKeepLibraryInMemory = 13,
NPPVpluginNeedsXEmbed = 14,
/* Get the NPObject for scripting the plugin. Introduced in NPAPI minor version 14.
*/
NPPVpluginScriptableNPObject = 15,
/* Get the plugin value (as \0-terminated UTF-8 string data) for
* form submission if the plugin is part of a form. Use
* NPN_MemAlloc() to allocate memory for the string data. Introduced
* in NPAPI minor version 15.
*/
NPPVformValue = 16,
NPPVpluginUrlRequestsDisplayedBool = 17,
/* Checks if the plugin is interested in receiving the http body of
* all http requests (including failed ones, http status != 200).
*/
NPPVpluginWantsAllNetworkStreams = 18,
/* Browsers can retrieve a native ATK accessibility plug ID via this variable. */
NPPVpluginNativeAccessibleAtkPlugId = 19,
/* Checks to see if the plug-in would like the browser to load the "src" attribute. */
NPPVpluginCancelSrcStream = 20,
NPPVsupportsAdvancedKeyHandling = 21,
NPPVpluginUsesDOMForCursorBool = 22
#if defined(XP_MACOSX)
/* Used for negotiating drawing models */
, NPPVpluginDrawingModel = 1000
/* Used for negotiating event models */
, NPPVpluginEventModel = 1001
/* In the NPDrawingModelCoreAnimation drawing model, the browser asks the plug-in for a Core Animation layer. */
, NPPVpluginCoreAnimationLayer = 1003
#endif
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
, NPPVpluginWindowlessLocalBool = 2002
#endif
} NPPVariable;
/*
* List of variable names for which NPN_GetValue should be implemented.
*/
typedef enum {
NPNVxDisplay = 1,
NPNVxtAppContext,
NPNVnetscapeWindow,
NPNVjavascriptEnabledBool,
NPNVasdEnabledBool,
NPNVisOfflineBool,
NPNVserviceManager = (10 | NP_ABI_MASK),
NPNVDOMElement = (11 | NP_ABI_MASK),
NPNVDOMWindow = (12 | NP_ABI_MASK),
NPNVToolkit = (13 | NP_ABI_MASK),
NPNVSupportsXEmbedBool = 14,
/* Get the NPObject wrapper for the browser window. */
NPNVWindowNPObject = 15,
/* Get the NPObject wrapper for the plugins DOM element. */
NPNVPluginElementNPObject = 16,
NPNVSupportsWindowless = 17,
NPNVprivateModeBool = 18,
NPNVsupportsAdvancedKeyHandling = 21
#if defined(XP_MACOSX)
/* Used for negotiating drawing models */
, NPNVpluginDrawingModel = 1000
#ifndef NP_NO_QUICKDRAW
, NPNVsupportsQuickDrawBool = 2000
#endif
, NPNVsupportsCoreGraphicsBool = 2001
, NPNVsupportsOpenGLBool = 2002
, NPNVsupportsCoreAnimationBool = 2003
, NPNVsupportsInvalidatingCoreAnimationBool = 2004
#ifndef NP_NO_CARBON
, NPNVsupportsCarbonBool = 3000 /* TRUE if the browser supports the Carbon event model */
#endif
, NPNVsupportsCocoaBool = 3001 /* TRUE if the browser supports the Cocoa event model */
, NPNVsupportsUpdatedCocoaTextInputBool = 3002 /* TRUE if the browser supports the updated
Cocoa text input specification. */
, NPNVsupportsCompositingCoreAnimationPluginsBool = 74656 /* TRUE if the browser supports
CA model compositing */
#endif
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
, NPNVSupportsWindowlessLocal = 2002
#endif
} NPNVariable;
typedef enum {
NPNURLVCookie = 501,
NPNURLVProxy
} NPNURLVariable;
/*
* The type of Toolkit the widgets use
*/
typedef enum {
NPNVGtk12 = 1,
NPNVGtk2
} NPNToolkitType;
/*
* The type of a NPWindow - it specifies the type of the data structure
* returned in the window field.
*/
typedef enum {
NPWindowTypeWindow = 1,
NPWindowTypeDrawable
} NPWindowType;
typedef struct _NPWindow
{
void* window; /* Platform specific window handle */
/* OS/2: x - Position of bottom left corner */
/* OS/2: y - relative to visible netscape window */
int32_t x; /* Position of top left corner relative */
int32_t y; /* to a netscape page. */
uint32_t width; /* Maximum window size */
uint32_t height;
NPRect clipRect; /* Clipping rectangle in port coordinates */
#if (defined(XP_UNIX) || defined(XP_SYMBIAN)) && !defined(XP_MACOSX)
void * ws_info; /* Platform-dependent additional data */
#endif /* XP_UNIX */
NPWindowType type; /* Is this a window or a drawable? */
} NPWindow;
typedef struct _NPImageExpose
{
char* data; /* image pointer */
int32_t stride; /* Stride of data image pointer */
int32_t depth; /* Depth of image pointer */
int32_t x; /* Expose x */
int32_t y; /* Expose y */
uint32_t width; /* Expose width */
uint32_t height; /* Expose height */
NPSize dataSize; /* Data buffer size */
float translateX; /* translate X matrix value */
float translateY; /* translate Y matrix value */
float scaleX; /* scale X matrix value */
float scaleY; /* scale Y matrix value */
} NPImageExpose;
typedef struct _NPFullPrint
{
NPBool pluginPrinted;/* Set TRUE if plugin handled fullscreen printing */
NPBool printOne; /* TRUE if plugin should print one copy to default
printer */
void* platformPrint; /* Platform-specific printing info */
} NPFullPrint;
typedef struct _NPEmbedPrint
{
NPWindow window;
void* platformPrint; /* Platform-specific printing info */
} NPEmbedPrint;
typedef struct _NPPrint
{
uint16_t mode; /* NP_FULL or NP_EMBED */
union
{
NPFullPrint fullPrint; /* if mode is NP_FULL */
NPEmbedPrint embedPrint; /* if mode is NP_EMBED */
} print;
} NPPrint;
#if defined(XP_MACOSX)
#ifndef NP_NO_CARBON
typedef EventRecord NPEvent;
#endif
#elif defined(XP_SYMBIAN)
typedef QEvent NPEvent;
#elif defined(XP_WIN)
typedef struct _NPEvent
{
uint16_t event;
uintptr_t wParam;
uintptr_t lParam;
} NPEvent;
#elif defined(XP_OS2)
typedef struct _NPEvent
{
uint32_t event;
uint32_t wParam;
uint32_t lParam;
} NPEvent;
#elif defined(XP_UNIX) && defined(MOZ_X11)
typedef XEvent NPEvent;
#else
typedef void* NPEvent;
#endif
#if defined(XP_MACOSX)
typedef void* NPRegion;
#ifndef NP_NO_QUICKDRAW
typedef RgnHandle NPQDRegion;
#endif
typedef CGPathRef NPCGRegion;
#elif defined(XP_WIN)
typedef HRGN NPRegion;
#elif defined(XP_UNIX) && defined(MOZ_X11)
typedef Region NPRegion;
#elif defined(XP_SYMBIAN)
typedef QRegion* NPRegion;
#else
typedef void *NPRegion;
#endif
typedef struct _NPNSString NPNSString;
typedef struct _NPNSWindow NPNSWindow;
typedef struct _NPNSMenu NPNSMenu;
#if defined(XP_MACOSX)
typedef NPNSMenu NPMenu;
#else
typedef void *NPMenu;
#endif
typedef enum {
NPCoordinateSpacePlugin = 1,
NPCoordinateSpaceWindow,
NPCoordinateSpaceFlippedWindow,
NPCoordinateSpaceScreen,
NPCoordinateSpaceFlippedScreen
} NPCoordinateSpace;
#if defined(XP_MACOSX)
#ifndef NP_NO_QUICKDRAW
typedef struct NP_Port
{
CGrafPtr port;
int32_t portx; /* position inside the topmost window */
int32_t porty;
} NP_Port;
#endif /* NP_NO_QUICKDRAW */
/*
* NP_CGContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelCoreGraphics
* as its drawing model.
*/
typedef struct NP_CGContext
{
CGContextRef context;
void *window; /* A WindowRef under the Carbon event model. */
} NP_CGContext;
/*
* NP_GLContext is the type of the NPWindow's 'window' when the plugin specifies NPDrawingModelOpenGL as its
* drawing model.
*/
typedef struct NP_GLContext
{
CGLContextObj context;
#ifdef NP_NO_CARBON
NPNSWindow *window;
#else
void *window; /* Can be either an NSWindow or a WindowRef depending on the event model */
#endif
} NP_GLContext;
typedef enum {
NPCocoaEventDrawRect = 1,
NPCocoaEventMouseDown,
NPCocoaEventMouseUp,
NPCocoaEventMouseMoved,
NPCocoaEventMouseEntered,
NPCocoaEventMouseExited,
NPCocoaEventMouseDragged,
NPCocoaEventKeyDown,
NPCocoaEventKeyUp,
NPCocoaEventFlagsChanged,
NPCocoaEventFocusChanged,
NPCocoaEventWindowFocusChanged,
NPCocoaEventScrollWheel,
NPCocoaEventTextInput
} NPCocoaEventType;
typedef struct _NPCocoaEvent {
NPCocoaEventType type;
uint32_t version;
union {
struct {
uint32_t modifierFlags;
double pluginX;
double pluginY;
int32_t buttonNumber;
int32_t clickCount;
double deltaX;
double deltaY;
double deltaZ;
} mouse;
struct {
uint32_t modifierFlags;
NPNSString *characters;
NPNSString *charactersIgnoringModifiers;
NPBool isARepeat;
uint16_t keyCode;
} key;
struct {
CGContextRef context;
double x;
double y;
double width;
double height;
} draw;
struct {
NPBool hasFocus;
} focus;
struct {
NPNSString *text;
} text;
} data;
} NPCocoaEvent;
#ifndef NP_NO_CARBON
/* Non-standard event types that can be passed to HandleEvent */
enum NPEventType {
NPEventType_GetFocusEvent = (osEvt + 16),
NPEventType_LoseFocusEvent,
NPEventType_AdjustCursorEvent,
NPEventType_MenuCommandEvent,
NPEventType_ClippingChangedEvent,
NPEventType_ScrollingBeginsEvent = 1000,
NPEventType_ScrollingEndsEvent
};
#endif /* NP_NO_CARBON */
#endif /* XP_MACOSX */
/*
* Values for mode passed to NPP_New:
*/
#define NP_EMBED 1
#define NP_FULL 2
/*
* Values for stream type passed to NPP_NewStream:
*/
#define NP_NORMAL 1
#define NP_SEEK 2
#define NP_ASFILE 3
#define NP_ASFILEONLY 4
#define NP_MAXREADY (((unsigned)(~0)<<1)>>1)
/*
* Flags for NPP_ClearSiteData.
*/
#define NP_CLEAR_ALL 0
#define NP_CLEAR_CACHE (1 << 0)
#if !defined(__LP64__)
#if defined(XP_MACOSX)
#pragma options align=reset
#endif
#endif /* __LP64__ */
/*----------------------------------------------------------------------*/
/* Error and Reason Code definitions */
/*----------------------------------------------------------------------*/
/*
* Values of type NPError:
*/
#define NPERR_BASE 0
#define NPERR_NO_ERROR (NPERR_BASE + 0)
#define NPERR_GENERIC_ERROR (NPERR_BASE + 1)
#define NPERR_INVALID_INSTANCE_ERROR (NPERR_BASE + 2)
#define NPERR_INVALID_FUNCTABLE_ERROR (NPERR_BASE + 3)
#define NPERR_MODULE_LOAD_FAILED_ERROR (NPERR_BASE + 4)
#define NPERR_OUT_OF_MEMORY_ERROR (NPERR_BASE + 5)
#define NPERR_INVALID_PLUGIN_ERROR (NPERR_BASE + 6)
#define NPERR_INVALID_PLUGIN_DIR_ERROR (NPERR_BASE + 7)
#define NPERR_INCOMPATIBLE_VERSION_ERROR (NPERR_BASE + 8)
#define NPERR_INVALID_PARAM (NPERR_BASE + 9)
#define NPERR_INVALID_URL (NPERR_BASE + 10)
#define NPERR_FILE_NOT_FOUND (NPERR_BASE + 11)
#define NPERR_NO_DATA (NPERR_BASE + 12)
#define NPERR_STREAM_NOT_SEEKABLE (NPERR_BASE + 13)
#define NPERR_TIME_RANGE_NOT_SUPPORTED (NPERR_BASE + 14)
#define NPERR_MALFORMED_SITE (NPERR_BASE + 15)
/*
* Values of type NPReason:
*/
#define NPRES_BASE 0
#define NPRES_DONE (NPRES_BASE + 0)
#define NPRES_NETWORK_ERR (NPRES_BASE + 1)
#define NPRES_USER_BREAK (NPRES_BASE + 2)
/*
* Don't use these obsolete error codes any more.
*/
#define NP_NOERR NP_NOERR_is_obsolete_use_NPERR_NO_ERROR
#define NP_EINVAL NP_EINVAL_is_obsolete_use_NPERR_GENERIC_ERROR
#define NP_EABORT NP_EABORT_is_obsolete_use_NPRES_USER_BREAK
/*
* Version feature information
*/
#define NPVERS_HAS_STREAMOUTPUT 8
#define NPVERS_HAS_NOTIFICATION 9
#define NPVERS_HAS_LIVECONNECT 9
#define NPVERS_68K_HAS_LIVECONNECT 11
#define NPVERS_HAS_WINDOWLESS 11
#define NPVERS_HAS_XPCONNECT_SCRIPTING 13
#define NPVERS_HAS_NPRUNTIME_SCRIPTING 14
#define NPVERS_HAS_FORM_VALUES 15
#define NPVERS_HAS_POPUPS_ENABLED_STATE 16
#define NPVERS_HAS_RESPONSE_HEADERS 17
#define NPVERS_HAS_NPOBJECT_ENUM 18
#define NPVERS_HAS_PLUGIN_THREAD_ASYNC_CALL 19
#define NPVERS_HAS_ALL_NETWORK_STREAMS 20
#define NPVERS_HAS_URL_AND_AUTH_INFO 21
#define NPVERS_HAS_PRIVATE_MODE 22
#define NPVERS_MACOSX_HAS_COCOA_EVENTS 23
#define NPVERS_HAS_ADVANCED_KEY_HANDLING 25
#define NPVERS_HAS_URL_REDIRECT_HANDLING 26
#define NPVERS_HAS_CLEAR_SITE_DATA 27
/*----------------------------------------------------------------------*/
/* Function Prototypes */
/*----------------------------------------------------------------------*/
#if defined(__OS2__)
#define NP_LOADDS _System
#else
#define NP_LOADDS
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* NPP_* functions are provided by the plugin and called by the navigator. */
#if defined(XP_UNIX)
const char* NPP_GetMIMEDescription(void);
#endif
NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance,
uint16_t mode, int16_t argc, char* argn[],
char* argv[], NPSavedData* saved);
NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save);
NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window);
NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type,
NPStream* stream, NPBool seekable,
uint16_t* stype);
NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream,
NPReason reason);
int32_t NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream);
int32_t NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32_t offset,
int32_t len, void* buffer);
void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream,
const char* fname);
void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint);
int16_t NP_LOADDS NPP_HandleEvent(NPP instance, void* event);
void NP_LOADDS NPP_URLNotify(NPP instance, const char* url,
NPReason reason, void* notifyData);
NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value);
NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value);
NPBool NP_LOADDS NPP_GotFocus(NPP instance, NPFocusDirection direction);
void NP_LOADDS NPP_LostFocus(NPP instance);
void NP_LOADDS NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData);
NPError NP_LOADDS NPP_ClearSiteData(const char* site, uint64_t flags, uint64_t maxAge);
char** NP_LOADDS NPP_GetSitesWithData(void);
/* NPN_* functions are provided by the navigator and called by the plugin. */
void NP_LOADDS NPN_Version(int* plugin_major, int* plugin_minor,
int* netscape_major, int* netscape_minor);
NPError NP_LOADDS NPN_GetURLNotify(NPP instance, const char* url,
const char* target, void* notifyData);
NPError NP_LOADDS NPN_GetURL(NPP instance, const char* url,
const char* target);
NPError NP_LOADDS NPN_PostURLNotify(NPP instance, const char* url,
const char* target, uint32_t len,
const char* buf, NPBool file,
void* notifyData);
NPError NP_LOADDS NPN_PostURL(NPP instance, const char* url,
const char* target, uint32_t len,
const char* buf, NPBool file);
NPError NP_LOADDS NPN_RequestRead(NPStream* stream, NPByteRange* rangeList);
NPError NP_LOADDS NPN_NewStream(NPP instance, NPMIMEType type,
const char* target, NPStream** stream);
int32_t NP_LOADDS NPN_Write(NPP instance, NPStream* stream, int32_t len,
void* buffer);
NPError NP_LOADDS NPN_DestroyStream(NPP instance, NPStream* stream,
NPReason reason);
void NP_LOADDS NPN_Status(NPP instance, const char* message);
const char* NP_LOADDS NPN_UserAgent(NPP instance);
void* NP_LOADDS NPN_MemAlloc(uint32_t size);
void NP_LOADDS NPN_MemFree(void* ptr);
uint32_t NP_LOADDS NPN_MemFlush(uint32_t size);
void NP_LOADDS NPN_ReloadPlugins(NPBool reloadPages);
NPError NP_LOADDS NPN_GetValue(NPP instance, NPNVariable variable,
void *value);
NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable,
void *value);
void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect);
void NP_LOADDS NPN_InvalidateRegion(NPP instance,
NPRegion invalidRegion);
void NP_LOADDS NPN_ForceRedraw(NPP instance);
void NP_LOADDS NPN_PushPopupsEnabledState(NPP instance, NPBool enabled);
void NP_LOADDS NPN_PopPopupsEnabledState(NPP instance);
void NP_LOADDS NPN_PluginThreadAsyncCall(NPP instance,
void (*func) (void *),
void *userData);
NPError NP_LOADDS NPN_GetValueForURL(NPP instance, NPNURLVariable variable,
const char *url, char **value,
uint32_t *len);
NPError NP_LOADDS NPN_SetValueForURL(NPP instance, NPNURLVariable variable,
const char *url, const char *value,
uint32_t len);
NPError NP_LOADDS NPN_GetAuthenticationInfo(NPP instance,
const char *protocol,
const char *host, int32_t port,
const char *scheme,
const char *realm,
char **username, uint32_t *ulen,
char **password,
uint32_t *plen);
uint32_t NP_LOADDS NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
void NP_LOADDS NPN_UnscheduleTimer(NPP instance, uint32_t timerID);
NPError NP_LOADDS NPN_PopUpContextMenu(NPP instance, NPMenu* menu);
NPBool NP_LOADDS NPN_ConvertPoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
NPBool NP_LOADDS NPN_HandleEvent(NPP instance, void *event, NPBool handled);
NPBool NP_LOADDS NPN_UnfocusInstance(NPP instance, NPFocusDirection direction);
void NP_LOADDS NPN_URLRedirectResponse(NPP instance, void* notifyData, NPBool allow);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* RC_INVOKED */
#if defined(__OS2__)
#pragma pack()
#endif
#endif /* npapi_h_ */

View File

@ -0,0 +1,322 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef npfunctions_h_
#define npfunctions_h_
#ifdef __OS2__
#pragma pack(1)
#define NP_LOADDS _System
#else
#define NP_LOADDS
#endif
#include "npapi.h"
#include "npruntime.h"
typedef NPError (* NP_LOADDS NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
typedef NPError (* NP_LOADDS NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
typedef NPError (* NP_LOADDS NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
typedef NPError (* NP_LOADDS NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype);
typedef NPError (* NP_LOADDS NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
typedef int32_t (* NP_LOADDS NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
typedef int32_t (* NP_LOADDS NPP_WriteProcPtr)(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
typedef void (* NP_LOADDS NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream, const char* fname);
typedef void (* NP_LOADDS NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
typedef int16_t (* NP_LOADDS NPP_HandleEventProcPtr)(NPP instance, void* event);
typedef void (* NP_LOADDS NPP_URLNotifyProcPtr)(NPP instance, const char* url, NPReason reason, void* notifyData);
/* Any NPObjects returned to the browser via NPP_GetValue should be retained
by the plugin on the way out. The browser is responsible for releasing. */
typedef NPError (* NP_LOADDS NPP_GetValueProcPtr)(NPP instance, NPPVariable variable, void *ret_value);
typedef NPError (* NP_LOADDS NPP_SetValueProcPtr)(NPP instance, NPNVariable variable, void *value);
typedef NPBool (* NP_LOADDS NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction);
typedef void (* NP_LOADDS NPP_LostFocusPtr)(NPP instance);
typedef void (* NP_LOADDS NPP_URLRedirectNotifyPtr)(NPP instance, const char* url, int32_t status, void* notifyData);
typedef NPError (* NP_LOADDS NPP_ClearSiteDataPtr)(const char* site, uint64_t flags, uint64_t maxAge);
typedef char** (* NP_LOADDS NPP_GetSitesWithDataPtr)(void);
typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable, void *ret_value);
typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable, void *value);
typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* url, const char* window, void* notifyData);
typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData);
typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* url, const char* window);
typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file);
typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream, NPByteRange* rangeList);
typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type, const char* window, NPStream** stream);
typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len, void* buffer);
typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream, NPReason reason);
typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message);
/* Browser manages the lifetime of the buffer returned by NPN_UserAgent, don't
depend on it sticking around and don't free it. */
typedef const char* (*NPN_UserAgentProcPtr)(NPP instance);
typedef void* (*NPN_MemAllocProcPtr)(uint32_t size);
typedef void (*NPN_MemFreeProcPtr)(void* ptr);
typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size);
typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
typedef void* (*NPN_GetJavaEnvProcPtr)(void);
typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance);
typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect *rect);
typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
typedef void (*NPN_ForceRedrawProcPtr)(NPP instance);
typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr)(const NPUTF8* name);
typedef void (*NPN_GetStringIdentifiersProcPtr)(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers);
typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr)(int32_t intid);
typedef bool (*NPN_IdentifierIsStringProcPtr)(NPIdentifier identifier);
typedef NPUTF8* (*NPN_UTF8FromIdentifierProcPtr)(NPIdentifier identifier);
typedef int32_t (*NPN_IntFromIdentifierProcPtr)(NPIdentifier identifier);
typedef NPObject* (*NPN_CreateObjectProcPtr)(NPP npp, NPClass *aClass);
typedef NPObject* (*NPN_RetainObjectProcPtr)(NPObject *obj);
typedef void (*NPN_ReleaseObjectProcPtr)(NPObject *obj);
typedef bool (*NPN_InvokeProcPtr)(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
typedef bool (*NPN_InvokeDefaultProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
typedef bool (*NPN_EvaluateProcPtr)(NPP npp, NPObject *obj, NPString *script, NPVariant *result);
typedef bool (*NPN_GetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result);
typedef bool (*NPN_SetPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value);
typedef bool (*NPN_RemovePropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
typedef bool (*NPN_HasPropertyProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
typedef bool (*NPN_HasMethodProcPtr)(NPP npp, NPObject *obj, NPIdentifier propertyName);
typedef void (*NPN_ReleaseVariantValueProcPtr)(NPVariant *variant);
typedef void (*NPN_SetExceptionProcPtr)(NPObject *obj, const NPUTF8 *message);
typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp, NPBool enabled);
typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp);
typedef bool (*NPN_EnumerateProcPtr)(NPP npp, NPObject *obj, NPIdentifier **identifier, uint32_t *count);
typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance, void (*func)(void *), void *userData);
typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
typedef NPError (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, char **value, uint32_t *len);
typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable, const char *url, const char *value, uint32_t len);
typedef NPError (*NPN_GetAuthenticationInfoPtr)(NPP npp, const char *protocol, const char *host, int32_t port, const char *scheme, const char *realm, char **username, uint32_t *ulen, char **password, uint32_t *plen);
typedef uint32_t (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID));
typedef void (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID);
typedef NPError (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu);
typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void *event, NPBool handled);
typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance, NPFocusDirection direction);
typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData, NPBool allow);
typedef struct _NPPluginFuncs {
uint16_t size;
uint16_t version;
NPP_NewProcPtr newp;
NPP_DestroyProcPtr destroy;
NPP_SetWindowProcPtr setwindow;
NPP_NewStreamProcPtr newstream;
NPP_DestroyStreamProcPtr destroystream;
NPP_StreamAsFileProcPtr asfile;
NPP_WriteReadyProcPtr writeready;
NPP_WriteProcPtr write;
NPP_PrintProcPtr print;
NPP_HandleEventProcPtr event;
NPP_URLNotifyProcPtr urlnotify;
void* javaClass;
NPP_GetValueProcPtr getvalue;
NPP_SetValueProcPtr setvalue;
NPP_GotFocusPtr gotfocus;
NPP_LostFocusPtr lostfocus;
NPP_URLRedirectNotifyPtr urlredirectnotify;
NPP_ClearSiteDataPtr clearsitedata;
NPP_GetSitesWithDataPtr getsiteswithdata;
} NPPluginFuncs;
typedef struct _NPNetscapeFuncs {
uint16_t size;
uint16_t version;
NPN_GetURLProcPtr geturl;
NPN_PostURLProcPtr posturl;
NPN_RequestReadProcPtr requestread;
NPN_NewStreamProcPtr newstream;
NPN_WriteProcPtr write;
NPN_DestroyStreamProcPtr destroystream;
NPN_StatusProcPtr status;
NPN_UserAgentProcPtr uagent;
NPN_MemAllocProcPtr memalloc;
NPN_MemFreeProcPtr memfree;
NPN_MemFlushProcPtr memflush;
NPN_ReloadPluginsProcPtr reloadplugins;
NPN_GetJavaEnvProcPtr getJavaEnv;
NPN_GetJavaPeerProcPtr getJavaPeer;
NPN_GetURLNotifyProcPtr geturlnotify;
NPN_PostURLNotifyProcPtr posturlnotify;
NPN_GetValueProcPtr getvalue;
NPN_SetValueProcPtr setvalue;
NPN_InvalidateRectProcPtr invalidaterect;
NPN_InvalidateRegionProcPtr invalidateregion;
NPN_ForceRedrawProcPtr forceredraw;
NPN_GetStringIdentifierProcPtr getstringidentifier;
NPN_GetStringIdentifiersProcPtr getstringidentifiers;
NPN_GetIntIdentifierProcPtr getintidentifier;
NPN_IdentifierIsStringProcPtr identifierisstring;
NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
NPN_IntFromIdentifierProcPtr intfromidentifier;
NPN_CreateObjectProcPtr createobject;
NPN_RetainObjectProcPtr retainobject;
NPN_ReleaseObjectProcPtr releaseobject;
NPN_InvokeProcPtr invoke;
NPN_InvokeDefaultProcPtr invokeDefault;
NPN_EvaluateProcPtr evaluate;
NPN_GetPropertyProcPtr getproperty;
NPN_SetPropertyProcPtr setproperty;
NPN_RemovePropertyProcPtr removeproperty;
NPN_HasPropertyProcPtr hasproperty;
NPN_HasMethodProcPtr hasmethod;
NPN_ReleaseVariantValueProcPtr releasevariantvalue;
NPN_SetExceptionProcPtr setexception;
NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
NPN_EnumerateProcPtr enumerate;
NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
NPN_ConstructProcPtr construct;
NPN_GetValueForURLPtr getvalueforurl;
NPN_SetValueForURLPtr setvalueforurl;
NPN_GetAuthenticationInfoPtr getauthenticationinfo;
NPN_ScheduleTimerPtr scheduletimer;
NPN_UnscheduleTimerPtr unscheduletimer;
NPN_PopUpContextMenuPtr popupcontextmenu;
NPN_ConvertPointPtr convertpoint;
NPN_HandleEventPtr handleevent;
NPN_UnfocusInstancePtr unfocusinstance;
NPN_URLRedirectResponsePtr urlredirectresponse;
} NPNetscapeFuncs;
#ifdef XP_MACOSX
/*
* Mac OS X version(s) of NP_GetMIMEDescription(const char *)
* These can be called to retreive MIME information from the plugin dynamically
*
* Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way
* to get mime info from the plugin only on OSX and may not be supported
* in furture version -- use NP_GetMIMEDescription instead
*/
enum
{
kBPSupportedMIMETypesStructVers_1 = 1
};
typedef struct _BPSupportedMIMETypes
{
SInt32 structVersion; /* struct version */
Handle typeStrings; /* STR# formated handle, allocated by plug-in */
Handle infoStrings; /* STR# formated handle, allocated by plug-in */
} BPSupportedMIMETypes;
OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes *mimeInfo, UInt32 flags);
#define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription"
typedef const char* (*NP_GetMIMEDescriptionProcPtr)(void);
typedef OSErr (*BP_GetSupportedMIMETypesProcPtr)(BPSupportedMIMETypes*, UInt32);
#endif
#if defined(_WIN32)
#define OSCALL WINAPI
#else
#if defined(__OS2__)
#define OSCALL _System
#else
#define OSCALL
#endif
#endif
#if defined(XP_UNIX)
/* GCC 3.3 and later support the visibility attribute. */
#if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
#define NP_VISIBILITY_DEFAULT __attribute__((visibility("default")))
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#define NP_VISIBILITY_DEFAULT __global
#else
#define NP_VISIBILITY_DEFAULT
#endif
#define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type
#endif
#if defined(_WIN32) || defined (__OS2__)
#ifdef __cplusplus
extern "C" {
#endif
/* plugin meta member functions */
#if defined(__OS2__)
typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */
char *pMimeTypes;
char *pFileExtents;
char *pFileOpenTemplate;
char *pProductName;
char *pProductDescription;
unsigned long dwProductVersionMS;
unsigned long dwProductVersionLS;
} NPPluginData;
typedef NPError (*NP_GetPluginDataFunc)(NPPluginData*);
NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData);
#endif
typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs);
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*);
NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs);
typedef NPError (*NP_ShutdownFunc)(void);
NPError OSCALL NP_Shutdown(void);
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
const char* NP_GetMIMEDescription(void);
#ifdef __cplusplus
}
#endif
#endif
#if defined(__OS2__)
#pragma pack()
#endif
#ifdef XP_UNIX
#ifdef __cplusplus
extern "C" {
#endif
typedef char* (*NP_GetPluginVersionFunc)(void);
NP_EXPORT(char*) NP_GetPluginVersion(void);
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
NP_EXPORT(const char*) NP_GetMIMEDescription(void);
#ifdef XP_MACOSX
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*);
NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs);
typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs);
#else
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*);
NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);
#endif
typedef NPError (*NP_ShutdownFunc)(void);
NP_EXPORT(NPError) NP_Shutdown(void);
typedef NPError (*NP_GetValueFunc)(void *, NPPVariable, void *);
NP_EXPORT(NPError) NP_GetValue(void *future, NPPVariable aVariable, void *aValue);
#ifdef __cplusplus
}
#endif
#endif
#endif /* npfunctions_h_ */

View File

@ -0,0 +1,393 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
* Foundation ("Mozilla") nor the names of their contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
* THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _NP_RUNTIME_H_
#define _NP_RUNTIME_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "nptypes.h"
/*
This API is used to facilitate binding code written in C to script
objects. The API in this header does not assume the presence of a
user agent. That is, it can be used to bind C code to scripting
environments outside of the context of a user agent.
However, the normal use of the this API is in the context of a
scripting environment running in a browser or other user agent.
In particular it is used to support the extended Netscape
script-ability API for plugins (NP-SAP). NP-SAP is an extension
of the Netscape plugin API. As such we have adopted the use of
the "NP" prefix for this API.
The following NP{N|P}Variables were added to the Netscape plugin
API (in npapi.h):
NPNVWindowNPObject
NPNVPluginElementNPObject
NPPVpluginScriptableNPObject
These variables are exposed through NPN_GetValue() and
NPP_GetValue() (respectively) and are used to establish the
initial binding between the user agent and native code. The DOM
objects in the user agent can be examined and manipulated using
the NPN_ functions that operate on NPObjects described in this
header.
To the extent possible the assumptions about the scripting
language used by the scripting environment have been minimized.
*/
#define NP_BEGIN_MACRO do {
#define NP_END_MACRO } while (0)
/*
Objects (non-primitive data) passed between 'C' and script is
always wrapped in an NPObject. The 'interface' of an NPObject is
described by an NPClass.
*/
typedef struct NPObject NPObject;
typedef struct NPClass NPClass;
typedef char NPUTF8;
typedef struct _NPString {
const NPUTF8 *UTF8Characters;
uint32_t UTF8Length;
} NPString;
typedef enum {
NPVariantType_Void,
NPVariantType_Null,
NPVariantType_Bool,
NPVariantType_Int32,
NPVariantType_Double,
NPVariantType_String,
NPVariantType_Object
} NPVariantType;
typedef struct _NPVariant {
NPVariantType type;
union {
bool boolValue;
int32_t intValue;
double doubleValue;
NPString stringValue;
NPObject *objectValue;
} value;
} NPVariant;
/*
NPN_ReleaseVariantValue is called on all 'out' parameters
references. Specifically it is to be called on variants that own
their value, as is the case with all non-const NPVariant*
arguments after a successful call to any methods (except this one)
in this API.
After calling NPN_ReleaseVariantValue, the type of the variant
will be NPVariantType_Void.
*/
void NPN_ReleaseVariantValue(NPVariant *variant);
#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void)
#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null)
#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32)
#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double)
#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String)
#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object)
#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue)
#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue)
#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue)
#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue)
#define VOID_TO_NPVARIANT(_v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Void; \
(_v).value.objectValue = NULL; \
NP_END_MACRO
#define NULL_TO_NPVARIANT(_v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Null; \
(_v).value.objectValue = NULL; \
NP_END_MACRO
#define BOOLEAN_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Bool; \
(_v).value.boolValue = !!(_val); \
NP_END_MACRO
#define INT32_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Int32; \
(_v).value.intValue = _val; \
NP_END_MACRO
#define DOUBLE_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Double; \
(_v).value.doubleValue = _val; \
NP_END_MACRO
#define STRINGZ_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_String; \
NPString str = { _val, (uint32_t)(strlen(_val)) }; \
(_v).value.stringValue = str; \
NP_END_MACRO
#define STRINGN_TO_NPVARIANT(_val, _len, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_String; \
NPString str = { _val, (uint32_t)(_len) }; \
(_v).value.stringValue = str; \
NP_END_MACRO
#define OBJECT_TO_NPVARIANT(_val, _v) \
NP_BEGIN_MACRO \
(_v).type = NPVariantType_Object; \
(_v).value.objectValue = _val; \
NP_END_MACRO
/*
Type mappings (JavaScript types have been used for illustration
purposes):
JavaScript to C (NPVariant with type:)
undefined NPVariantType_Void
null NPVariantType_Null
Boolean NPVariantType_Bool
Number NPVariantType_Double or NPVariantType_Int32
String NPVariantType_String
Object NPVariantType_Object
C (NPVariant with type:) to JavaScript
NPVariantType_Void undefined
NPVariantType_Null null
NPVariantType_Bool Boolean
NPVariantType_Int32 Number
NPVariantType_Double Number
NPVariantType_String String
NPVariantType_Object Object
*/
typedef void *NPIdentifier;
/*
NPObjects have methods and properties. Methods and properties are
identified with NPIdentifiers. These identifiers may be reflected
in script. NPIdentifiers can be either strings or integers, IOW,
methods and properties can be identified by either strings or
integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
compared using ==. In case of any errors, the requested
NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled
by the browser. Plugins do not need to worry about memory management
with regards to NPIdentifiers.
*/
NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name);
void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
NPIdentifier *identifiers);
NPIdentifier NPN_GetIntIdentifier(int32_t intid);
bool NPN_IdentifierIsString(NPIdentifier identifier);
/*
The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
*/
NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier);
/*
Get the integer represented by identifier. If identifier is not an
integer identifier, the behaviour is undefined.
*/
int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
/*
NPObject behavior is implemented using the following set of
callback functions.
The NPVariant *result argument of these functions (where
applicable) should be released using NPN_ReleaseVariantValue().
*/
typedef NPObject *(*NPAllocateFunctionPtr)(NPP npp, NPClass *aClass);
typedef void (*NPDeallocateFunctionPtr)(NPObject *npobj);
typedef void (*NPInvalidateFunctionPtr)(NPObject *npobj);
typedef bool (*NPHasMethodFunctionPtr)(NPObject *npobj, NPIdentifier name);
typedef bool (*NPInvokeFunctionPtr)(NPObject *npobj, NPIdentifier name,
const NPVariant *args, uint32_t argCount,
NPVariant *result);
typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject *npobj,
const NPVariant *args,
uint32_t argCount,
NPVariant *result);
typedef bool (*NPHasPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name);
typedef bool (*NPGetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
NPVariant *result);
typedef bool (*NPSetPropertyFunctionPtr)(NPObject *npobj, NPIdentifier name,
const NPVariant *value);
typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj,
NPIdentifier name);
typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value,
uint32_t *count);
typedef bool (*NPConstructFunctionPtr)(NPObject *npobj,
const NPVariant *args,
uint32_t argCount,
NPVariant *result);
/*
NPObjects returned by create, retain, invoke, and getProperty pass
a reference count to the caller. That is, the callee adds a
reference count which passes to the caller. It is the caller's
responsibility to release the returned object.
NPInvokeFunctionPtr function may return 0 to indicate a void
result.
NPInvalidateFunctionPtr is called by the scripting environment
when the native code is shutdown. Any attempt to message a
NPObject instance after the invalidate callback has been
called will result in undefined behavior, even if the native code
is still retaining those NPObject instances. (The runtime
will typically return immediately, with 0 or NULL, from an attempt
to dispatch to a NPObject, but this behavior should not be
depended upon.)
The NPEnumerationFunctionPtr function may pass an array of
NPIdentifiers back to the caller. The callee allocs the memory of
the array using NPN_MemAlloc(), and it's the caller's responsibility
to release it using NPN_MemFree().
*/
struct NPClass
{
uint32_t structVersion;
NPAllocateFunctionPtr allocate;
NPDeallocateFunctionPtr deallocate;
NPInvalidateFunctionPtr invalidate;
NPHasMethodFunctionPtr hasMethod;
NPInvokeFunctionPtr invoke;
NPInvokeDefaultFunctionPtr invokeDefault;
NPHasPropertyFunctionPtr hasProperty;
NPGetPropertyFunctionPtr getProperty;
NPSetPropertyFunctionPtr setProperty;
NPRemovePropertyFunctionPtr removeProperty;
NPEnumerationFunctionPtr enumerate;
NPConstructFunctionPtr construct;
};
#define NP_CLASS_STRUCT_VERSION 3
#define NP_CLASS_STRUCT_VERSION_ENUM 2
#define NP_CLASS_STRUCT_VERSION_CTOR 3
#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
struct NPObject {
NPClass *_class;
uint32_t referenceCount;
/*
* Additional space may be allocated here by types of NPObjects
*/
};
/*
If the class has an allocate function, NPN_CreateObject invokes
that function, otherwise a NPObject is allocated and
returned. This method will initialize the referenceCount member of
the NPObject to 1.
*/
NPObject *NPN_CreateObject(NPP npp, NPClass *aClass);
/*
Increment the NPObject's reference count.
*/
NPObject *NPN_RetainObject(NPObject *npobj);
/*
Decremented the NPObject's reference count. If the reference
count goes to zero, the class's destroy function is invoke if
specified, otherwise the object is freed directly.
*/
void NPN_ReleaseObject(NPObject *npobj);
/*
Functions to access script objects represented by NPObject.
Calls to script objects are synchronous. If a function returns a
value, it will be supplied via the result NPVariant
argument. Successful calls will return true, false will be
returned in case of an error.
Calls made from plugin code to script must be made from the thread
on which the plugin was initialized.
*/
bool NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName,
const NPVariant *args, uint32_t argCount, NPVariant *result);
bool NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args,
uint32_t argCount, NPVariant *result);
bool NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script,
NPVariant *result);
bool NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
NPVariant *result);
bool NPN_SetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
const NPVariant *value);
bool NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName);
bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName);
bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
uint32_t *count);
bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
uint32_t argCount, NPVariant *result);
/*
NPN_SetException may be called to trigger a script exception upon
return from entry points into NPObjects. Typical usage:
NPN_SetException (npobj, message);
*/
void NPN_SetException(NPObject *npobj, const NPUTF8 *message);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,121 @@
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* mozilla.org.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Johnny Stenback <jst@mozilla.org> (Original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nptypes_h_
#define nptypes_h_
/*
* Header file for ensuring that C99 types ([u]int32_t, [u]int64_t and bool) and
* true/false macros are available.
*/
#if defined(WIN32) || defined(OS2)
/*
* Win32 and OS/2 don't know C99, so define [u]int_16/32/64 here. The bool
* is predefined tho, both in C and C++.
*/
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned int uint32_t;
typedef long long int64_t;
typedef unsigned long long uint64_t;
#elif defined(_AIX) || defined(__sun) || defined(__osf__) || defined(IRIX) || defined(HPUX)
/*
* AIX and SunOS ship a inttypes.h header that defines [u]int32_t,
* but not bool for C.
*/
#include <inttypes.h>
#ifndef __cplusplus
typedef int bool;
#define true 1
#define false 0
#endif
#elif defined(bsdi) || defined(FREEBSD) || defined(OPENBSD)
/*
* BSD/OS, FreeBSD, and OpenBSD ship sys/types.h that define int32_t and
* u_int32_t.
*/
#include <sys/types.h>
/*
* BSD/OS ships no header that defines uint32_t, nor bool (for C)
*/
#if defined(bsdi)
typedef u_int32_t uint32_t;
typedef u_int64_t uint64_t;
#if !defined(__cplusplus)
typedef int bool;
#define true 1
#define false 0
#endif
#else
/*
* FreeBSD and OpenBSD define uint32_t and bool.
*/
#include <inttypes.h>
#include <stdbool.h>
#endif
#elif defined(BEOS)
#include <inttypes.h>
#else
/*
* For those that ship a standard C99 stdint.h header file, include
* it. Can't do the same for stdbool.h tho, since some systems ship
* with a stdbool.h file that doesn't compile!
*/
#include <stdint.h>
#ifndef __cplusplus
#if !defined(__GNUC__) || (__GNUC__ > 2 || __GNUC_MINOR__ > 95)
#include <stdbool.h>
#else
/*
* GCC 2.91 can't deal with a typedef for bool, but a #define
* works.
*/
#define bool int
#define true 1
#define false 0
#endif
#endif
#endif
#endif /* nptypes_h_ */

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.1.90],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.2.0],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -9,8 +9,8 @@ AC_CONFIG_AUX_DIR([config])
AC_SUBST([PACKAGE_NAME], ["$PACKAGE_NAME"])
AC_SUBST([PACKAGE_VERSION], ["$PACKAGE_VERSION"])
AM_INIT_AUTOMAKE([1.10 dist-bzip2 no-dist-gzip foreign])
AM_MAINTAINER_MODE
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar foreign])
AM_MAINTAINER_MODE([enable])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
@ -66,7 +66,7 @@ AM_CONDITIONAL(BUILD_RECORDER, $build_recorder)
CLUTTER_MIN_VERSION=1.7.5
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.29.15
GJS_MIN_VERSION=1.29.18
MUTTER_MIN_VERSION=3.0.0
FOLKS_MIN_VERSION=0.5.2
GTK_MIN_VERSION=3.0.0
@ -102,6 +102,8 @@ PKG_CHECK_MODULES(SHELL_PERF_HELPER, gtk+-3.0 gio-2.0)
PKG_CHECK_MODULES(SHELL_HOTPLUG_SNIFFER, gio-2.0 gdk-pixbuf-2.0)
PKG_CHECK_MODULES(BROWSER_PLUGIN, gio-2.0 >= $GIO_MIN_VERSION json-glib-1.0 >= 0.13.2)
GJS_VERSION=`$PKG_CONFIG --modversion gjs-internals-1.0`
AC_DEFINE_UNQUOTED([GJS_VERSION], ["$GJS_VERSION"], [The version of GJS we're linking to])
AC_SUBST([GJS_VERSION], ["$GJS_VERSION"])
@ -208,12 +210,41 @@ AC_ARG_ENABLE(jhbuild-wrapper-script,
AS_HELP_STRING([--jhbuild-wrapper-script=yes],[Make "gnome-shell" script work for jhbuild]),,enable_jhbuild_wrapper_script=no)
AM_CONDITIONAL(USE_JHBUILD_WRAPPER_SCRIPT, test "x$enable_jhbuild_wrapper_script" = xyes)
AC_MSG_CHECKING([location of system Certificate Authority list])
AC_ARG_WITH(ca-certificates,
[AC_HELP_STRING([--with-ca-certificates=@<:@path@:>@],
[path to system Certificate Authority list])])
if test "$with_ca_certificates" = "no"; then
AC_MSG_RESULT([disabled])
else
if test -z "$with_ca_certificates"; then
for f in /etc/pki/tls/certs/ca-bundle.crt \
/etc/ssl/certs/ca-certificates.crt; do
if test -f "$f"; then
with_ca_certificates="$f"
fi
done
if test -z "$with_ca_certificates"; then
AC_MSG_ERROR([could not find. Use --with-ca-certificates=path to set, or --without-ca-certificates to disable])
fi
fi
AC_MSG_RESULT($with_ca_certificates)
AC_DEFINE_UNQUOTED(SHELL_SYSTEM_CA_FILE, ["$with_ca_certificates"], [The system TLS CA list])
fi
AC_SUBST(SHELL_SYSTEM_CA_FILE,["$with_ca_certificates"])
BROWSER_PLUGIN_DIR="${BROWSER_PLUGIN_DIR:-"\${libdir}/mozilla/plugins"}"
AC_ARG_VAR([BROWSER_PLUGIN_DIR],[Where to install the plugin to])
AC_CONFIG_FILES([
Makefile
data/Makefile
js/Makefile
js/misc/config.js
src/Makefile
browser-plugin/Makefile
tests/Makefile
po/Makefile.in
man/Makefile

View File

@ -31,7 +31,7 @@
</_description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'firefox.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
<default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'nautilus.desktop', 'gnome-documents.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary>
<_description>
The applications corresponding to these identifiers
@ -69,13 +69,6 @@
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="show-keyboard" type="b">
<default>false</default>
<_summary>Show the onscreen keyboard</_summary>
<_description>
If true, display onscreen keyboard.
</_description>
</key>
<key name="keyboard-type" type="s">
<default>'touch'</default>
<_summary>Which keyboard to use</_summary>

View File

@ -1,5 +1,5 @@
#version 110
uniform sampler2D sampler0;
uniform sampler2D tex;
uniform float fraction;
uniform float height;
const float c = -0.2;
@ -12,15 +12,16 @@ mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
vec4 off = vec4(0.633, 0.633, 0.633, 0);
void main()
{
vec4 color = texture2D(sampler0, gl_TexCoord[0].st);
float y = height * gl_TexCoord[0][1];
vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
float y = height * cogl_tex_coord_in[0].y;
// To reduce contrast, blend with a mid gray
gl_FragColor = color * contrast - off * c;
cogl_color_out = color * contrast - off * c * color.a;
// We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
// We only fully dim at a distance of BORDER_MAX_HEIGHT from the top and
// when the fraction is 1.0. For other locations and fractions we linearly
// interpolate back to the original undimmed color.
gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0);
gl_FragColor = color + (gl_FragColor - color) * fraction;
// interpolate back to the original undimmed color, so the top of the window
// is at full color.
cogl_color_out = color + (cogl_color_out - color) * max(min(y / border_max_height, 1.0), 0.0);
cogl_color_out = color + (cogl_color_out - color) * fraction;
}

View File

@ -30,6 +30,10 @@
min-width: 350px;
}
.login-dialog-prompt-fingerprint-message {
font-size: 10.5pt;
}
.login-dialog-user-list-view {
-st-vfade-offset: 1em;
}
@ -110,6 +114,7 @@
background-color: white;
caret-color: black;
caret-size: 1px;
width: 15em;
}
.login-dialog-session-list {

View File

@ -164,6 +164,10 @@ StTooltip StLabel {
background-color: #4c4c4c;
}
.popup-menu-item:insensitive {
color: #9f9f9f;
}
.popup-image-menu-item {
}
@ -276,12 +280,12 @@ StTooltip StLabel {
background-color: black;
border-image: url("panel-border.svg") 1;
font-size: 10.5pt;
font-weight: bold;
height: 1.86em;
}
#panelLeft, #panelCenter, #panelRight {
#panelLeft, #panelCenter {
spacing: 4px;
font-weight: bold;
}
#panelLeft:ltr {
@ -335,7 +339,8 @@ StTooltip StLabel {
}
.panel-button {
padding: 0px 12px;
-natural-hpadding: 12px;
-minimum-hpadding: 6px;
font-weight: bold;
color: #ccc;
transition-duration: 100;
@ -355,9 +360,9 @@ StTooltip StLabel {
text-shadow: black 0px 2px 2px;
}
#statusTray > .panel-button:active,
#statusTray > .panel-button:checked,
#statusTray > .panel-button:focus {
.panel-status-button:active,
.panel-status-button:checked,
.panel-status-button:focus {
background-image: url("panel-button-highlight-narrow.svg");
}
@ -371,19 +376,7 @@ StTooltip StLabel {
-boxpointer-gap: 4px
}
/* The rounded panel corners we draw don't
* support transitions, so disable transitions
* for the buttons at the left/right edges
*/
#panelActivities {
transition-duration: 0;
}
#panelStatus {
transition-duration: 0;
}
#panelStatusMenu {
#panelUserMenu {
spacing: 4px;
}
@ -410,6 +403,7 @@ StTooltip StLabel {
.status-chooser-user-name {
font-weight: bold;
font-size: 1.3em;
min-width: 120pt;
}
.status-chooser-combo {
@ -426,24 +420,10 @@ StTooltip StLabel {
}
.status-chooser-status-item,
.status-chooser-combo > .popup-combobox-item {
.status-chooser-combo .popup-combobox-item {
spacing: .4em;
}
#legacyTray {
spacing: 14px;
padding-left: 14px;
}
#legacyTray:rtl {
padding-left: 0px;
padding-right: 14px;
}
#legacyTray:compact {
spacing: 8px;
}
.system-status-icon {
icon-size: 1.14em;
}
@ -531,8 +511,6 @@ StTooltip StLabel {
.dash-placeholder {
background-image: url("dash-placeholder.svg");
height: 27px;
width: 48px;
}
#viewSelector {
@ -951,7 +929,7 @@ StTooltip StLabel {
.calendar-vertical-separator {
-stipple-width: 1px;
-stipple-color: #505050;
width: 1.5em;
width: 0.3em;
}
#calendarPopup {
@ -974,13 +952,14 @@ StTooltip StLabel {
.calendar-month-label {
color: #666666;
font-size: 7.5pt;
padding: 2px;
padding-bottom: 8px;
padding-top: 8px;
font-weight: bold;
}
.calendar-change-month-back {
width: 20px;
height: 20px;
width: 18px;
height: 12px;
background-image: url("calendar-arrow-left.svg");
border-radius: 4px;
}
@ -997,8 +976,8 @@ StTooltip StLabel {
}
.calendar-change-month-forward {
width: 20px;
height: 20px;
width: 18px;
height: 12px;
background-image: url("calendar-arrow-right.svg");
border-radius: 4px;
}
@ -1030,6 +1009,7 @@ StTooltip StLabel {
.calendar-day-base:hover {
background-color: #777777;
color: #fff;
}
.calendar-day-base:active {
@ -1038,6 +1018,7 @@ StTooltip StLabel {
.calendar-day-heading {
color: #666666;
padding-top: 1em;
}
.calendar-week-number {
@ -1100,7 +1081,8 @@ StTooltip StLabel {
font-size: 9pt;
font-weight: bold;
color: rgba(153, 153, 153, 1.0);
padding-left: 0.3em;
padding-left: 1.8em;
padding-top: 0.8em;
}
.events-day-header:rtl {

View File

@ -3,7 +3,10 @@ jsdir = $(pkgdatadir)/js
nobase_dist_js_DATA = \
gdm/batch.js \
gdm/consoleKit.js \
gdm/fingerprint.js \
gdm/loginDialog.js \
gdm/powerMenu.js \
misc/config.js \
misc/docInfo.js \
misc/fileUtils.js \

32
js/gdm/consoleKit.js Normal file
View File

@ -0,0 +1,32 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
const DBus = imports.dbus;
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: '' }]
};
function ConsoleKitManager() {
this._init();
};
ConsoleKitManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager');
}
};
DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);

26
js/gdm/fingerprint.js Normal file
View File

@ -0,0 +1,26 @@
// -*- mode: js2; indent-tabs-mode: nil; js2-basic-offset: 4 -*-
const DBus = imports.dbus;
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' }]
};
function FprintManager() {
this._init();
};
FprintManager.prototype = {
_init: function() {
DBus.system.proxifyObject(this,
'net.reactivated.Fprint',
'/net/reactivated/Fprint/Manager');
}
};
DBus.proxifyPrototype(FprintManager.prototype, FprintManagerIface);

View File

@ -32,16 +32,26 @@ const Shell = imports.gi.Shell;
const St = imports.gi.St;
const GdmGreeter = imports.gi.GdmGreeter;
const Batch = imports.misc.batch;
const Batch = imports.gdm.batch;
const DBus = imports.dbus;
const Fprint = imports.gdm.fingerprint;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const Tweener = imports.ui.tweener;
const _PASSWORD_SERVICE_NAME = 'gdm-password';
const _FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
const _FADE_ANIMATION_TIME = 0.16;
const _RESIZE_ANIMATION_TIME = 0.25;
const _SCROLL_ANIMATION_TIME = 2.0;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_NAME_SIZE = 48;
const _LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
const _FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
const _LOGO_KEY = 'logo';
let _loginDialog = null;
@ -246,12 +256,15 @@ UserListItem.prototype = {
showFocusAnimation: function(time) {
let hold = new Batch.Hold();
let node = this.actor.get_theme_node();
let padding = node.get_horizontal_padding();
let box = this._verticalBox.get_allocation_box();
Tweener.removeTweens(this._focusBin);
this._focusBin.width = 0;
Tweener.addTween(this._focusBin,
{ width: box.x2 - box.x1,
{ width: (box.x2 - box.x1 - padding),
time: time,
transition: 'linear',
onComplete: function() {
@ -580,8 +593,11 @@ function SessionList() {
SessionList.prototype = {
_init: function() {
this.actor = new St.BoxLayout({ style_class: 'login-dialog-session-list',
this.actor = new St.Bin();
this._box = new St.BoxLayout({ style_class: 'login-dialog-session-list',
vertical: true});
this.actor.child = this._box;
this._button = new St.Button({ style_class: 'login-dialog-session-list-button',
can_focus: true,
@ -606,14 +622,14 @@ SessionList.prototype = {
this._button.connect('clicked',
Lang.bind(this, this._onClicked));
this.actor.add_actor(this._button,
this._box.add_actor(this._button,
{ x_fill: true,
y_fill: true,
expand: true });
this._scrollView = new St.ScrollView({ style_class: 'login-dialog-session-list-scroll-view'});
this._scrollView.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC);
this.actor.add_actor(this._scrollView,
this._box.add_actor(this._scrollView,
{ x_fill: true,
y_fill: true,
expand: true });
@ -679,9 +695,9 @@ SessionList.prototype = {
ids.sort();
if (ids.length <= 1)
this.actor.hide();
this._box.hide();
else
this.actor.show();
this._box.show();
for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription] = GdmGreeter.get_session_name_and_description(ids[i]);
@ -731,7 +747,7 @@ LoginDialog.prototype = {
this._greeterClient.open_connection();
this._greeterClient.call_start_conversation('gdm-password');
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
this._greeterClient.connect('reset',
Lang.bind(this, this._onReset));
@ -754,8 +770,19 @@ LoginDialog.prototype = {
this._greeterClient.connect('conversation-stopped',
Lang.bind(this, this._onConversationStopped));
this._settings = new Gio.Settings({ schema: _LOGIN_SCREEN_SCHEMA });
this._fprintManager = new Fprint.FprintManager();
this._startFingerprintConversationIfNeeded();
this._settings.connect('changed::' + _LOGO_KEY,
Lang.bind(this, this._updateLogo));
this._logoBox = new St.Bin({ style_class: 'login-dialog-logo-box' });
this.contentLayout.add(this._logoBox);
this._updateLogo();
this._titleLabel = new St.Label({ style_class: 'login-dialog-title',
text: _("Sign In") });
text: C_("title", "Sign In") });
this.contentLayout.add(this._titleLabel,
{ y_fill: false,
@ -798,6 +825,12 @@ LoginDialog.prototype = {
x_fill: true,
y_fill: false,
x_align: St.Align.START });
// 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' });
this._promptFingerprintMessage.hide();
this._promptBox.add(this._promptFingerprintMessage);
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
@ -807,10 +840,9 @@ LoginDialog.prototype = {
this._promptBox.add(this._sessionList.actor,
{ expand: true,
x_fill: true,
x_fill: false,
y_fill: true,
x_align: St.Align.START,
y_align: St.Align.START});
x_align: St.Align.START });
this._promptBox.hide();
let notListedLabel = new St.Label({ text: _("Not listed?"),
@ -848,13 +880,45 @@ LoginDialog.prototype = {
},
_startFingerprintConversationIfNeeded: function() {
this._haveFingerprintReader = false;
if (!this._settings.get_boolean(_FINGERPRINT_AUTHENTICATION_KEY))
return;
this._fprintManager.GetDefaultDeviceRemote(DBus.CALL_FLAG_START, Lang.bind(this,
function(device, error) {
if (!error && device)
this._haveFingerprintReader = true;
if (this._haveFingerprintReader)
this._greeterClient.call_start_conversation(_FINGERPRINT_SERVICE_NAME);
}));
},
_updateLogo: function() {
this._logoBox.child = null;
let path = this._settings.get_string(_LOGO_KEY);
if (path) {
let file = Gio.file_new_for_path(path);
let uri = file.get_uri();
let textureCache = St.TextureCache.get_default();
this._logoBox.child = textureCache.load_uri_async(uri, -1, _LOGO_ICON_NAME_SIZE);
}
},
_onReset: function(client, serviceName) {
this._greeterClient.call_start_conversation('gdm-password');
this._greeterClient.call_start_conversation(_PASSWORD_SERVICE_NAME);
this._startFingerprintConversationIfNeeded();
let tasks = [this._hidePrompt,
new Batch.ConcurrentBatch(this, [this._fadeInTitleLabel,
this._fadeInNotListedButton]),
this._fadeInNotListedButton,
this._fadeInLogo]),
function() {
this._sessionList.close();
@ -879,10 +943,17 @@ LoginDialog.prototype = {
},
_onInfo: function(client, serviceName, info) {
// we don't want fingerprint messages with the word UPEK in them
if (serviceName != _PASSWORD_SERVICE_NAME)
return;
Main.notifyError(info);
},
_onProblem: function(client, serviceName, problem) {
// we don't want to show auth failed messages to
// users who haven't enrolled their fingerprint.
if (serviceName != _PASSWORD_SERVICE_NAME)
return;
Main.notifyError(problem);
},
@ -899,6 +970,13 @@ LoginDialog.prototype = {
return _fadeInActor(this._promptEntry);
},
function() {
if (!this._haveFingerprintReader)
return null;
return _fadeInActor(this._promptFingerprintMessage);
},
function() {
return _fadeInActor(this._promptBox);
},
@ -928,7 +1006,7 @@ LoginDialog.prototype = {
{ action: Lang.bind(this, function() {
hold.release();
}),
label: _("Sign In") }];
label: C_("button", "Sign In") }];
this._promptEntryActivateCallbackId = this._promptEntry.clutter_text.connect('activate',
Lang.bind(this, function() {
@ -967,6 +1045,7 @@ LoginDialog.prototype = {
},
function() {
this._promptFingerprintMessage.hide();
this._promptEntry.set_text('');
}];
@ -990,12 +1069,20 @@ LoginDialog.prototype = {
return batch.run();
},
_onInfoQuery: function(client, serviceName, question) {
// We only expect questions to come from the main auth service
if (serviceName != _PASSWORD_SERVICE_NAME)
return;
this._promptEntry.set_text('');
this._promptEntry.clutter_text.set_password_char('');
this._askQuestion(serviceName, question);
},
_onSecretInfoQuery: function(client, serviceName, secretQuestion) {
// We only expect secret requests to come from the main auth service
if (serviceName != _PASSWORD_SERVICE_NAME)
return;
this._promptEntry.set_text('');
this._promptEntry.clutter_text.set_password_char('\u25cf');
this._askQuestion(serviceName, secretQuestion);
@ -1132,7 +1219,14 @@ LoginDialog.prototype = {
},
_onConversationStopped: function(client, serviceName) {
// if the password service fails, then cancel everything.
// But if, e.g., fingerprint fails, still give
// password authentication a chance to succeed
if (serviceName == _PASSWORD_SERVICE_NAME) {
this._greeterClient.call_cancel();
} else if (serviceName == _FINGERPRINT_SERVICE_NAME) {
_fadeOutActor(this._promptFingerprintMessage);
}
},
_onNotListedClicked: function(user) {
@ -1149,16 +1243,25 @@ LoginDialog.prototype = {
},
new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
this._fadeOutNotListedButton]),
this._fadeOutNotListedButton,
this._fadeOutLogo]),
function() {
this._greeterClient.call_begin_verification('gdm-password');
this._greeterClient.call_begin_verification(_PASSWORD_SERVICE_NAME);
}];
let batch = new Batch.ConsecutiveBatch(this, tasks);
batch.run();
},
_fadeInLogo: function() {
return _fadeInActor(this._logoBox);
},
_fadeOutLogo: function() {
return _fadeOutActor(this._logoBox);
},
_fadeInTitleLabel: function() {
return _fadeInActor(this._titleLabel);
},
@ -1194,7 +1297,8 @@ LoginDialog.prototype = {
},
new Batch.ConcurrentBatch(this, [this._fadeOutTitleLabel,
this._fadeOutNotListedButton]),
this._fadeOutNotListedButton,
this._fadeOutLogo]),
function() {
return this._userList.shrinkToNaturalHeight();
@ -1202,8 +1306,11 @@ LoginDialog.prototype = {
function() {
let userName = activatedItem.user.get_user_name();
this._greeterClient.call_begin_verification_for_user('gdm-password',
this._greeterClient.call_begin_verification_for_user(_PASSWORD_SERVICE_NAME,
userName);
if (this._haveFingerprintReader)
this._greeterClient.call_begin_verification_for_user(_FINGERPRINT_SERVICE_NAME, userName);
}];
this._user = activatedItem.user;

146
js/gdm/powerMenu.js Normal file
View File

@ -0,0 +1,146 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*-
*
* Copyright 2011 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
const Lang = imports.lang;
const UPowerGlib = imports.gi.UPowerGlib;
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,
_init: function() {
PanelMenu.SystemStatusButton.prototype._init.call(this, 'system-shutdown', null);
this._consoleKitManager = new ConsoleKit.ConsoleKitManager();
this._upClient = new UPowerGlib.Client();
this._createSubMenu();
this._upClient.connect('notify::can-suspend',
Lang.bind(this, this._updateHaveSuspend));
this._updateHaveSuspend();
// ConsoleKit doesn't send notifications when shutdown/reboot
// are disabled, so we update the menu item each time the menu opens
this.menu.connect('open-state-changed', Lang.bind(this,
function(menu, open) {
if (open) {
this._updateHaveShutdown();
this._updateHaveRestart();
}
}));
this._updateHaveShutdown();
this._updateHaveRestart();
},
_updateVisibility: function() {
if (!this._haveSuspend && !this._haveShutdown && !this._haveRestart)
this.actor.hide();
else
this.actor.show();
},
_updateHaveShutdown: function() {
this._consoleKitManager.CanStopRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveShutdown = result;
else
this._haveShutdown = false;
if (this._haveShutdown) {
this._powerOffItem.actor.show();
} else {
this._powerOffItem.actor.hide();
}
this._updateVisibility();
}));
},
_updateHaveRestart: function() {
this._consoleKitManager.CanRestartRemote(Lang.bind(this,
function(result, error) {
if (!error)
this._haveRestart = result;
else
this._haveRestart = false;
if (this._haveRestart) {
this._restartItem.actor.show();
} else {
this._restartItem.actor.hide();
}
this._updateVisibility();
}));
},
_updateHaveSuspend: function() {
this._haveSuspend = this._upClient.get_can_suspend();
if (this._haveSuspend)
this._suspendItem.actor.show();
else
this._suspendItem.actor.hide();
this._updateVisibility();
},
_createSubMenu: function() {
let item;
item = new PopupMenu.PopupMenuItem(_("Suspend"));
item.connect('activate', Lang.bind(this, this._onActivateSuspend));
this.menu.addMenuItem(item);
this._suspendItem = item;
item = new PopupMenu.PopupMenuItem(_("Restart"));
item.connect('activate', Lang.bind(this, this._onActivateRestart));
this.menu.addMenuItem(item);
this._restartItem = item;
item = new PopupMenu.PopupMenuItem(_("Power Off"));
item.connect('activate', Lang.bind(this, this._onActivatePowerOff));
this.menu.addMenuItem(item);
this._powerOffItem = item;
},
_onActivateSuspend: function() {
if (this._haveSuspend)
this._upClient.suspend_sync(null);
},
_onActivateRestart: function() {
if (this._haveRestart)
this._consoleKitManager.RestartRemote();
},
_onActivatePowerOff: function() {
if (this._haveShutdown)
this._consoleKitManager.StopRemote();
}
};

View File

@ -7,4 +7,5 @@ const PACKAGE_VERSION = '@PACKAGE_VERSION@';
const GJS_VERSION = '@GJS_VERSION@';
/* 1 if gnome-bluetooth is available, 0 otherwise */
const HAVE_BLUETOOTH = @HAVE_BLUETOOTH@;
/* The system TLS CA list */
const SHELL_SYSTEM_CA_FILE = '@SHELL_SYSTEM_CA_FILE@';

View File

@ -20,3 +20,25 @@ function listDirAsync(file, callback) {
enumerator.next_files_async(100, GLib.PRIORITY_LOW, null, onNextFileComplete);
});
}
function deleteGFile(file) {
// Work around 'delete' being a keyword in JS.
return file['delete'](null);
}
function recursivelyDeleteDir(dir) {
let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
let info, child;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let child = dir.get_child(info.get_name());
if (type == Gio.FileType.REGULAR)
deleteGFile(child);
else if (type == Gio.TypeType.DIRECTORY)
recursivelyDeleteDir(child);
}
deleteGFile(dir);
}

View File

@ -7,8 +7,32 @@ const Shell = imports.gi.Shell;
const Main = imports.ui.main;
/* http://daringfireball.net/2010/07/improved_regex_for_matching_urls */
const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}/)([^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'\\".,<>?«»“”‘’]))', 'gi');
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\((?:[^\\s()<>]+|(?:\\(?:[^\\s()<>]+\\)))*\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _urlRegexp = new RegExp(
'(^|' + _leadingJunk + ')' +
'(' +
'(?:' +
'[a-z][\\w-]+://' + // scheme://
'|' +
'www\\d{0,3}[.]' + // www.
'|' +
'[a-z0-9.\\-]+[.][a-z]{2,4}/' + // foo.xx/
')' +
'(?:' + // one or more:
'[^\\s()<>]+' + // run of non-space non-()
'|' + // or
_balancedParens + // balanced parens
')+' +
'(?:' + // end with:
_balancedParens + // balanced parens
'|' + // or
_notTrailingJunk + // last non-junk char
')' +
')', 'gi');
// findUrls:
// @str: string to find URLs in
@ -21,7 +45,7 @@ const _urlRegexp = new RegExp('\\b(([a-z][\\w-]+:(/{1,3}|[a-z0-9%])|www\\d{0,3}[
function findUrls(str) {
let res = [], match;
while ((match = _urlRegexp.exec(str)))
res.push({ url: match[0], pos: match.index });
res.push({ url: match[2], pos: match.index + match[1].length });
return res;
}

View File

@ -31,6 +31,18 @@ function mod(a, b) {
return (a + b) % b;
}
function primaryModifier(mask) {
if (mask == 0)
return 0;
let primary = 1;
while (mask > 1) {
mask >>= 1;
primary <<= 1;
}
return primary;
}
function AltTabPopup() {
this._init();
}
@ -48,6 +60,7 @@ AltTabPopup.prototype = {
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._haveModal = false;
this._modifierMask = 0;
this._currentApp = 0;
this._currentWindow = -1;
@ -121,9 +134,9 @@ AltTabPopup.prototype = {
}
},
show : function(backward, binding) {
let tracker = Shell.WindowTracker.get_default();
let apps = tracker.get_running_apps ('');
show : function(backward, binding, mask) {
let appSys = Shell.AppSystem.get_default();
let apps = appSys.get_running ();
if (!apps.length)
return false;
@ -131,6 +144,7 @@ AltTabPopup.prototype = {
if (!Main.pushModal(this.actor))
return false;
this._haveModal = true;
this._modifierMask = primaryModifier(mask);
this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
@ -147,6 +161,8 @@ AltTabPopup.prototype = {
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
this.actor.opacity = 0;
this.actor.show();
this.actor.get_allocation_box();
// Make the initial selection
@ -177,7 +193,7 @@ AltTabPopup.prototype = {
// details.) So we check now. (Have to do this after updating
// selection.)
let [x, y, mods] = global.get_pointer();
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
if (!(mods & this._modifierMask)) {
this._finish();
return false;
}
@ -186,7 +202,7 @@ AltTabPopup.prototype = {
// disturbed by the popup briefly flashing.
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
Lang.bind(this, function () {
this.actor.show();
this.actor.opacity = 255;
this._initialDelayTimeoutId = 0;
}));
@ -254,7 +270,7 @@ AltTabPopup.prototype = {
_keyReleaseEvent : function(actor, event) {
let [x, y, mods] = global.get_pointer();
let state = mods & Clutter.ModifierType.MOD1_MASK;
let state = mods & this._modifierMask;
if (state == 0)
this._finish();
@ -479,6 +495,10 @@ AltTabPopup.prototype = {
this.actor.add_actor(this._thumbnails.actor);
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
this._thumbnails.actor.get_allocation_box();
this._thumbnails.actor.opacity = 0;
Tweener.addTween(this._thumbnails.actor,
{ opacity: 255,
@ -630,11 +650,10 @@ SwitcherList.prototype = {
this._items[this._highlighted].add_style_pseudo_class('selected');
}
let monitor = Main.layoutManager.primaryMonitor;
let itemSize = this._items[index].allocation.x2 - this._items[index].allocation.x1;
let [posX, posY] = this._items[index].get_transformed_position();
posX += this.actor.x;
if (posX + itemSize > monitor.width + monitor.x)
let [absItemX, absItemY] = this._items[index].get_transformed_position();
let [result, posX, posY] = this.actor.transform_stage_point(absItemX, 0);
let [containerWidth, containerHeight] = this.actor.get_transformed_size();
if (posX + this._items[index].get_width() > containerWidth)
this._scrollToRight();
else if (posX < 0)
this._scrollToLeft();

View File

@ -208,6 +208,7 @@ ViewByCategories.prototype = {
if (!entry.get_app_info().get_nodisplay())
appList.push(app);
} else if (nextType == GMenu.TreeItemType.DIRECTORY) {
if (!dir.get_is_nodisplay())
this._loadCategory(iter.get_directory(), appList);
}
}
@ -262,6 +263,8 @@ ViewByCategories.prototype = {
while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) {
if (nextType == GMenu.TreeItemType.DIRECTORY) {
var dir = iter.get_directory();
if (dir.get_is_nodisplay())
continue;
this._addCategory(dir.get_name(), i, dir);
i++;
}
@ -556,7 +559,7 @@ AppWellIcon.prototype = {
this._menu.connect('activate-window', Lang.bind(this, function (menu, window) {
this.activateWindow(window);
}));
this._menu.connect('popup', Lang.bind(this, function (menu, isPoppedUp) {
this._menu.connect('open-state-changed', Lang.bind(this, function (menu, isPoppedUp) {
if (!isPoppedUp)
this._onMenuPoppedDown();
}));
@ -640,7 +643,6 @@ AppIconMenu.prototype = {
this._source = source;
this.connect('activate', Lang.bind(this, this._onActivate));
this.connect('open-state-changed', Lang.bind(this, this._onOpenStateChanged));
this.actor.add_style_class_name('app-well-menu');
@ -704,14 +706,6 @@ AppIconMenu.prototype = {
this.open();
},
_onOpenStateChanged: function (menu, open) {
if (open) {
this.emit('popup', true);
} else {
this.emit('popup', false);
}
},
_onActivate: function (actor, child) {
if (child._window) {
let metaWindow = child._window;

View File

@ -23,8 +23,6 @@ const AutorunSetting = {
ASK: 3
};
const HOTPLUG_ICON_SIZE = 16;
// misc utils
function ignoreAutorunForMount(mount) {
let root = mount.get_root();
@ -279,12 +277,12 @@ AutorunResidentSource.prototype = {
__proto__: MessageTray.Source.prototype,
_init: function() {
MessageTray.Source.prototype._init.call(this, _('Removable Devices'));
MessageTray.Source.prototype._init.call(this, _("Removable Devices"));
this._mounts = [];
this._notification = new AutorunResidentNotification(this);
this._setSummaryIcon(this.createNotificationIcon(HOTPLUG_ICON_SIZE));
this._setSummaryIcon(this.createNotificationIcon());
},
addMount: function(mount, apps) {
@ -329,9 +327,10 @@ AutorunResidentSource.prototype = {
}
},
createNotificationIcon: function(iconSize) {
return new St.Icon ({ icon_name: 'drive-harddisk',
icon_size: iconSize ? iconSize : this.ICON_SIZE });
createNotificationIcon: function() {
return new St.Icon ({ icon_name: 'media-removable',
icon_type: St.IconType.FULLCOLOR,
icon_size: this.ICON_SIZE });
}
}
@ -532,16 +531,16 @@ AutorunTransientSource.prototype = {
this.apps = apps;
this._notification = new AutorunTransientNotification(this);
this._setSummaryIcon(this.createNotificationIcon(this.ICON_SIZE));
this._setSummaryIcon(this.createNotificationIcon());
// add ourselves as a source, and popup the notification
Main.messageTray.add(this);
this.notify(this._notification);
},
createNotificationIcon: function(iconSize) {
createNotificationIcon: function() {
return new St.Icon({ gicon: this.mount.get_icon(),
icon_size: iconSize ? iconSize : this.ICON_SIZE });
icon_size: this.ICON_SIZE });
}
}

View File

@ -94,7 +94,7 @@ CtrlAltTabManager.prototype = {
return a.x - b.x;
},
popup: function(backwards) {
popup: function(backwards, mask) {
// Start with the set of focus groups that are currently mapped
let items = this._items.filter(function (item) { return item.proxy.mapped; });
@ -123,7 +123,16 @@ CtrlAltTabManager.prototype = {
return;
items.sort(Lang.bind(this, this._sortItems));
new CtrlAltTabPopup().show(items, backwards);
if (!this._popup) {
this._popup = new CtrlAltTabPopup();
this._popup.show(items, backwards, mask);
this._popup.actor.connect('destroy',
Lang.bind(this, function() {
this._popup = null;
}));
}
}
};
@ -147,6 +156,7 @@ CtrlAltTabPopup.prototype = {
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
this._haveModal = false;
this._modifierMask = 0;
this._selection = 0;
Main.uiGroup.add_actor(this.actor);
@ -183,10 +193,11 @@ CtrlAltTabPopup.prototype = {
this._switcher.actor.allocate(childBox, flags);
},
show : function(items, startBackwards) {
show : function(items, startBackwards, mask) {
if (!Main.pushModal(this.actor))
return false;
this._haveModal = true;
this._modifierMask = AltTab.primaryModifier(mask);
this._keyPressEventId = this.actor.connect('key-press-event', Lang.bind(this, this._keyPressEvent));
this._keyReleaseEventId = this.actor.connect('key-release-event', Lang.bind(this, this._keyReleaseEvent));
@ -200,7 +211,7 @@ CtrlAltTabPopup.prototype = {
this._select(this._selection);
let [x, y, mods] = global.get_pointer();
if (!(mods & Gdk.ModifierType.MOD1_MASK)) {
if (!(mods & this._modifierMask)) {
this._finish();
return false;
}
@ -246,7 +257,7 @@ CtrlAltTabPopup.prototype = {
_keyReleaseEvent : function(actor, event) {
let [x, y, mods] = global.get_pointer();
let state = mods & Clutter.ModifierType.MOD1_MASK;
let state = mods & this._modifierMask;
if (state == 0)
this._finish();

View File

@ -275,7 +275,7 @@ Dash.prototype = {
this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay));
AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay));
this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
this._appSystem.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
Main.overview.connect('item-drag-begin',
Lang.bind(this, this._onDragBegin));
@ -471,10 +471,7 @@ Dash.prototype = {
_redisplay: function () {
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
/* hardcode here pending some design about how exactly desktop contexts behave */
let contextId = '';
let running = this._tracker.get_running_apps(contextId);
let running = this._appSystem.get_running();
let children = this._box.get_children().filter(function(actor) {
return actor._delegate.child &&
@ -687,6 +684,8 @@ Dash.prototype = {
}
this._dragPlaceholder = new DragPlaceholderItem();
this._dragPlaceholder.child.set_width (this.iconSize);
this._dragPlaceholder.child.set_height (this.iconSize / 2);
this._box.insert_actor(this._dragPlaceholder.actor,
this._dragPlaceholderPos);
if (fadeIn)

View File

@ -60,7 +60,7 @@ DateMenuButton.prototype = {
PanelMenu.Button.prototype._init.call(this, menuAlignment);
this._clock = new St.Label();
this.actor.set_child(this._clock);
this.actor.add_actor(this._clock);
hbox = new St.BoxLayout({name: 'calendarArea' });
this.menu.addActor(hbox);

View File

@ -60,8 +60,16 @@ const logoutDialogContent = {
subjectWithUser: _("Log Out %s"),
subject: _("Log Out"),
inhibitedDescription: _("Click Log Out to quit these applications and log out of the system."),
uninhibitedDescriptionWithUser: _("%s will be logged out automatically in %d seconds."),
uninhibitedDescription: _("You will be logged out automatically in %d seconds."),
uninhibitedDescriptionWithUser: function(user, seconds) {
return ngettext("%s will be logged out automatically in %d second.",
"%s will be logged out automatically in %d seconds.",
seconds).format(user, seconds);
},
uninhibitedDescription: function(seconds) {
return ngettext("You will be logged out automatically in %d second.",
"You will be logged out automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Logging out of the system."),
confirmButtons: [{ signal: 'ConfirmedLogout',
label: _("Log Out") }],
@ -71,7 +79,11 @@ const logoutDialogContent = {
const shutdownDialogContent = {
subject: _("Power Off"),
inhibitedDescription: _("Click Power Off to quit these applications and power off the system."),
uninhibitedDescription: _("The system will power off automatically in %d seconds."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will power off automatically in %d second.",
"The system will power off automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Powering off the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: _("Restart") },
@ -84,7 +96,11 @@ const shutdownDialogContent = {
const restartDialogContent = {
subject: _("Restart"),
inhibitedDescription: _("Click Restart to quit these applications and restart the system."),
uninhibitedDescription: _("The system will restart automatically in %d seconds."),
uninhibitedDescription: function(seconds) {
return ngettext("The system will restart automatically in %d second.",
"The system will restart automatically in %d seconds.",
seconds).format(seconds);
},
endDescription: _("Restarting the system."),
confirmButtons: [{ signal: 'ConfirmedReboot',
label: _("Restart") }],
@ -388,14 +404,14 @@ EndSessionDialog.prototype = {
subject = dialogContent.subjectWithUser.format(realName);
if (dialogContent.uninhibitedDescriptionWithUser)
description = dialogContent.uninhibitedDescriptionWithUser.format(realName, displayTime);
description = dialogContent.uninhibitedDescriptionWithUser(realName, displayTime);
else
description = dialogContent.uninhibitedDescription.format(displayTime);
description = dialogContent.uninhibitedDescription(displayTime);
}
}
if (!description)
description = dialogContent.uninhibitedDescription.format(displayTime);
description = dialogContent.uninhibitedDescription(displayTime);
} else {
description = dialogContent.endDescription;
}

View File

@ -3,6 +3,7 @@
const Lang = imports.lang;
const Signals = imports.signals;
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
@ -10,6 +11,10 @@ const Shell = imports.gi.Shell;
const Soup = imports.gi.Soup;
const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
const ModalDialog = imports.ui.modalDialog;
const API_VERSION = 1;
const ExtensionState = {
ENABLED: 1,
@ -28,6 +33,10 @@ const ExtensionType = {
PER_USER: 2
};
const REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
const REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
const REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
const _httpSession = new Soup.SessionAsync();
// The unfortunate state of gjs, gobject-introspection and libsoup
@ -37,6 +46,16 @@ const _httpSession = new Soup.SessionAsync();
if (Soup.Session.prototype.add_feature != null)
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
function _getCertFile() {
let localCert = GLib.build_filenamev([global.userdatadir, 'extensions.gnome.org.crt']);
if (GLib.file_test(localCert, GLib.FileTest.EXISTS))
return localCert;
else
return Config.SHELL_SYSTEM_CA_FILE;
}
_httpSession.ssl_ca_file = _getCertFile();
// Maps uuid -> metadata object
const extensionMeta = {};
// Maps uuid -> importer object (extension directory tree)
@ -92,53 +111,51 @@ function versionCheck(required, current) {
return false;
}
function installExtensionFromManifestURL(uuid, url) {
_httpSession.queue_message(
Soup.Message.new('GET', url),
function installExtensionFromUUID(uuid, version_tag) {
let params = { uuid: uuid,
version_tag: version_tag,
shell_version: Config.PACKAGE_VERSION,
api_version: API_VERSION.toString() };
let message = Soup.form_request_new_from_hash('GET', REPOSITORY_URL_INFO, params);
_httpSession.queue_message(message,
function(session, message) {
if (message.status_code != Soup.KnownStatusCode.OK) {
logExtensionError(uuid, 'downloading manifest: ' + message.status_code.toString());
return;
let info = JSON.parse(message.response_body.data);
let dialog = new InstallExtensionDialog(uuid, version_tag, info.name);
dialog.open(global.get_current_time());
});
}
let manifest;
try {
manifest = JSON.parse(message.response_body.data);
} catch (e) {
logExtensionError(uuid, 'parsing: ' + e.toString());
return;
}
function uninstallExtensionFromUUID(uuid) {
let meta = extensionMeta[uuid];
if (!meta)
return false;
if (uuid != manifest['uuid']) {
logExtensionError(uuid, 'manifest: manifest uuids do not match');
return;
}
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
disableExtension(uuid);
let meta = extensionMeta[uuid] = { uuid: uuid,
state: ExtensionState.DOWNLOADING,
error: '' };
// Don't try to uninstall system extensions
if (meta.type != ExtensionType.PER_USER)
return false;
meta.state = ExtensionState.UNINSTALLED;
_signals.emit('extension-state-changed', meta);
installExtensionFromManifest(manifest, meta);
});
}
delete extensionMeta[uuid];
function installExtensionFromManifest(manifest, meta) {
let uuid = manifest['uuid'];
let name = manifest['name'];
// Importers are marked as PERMANENT, so we can't do this.
// delete extensions[uuid];
extensions[uuid] = undefined;
if (!versionCheck(manifest['shell-version'], Config.PACKAGE_VERSION)) {
meta.state = ExtensionState.OUT_OF_DATE;
logExtensionError(uuid, 'version: ' + name + ' is not compatible with current GNOME Shell version', meta.state);
return;
}
delete extensionStateObjs[uuid];
delete errors[uuid];
let url = manifest['__installer'];
_httpSession.queue_message(Soup.Message.new('GET', url),
function(session, message) {
gotExtensionZipFile(session, message, uuid);
});
FileUtils.recursivelyDeleteDir(Gio.file_new_for_path(meta.path));
return true;
}
function gotExtensionZipFile(session, message, uuid) {
@ -173,6 +190,14 @@ function gotExtensionZipFile(session, message, uuid) {
GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, function(pid, status) {
GLib.spawn_close_pid(pid);
// Add extension to 'enabled-extensions' for the user, always...
let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
if (enabledExtensions.indexOf(uuid) == -1) {
enabledExtensions.push(uuid);
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
loadExtension(dir, true, ExtensionType.PER_USER);
});
}
@ -434,3 +459,73 @@ function loadExtensions() {
_loadExtensionsIn(dir, ExtensionType.SYSTEM);
}
}
function InstallExtensionDialog(uuid, version_tag, name) {
this._init(uuid, version_tag, name);
}
InstallExtensionDialog.prototype = {
__proto__: ModalDialog.ModalDialog.prototype,
_init: function(uuid, version_tag, name) {
ModalDialog.ModalDialog.prototype._init.call(this, { styleClass: 'extension-dialog' });
this._uuid = uuid;
this._version_tag = version_tag;
this._name = name;
this.setButtons([{ label: _("Cancel"),
action: Lang.bind(this, this._onCancelButtonPressed),
key: Clutter.Escape
},
{ label: _("Install"),
action: Lang.bind(this, this._onInstallButtonPressed)
}]);
let message = _("Download and install '%s' from extensions.gnome.org?").format(name);
this._descriptionLabel = new St.Label({ text: message });
this.contentLayout.add(this._descriptionLabel,
{ y_fill: true,
y_align: St.Align.START });
},
_onCancelButtonPressed: function(button, event) {
this.close(global.get_current_time());
// Even though the extension is already "uninstalled", send through
// a state-changed signal for any users who want to know if the install
// went through correctly -- using proper async DBus would block more
// traditional clients like the plugin
let meta = { uuid: this._uuid,
state: ExtensionState.UNINSTALLED,
error: '' };
_signals.emit('extension-state-changed', meta);
},
_onInstallButtonPressed: function(button, event) {
let meta = { uuid: this._uuid,
state: ExtensionState.DOWNLOADING,
error: '' };
extensionMeta[this._uuid] = meta;
_signals.emit('extension-state-changed', meta);
let params = { version_tag: this._version_tag,
shell_version: Config.PACKAGE_VERSION,
api_version: API_VERSION.toString() };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
let message = Soup.form_request_new_from_hash('GET', url, params);
_httpSession.queue_message(message,
Lang.bind(this, function(session, message) {
gotExtensionZipFile(session, message, this._uuid);
}));
this.close(global.get_current_time());
}
};

View File

@ -15,9 +15,11 @@ const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const KEYBOARD_SCHEMA = 'org.gnome.shell.keyboard';
const SHOW_KEYBOARD = 'show-keyboard';
const KEYBOARD_TYPE = 'keyboard-type';
const A11Y_APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEYBOARD = 'screen-keyboard-enabled';
// Key constants taken from Antler
// FIXME: ought to be moved into libcaribou
const PRETTY_KEYS = {
@ -199,26 +201,25 @@ function Keyboard() {
Keyboard.prototype = {
_init: function () {
DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
DBus.session.acquire_name('org.gnome.Caribou.Keyboard', 0, null, null);
this.actor = null;
this._timestamp = global.get_current_time();
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._redraw));
this._keyboardSettings = new Gio.Settings({ schema: KEYBOARD_SCHEMA });
this._keyboardSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._a11yApplicationsSettings = new Gio.Settings({ schema: A11Y_APPLICATIONS_SCHEMA });
this._a11yApplicationsSettings.connect('changed', Lang.bind(this, this._settingsChanged));
this._settingsChanged();
},
init: function () {
if (this._enableKeyboard)
this._redraw();
},
_settingsChanged: function () {
this._enableKeyboard = this._keyboardSettings.get_boolean(SHOW_KEYBOARD);
this._enableKeyboard = this._a11yApplicationsSettings.get_boolean(SHOW_KEYBOARD);
if (!this._enableKeyboard && !this._keyboard)
return;
if (this._enableKeyboard && this._keyboard &&
@ -239,12 +240,17 @@ Keyboard.prototype = {
if (this._focusNotifyId)
global.stage.disconnect(this._focusNotifyId);
this._keyboard = null;
this.actor.destroy_children();
this.actor.destroy();
this.actor = null;
this._destroySource();
},
_setupKeyboard: function() {
this.actor = new St.BoxLayout({ name: 'keyboard', vertical: true, reactive: true });
Main.layoutManager.keyboardBox.add_actor(this.actor);
Main.layoutManager.trackChrome(this.actor);
this._keyboard = new Caribou.KeyboardModel({ keyboard_type: this._keyboardSettings.get_string(KEYBOARD_TYPE) });
this._groups = {};
this._current_page = null;
@ -263,15 +269,14 @@ Keyboard.prototype = {
_onKeyFocusChanged: function () {
let focus = global.stage.key_focus;
if (focus == global.stage || focus == null)
// Showing an extended key popup will grab focus, but ignore that
if (focus && focus._extended_keys)
return;
if (focus instanceof Clutter.Text)
this.show();
else {
if (focus._extended_keys == null)
else
this.hide();
}
},
_addKeys: function () {
@ -359,6 +364,9 @@ Keyboard.prototype = {
},
_redraw: function () {
if (!this._enableKeyboard)
return;
let monitor = Main.layoutManager.bottomMonitor;
let maxHeight = monitor.height / 3;
this.actor.width = monitor.width;
@ -484,11 +492,11 @@ Keyboard.prototype = {
},
SetCursorLocation: function(x, y, w, h) {
this._setLocation(x, y);
// this._setLocation(x, y);
},
SetEntryLocation: function(x, y, w, h) {
this._setLocation(x, y);
// this._setLocation(x, y);
},
get Name() {

View File

@ -40,20 +40,16 @@ LayoutManager.prototype = {
this.panelBox.connect('allocation-changed',
Lang.bind(this, this._updatePanelBarriers));
// bottomBox contains the tray and keyboard (which move
// together, since the tray slides up from the top of the
// keyboard when the keyboard is visible).
this._bottomBox = new St.BoxLayout({ name: 'bottomBox',
vertical: true });
this.addChrome(this._bottomBox, { visibleInFullscreen: true });
this.trayBox = new St.BoxLayout({ name: 'trayBox' });
this.addChrome(this.trayBox, { visibleInFullscreen: true });
this.trayBox.connect('allocation-changed',
Lang.bind(this, this._updateTrayBarrier));
this._bottomBox.add_actor(this.trayBox);
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox' });
this._bottomBox.add_actor(this.keyboardBox);
this.keyboardBox = new St.BoxLayout({ name: 'keyboardBox',
reactive: true,
track_hover: true });
this.addChrome(this.keyboardBox, { visibleInFullscreen: true });
this._keyboardHeightNotifyId = 0;
global.screen.connect('monitors-changed',
Lang.bind(this, this._monitorsChanged));
@ -153,11 +149,13 @@ LayoutManager.prototype = {
this.panelBox.set_position(this.primaryMonitor.x, this.primaryMonitor.y);
this.panelBox.set_size(this.primaryMonitor.width, -1);
this._bottomBox.set_position(this.bottomMonitor.x,
this.keyboardBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
this._bottomBox.set_size(this.bottomMonitor.width, -1);
this.keyboardBox.set_size(this.bottomMonitor.width, -1);
this.trayBox.width = this.bottomMonitor.width;
this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
this.trayBox.set_size(this.bottomMonitor.width, -1);
// Set trayBox's clip to show things above it, but not below
// it (so it's not visible behind the keyboard). The exact
@ -250,23 +248,38 @@ LayoutManager.prototype = {
},
_startupAnimation: function() {
// Don't animate the strut
this._chrome.freezeUpdateRegions();
this.panelBox.anchor_y = this.panelBox.height;
Tweener.addTween(this.panelBox,
{ anchor_y: 0,
time: STARTUP_ANIMATION_TIME,
transition: 'easeOutQuad'
transition: 'easeOutQuad',
onComplete: this._startupAnimationComplete,
onCompleteScope: this
});
},
_startupAnimationComplete: function() {
this._chrome.thawUpdateRegions();
},
showKeyboard: function () {
Main.messageTray.hide();
Tweener.addTween(this._bottomBox,
{ anchor_y: this._bottomBox.height,
this.keyboardBox.raise_top();
Tweener.addTween(this.keyboardBox,
{ anchor_y: this.keyboardBox.height,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showKeyboardComplete,
onCompleteScope: this
});
Tweener.addTween(this.trayBox,
{ anchor_y: this.keyboardBox.height,
time: KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
_showKeyboardComplete: function() {
@ -274,20 +287,30 @@ LayoutManager.prototype = {
// anchor point changes
this._chrome.updateRegions();
this._bottomBox.connect('notify::height', Lang.bind(this, function () {
this._bottomBoxAnchor = this._bottomBox.height;
this._keyboardHeightNotifyId = this.keyboardBox.connect('notify::height', Lang.bind(this, function () {
this.keyboardBox.anchor_y = this.keyboardBox.height;
this.trayBox.anchor_y = this.keyboardBox.height;
}));
},
hideKeyboard: function (immediate) {
Main.messageTray.hide();
Tweener.addTween(this._bottomBox,
if (this._keyboardHeightNotifyId) {
this.keyboardBox.disconnect(this._keyboardHeightNotifyId);
this._keyboardHeightNotifyId = 0;
}
Tweener.addTween(this.keyboardBox,
{ anchor_y: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._showKeyboardComplete,
onComplete: this._hideKeyboardComplete,
onCompleteScope: this
});
Tweener.addTween(this.trayBox,
{ anchor_y: 0,
time: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
transition: 'easeOutQuad'
});
},
_hideKeyboardComplete: function() {
@ -295,11 +318,11 @@ LayoutManager.prototype = {
},
// addChrome:
// @actor: an actor to add to the chrome layer
// @actor: an actor to add to the chrome
// @params: (optional) additional params
//
// Adds @actor to the chrome layer and (unless %affectsInputRegion
// in @params is %false) extends the input region to include it.
// Adds @actor to the chrome, and (unless %affectsInputRegion in
// @params is %false) extends the input region to include it.
// Changes in @actor's size, position, and visibility will
// automatically result in appropriate changes to the input
// region.
@ -341,9 +364,9 @@ LayoutManager.prototype = {
},
// removeChrome:
// @actor: a child of the chrome layer
// @actor: a chrome actor
//
// Removes @actor from the chrome layer
// Removes @actor from the chrome
removeChrome: function(actor) {
this._chrome.removeActor(actor);
}
@ -542,13 +565,10 @@ Chrome.prototype = {
_init: function(layoutManager) {
this._layoutManager = layoutManager;
// The group itself has zero size so it doesn't interfere with DND
this.actor = new Shell.GenericContainer({ width: 0, height: 0 });
Main.uiGroup.add_actor(this.actor);
this.actor.connect('allocate', Lang.bind(this, this._allocated));
this._monitors = [];
this._inOverview = false;
this._updateRegionIdle = 0;
this._freezeUpdateCount = 0;
this._trackedActors = [];
@ -561,6 +581,7 @@ Chrome.prototype = {
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._queueUpdateRegions));
this._screenSaverActive = false;
this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
@ -579,14 +600,8 @@ Chrome.prototype = {
Lang.bind(this, this._overviewHidden));
},
_allocated: function(actor, box, flags) {
let children = this.actor.get_children();
for (let i = 0; i < children.length; i++)
children[i].allocate_preferred_size(flags);
},
addActor: function(actor, params) {
this.actor.add_actor(actor);
Main.uiGroup.add_actor(actor);
this._trackActor(actor, params);
},
@ -598,7 +613,7 @@ Chrome.prototype = {
index = this._findActor(ancestor);
}
if (!ancestor)
throw new Error('actor is not a descendent of the chrome layer');
throw new Error('actor is not a descendent of a chrome actor');
let ancestorData = this._trackedActors[index];
if (!params)
@ -618,7 +633,7 @@ Chrome.prototype = {
},
removeActor: function(actor) {
this.actor.remove_actor(actor);
Main.uiGroup.remove_actor(actor);
this._untrackActor(actor);
},
@ -637,6 +652,7 @@ Chrome.prototype = {
let actorData = Params.parse(params, defaultParams);
actorData.actor = actor;
actorData.isToplevel = actor.get_parent() == Main.uiGroup;
actorData.visibleId = actor.connect('notify::visible',
Lang.bind(this, this._queueUpdateRegions));
actorData.allocationId = actor.connect('notify::allocation',
@ -666,18 +682,29 @@ Chrome.prototype = {
},
_actorReparented: function(actor, oldParent) {
if (!this.actor.contains(actor))
let newParent = actor.get_parent();
if (!newParent)
this._untrackActor(actor);
else
actorData.isToplevel = (newParent == Main.uiGroup);
},
_updateVisibility: function() {
for (let i = 0; i < this._trackedActors.length; i++) {
let actorData = this._trackedActors[i];
if (!this._inOverview && !actorData.visibleInFullscreen &&
let actorData = this._trackedActors[i], visible;
if (!actorData.isToplevel)
continue;
if (this._screenSaverActive)
visible = false;
else if (this._inOverview)
visible = true;
else if (!actorData.visibleInFullscreen &&
this._findMonitorForActor(actorData.actor).inFullscreen)
this.actor.set_skip_paint(actorData.actor, true);
visible = false;
else
this.actor.set_skip_paint(actorData.actor, false);
visible = true;
Main.uiGroup.set_skip_paint(actorData.actor, !visible);
}
},
@ -703,7 +730,8 @@ Chrome.prototype = {
},
_onScreenSaverActiveChanged: function(proxy, screenSaverActive) {
this.actor.visible = !screenSaverActive;
this._screenSaverActive = screenSaverActive;
this._updateVisibility();
this._queueUpdateRegions();
},
@ -744,11 +772,22 @@ Chrome.prototype = {
},
_queueUpdateRegions: function() {
if (!this._updateRegionIdle)
if (!this._updateRegionIdle && !this._freezeUpdateCount)
this._updateRegionIdle = Mainloop.idle_add(Lang.bind(this, this.updateRegions),
Meta.PRIORITY_BEFORE_REDRAW);
},
freezeUpdateRegions: function() {
if (this._updateRegionIdle)
this.updateRegions();
this._freezeUpdateCount++;
},
thawUpdateRegions: function() {
this._freezeUpdateCount--;
this._queueUpdateRegions();
},
_updateFullscreen: function() {
let windows = Main.getWindowActorsForWorkspace(global.screen.get_active_workspace_index());
@ -756,7 +795,7 @@ Chrome.prototype = {
for (let i = 0; i < this._monitors.length; i++)
this._monitors[i].inFullscreen = false;
// The chrome layer should be visible unless there is a window
// Ordinary chrome should be visible unless there is a window
// with layer FULLSCREEN, or a window with layer
// OVERRIDE_REDIRECT that covers the whole screen.
// ('override_redirect' is not actually a layer above all
@ -837,7 +876,7 @@ Chrome.prototype = {
if (actorData.affectsInputRegion &&
actorData.actor.get_paint_visibility() &&
!this.actor.get_skip_paint(actorData.actor))
!Main.uiGroup.get_skip_paint(actorData.actor))
rects.push(rect);
if (!actorData.affectsStruts)

View File

@ -6,6 +6,7 @@ const GConf = imports.gi.GConf;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
@ -606,6 +607,9 @@ Memory.prototype = {
this._gjs_closure = new St.Label();
this.actor.add(this._gjs_closure);
this._last_gc_seconds_ago = new St.Label();
this.actor.add(this._last_gc_seconds_ago);
this._gcbutton = new St.Button({ label: 'Full GC',
style_class: 'lg-obj-inspector-button' });
this._gcbutton.connect('clicked', Lang.bind(this, function () { global.gc(); this._renderText(); }));
@ -625,6 +629,7 @@ Memory.prototype = {
this._gjs_gobject.text = 'gjs_gobject: ' + memInfo.gjs_gobject;
this._gjs_function.text = 'gjs_function: ' + memInfo.gjs_function;
this._gjs_closure.text = 'gjs_closure: ' + memInfo.gjs_closure;
this._last_gc_seconds_ago.text = 'last_gc_seconds_ago: ' + memInfo.last_gc_seconds_ago;
}
};
@ -761,9 +766,13 @@ LookingGlass.prototype = {
Lang.bind(this, this._updateFont));
this._updateFont();
// we add it to the chrome because we want it to appear to slide
// out from underneath the panel
Main.layoutManager.addChrome(this.actor);
// We want it to appear to slide out from underneath the panel
Main.layoutManager.panelBox.add_actor(this.actor);
this.actor.lower_bottom();
Main.layoutManager.panelBox.connect('allocation-changed',
Lang.bind(this, this._queueResize));
Main.layoutManager.keyboardBox.connect('allocation-changed',
Lang.bind(this, this._queueResize));
this._objInspector = new ObjInspector();
Main.uiGroup.add_actor(this._objInspector.actor);
@ -844,6 +853,8 @@ LookingGlass.prototype = {
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entry.clutter_text });
this._resize();
},
_updateFont: function() {
@ -918,13 +929,18 @@ LookingGlass.prototype = {
this.open();
},
_resizeTo: function(actor) {
_queueResize: function() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
Lang.bind(this, function () { this._resize(); }));
},
_resize: function() {
let primary = Main.layoutManager.primaryMonitor;
let myWidth = primary.width * 0.7;
let myHeight = primary.height * 0.7;
let [srcX, srcY] = actor.get_transformed_position();
this.actor.x = srcX + (primary.width - myWidth) / 2;
this._hiddenY = srcY + actor.height - myHeight - 4; // -4 to hide the top corners
let availableHeight = primary.height - Main.layoutManager.keyboardBox.height;
let myHeight = Math.min(primary.height * 0.7, availableHeight * 0.9);
this.actor.x = (primary.width - myWidth) / 2;
this._hiddenY = this.actor.get_parent().height - myHeight - 4; // -4 to hide the top corners
this._targetY = this._hiddenY + myHeight;
this.actor.y = this._hiddenY;
this.actor.width = myWidth;
@ -934,14 +950,6 @@ LookingGlass.prototype = {
this._targetY + Math.floor(myHeight * 0.1));
},
slaveTo: function(actor) {
this._slaveTo = actor;
actor.connect('notify::allocation', Lang.bind(this, function () {
this._resizeTo(actor);
}));
this._resizeTo(actor);
},
insertObject: function(obj) {
this._pushResult('<insert>', obj);
},
@ -974,7 +982,6 @@ LookingGlass.prototype = {
this._notebook.selectIndex(0);
this.actor.show();
this.actor.lower_bottom();
this._open = true;
this._history.lastItem();
@ -1005,7 +1012,6 @@ LookingGlass.prototype = {
Main.popModal(this._entry);
this.actor.lower_bottom();
Tweener.addTween(this.actor, { time: 0.5 / St.get_slow_down_factor(),
transition: 'easeOutQuad',
y: this._hiddenY,

View File

@ -193,7 +193,13 @@ function start() {
loadTheme();
// Set up stage hierarchy to group all UI actors under one container.
uiGroup = new Clutter.Group();
uiGroup = new Shell.GenericContainer({ name: 'uiGroup' });
uiGroup.connect('allocate',
function (actor, box, flags) {
let children = uiGroup.get_children();
for (let i = 0; i < children.length; i++)
children[i].allocate_preferred_size(flags);
});
St.set_ui_root(global.stage, uiGroup);
global.window_group.reparent(uiGroup);
global.overlay_group.reparent(uiGroup);
@ -220,6 +226,7 @@ function start() {
panel.startStatusArea();
layoutManager.init();
keyboard.init();
overview.init();
@ -588,9 +595,9 @@ function _globalKeyPressHandler(actor, event) {
return true;
}
// Other bindings are only available when the overview is up and
// Other bindings are only available to the user session when the overview is up and
// no modal dialog is present.
if (!overview.visible || modalCount > 1)
if (global.session_type == Shell.SessionType.USER && (!overview.visible || modalCount > 1))
return false;
// This isn't a Meta.KeyBindingAction yet
@ -600,7 +607,8 @@ function _globalKeyPressHandler(actor, event) {
}
if (action == Meta.KeyBindingAction.SWITCH_PANELS) {
ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK);
ctrlAltTabManager.popup(modifierState & Clutter.ModifierType.SHIFT_MASK,
modifierState);
return true;
}
@ -758,7 +766,6 @@ function popModal(actor, timestamp) {
function createLookingGlass() {
if (lookingGlass == null) {
lookingGlass = new LookingGlass.LookingGlass();
lookingGlass.slaveTo(panel.actor);
}
return lookingGlass;
}

View File

@ -111,12 +111,21 @@ URLHighlighter.prototype = {
this.setMarkup(text, allowMarkup);
this.actor.connect('button-press-event', Lang.bind(this, function(actor, event) {
// Don't try to URL highlight when invisible.
// The MessageTray doesn't actually hide us, so
// we need to check for paint opacities as well.
if (!actor.visible || actor.get_paint_opacity() == 0)
return false;
// Keep Notification.actor from seeing this and taking
// a pointer grab, which would block our button-release-event
// handler, if an URL is clicked
return this._findUrlAtPos(event) != -1;
}));
this.actor.connect('button-release-event', Lang.bind(this, function (actor, event) {
if (!actor.visible || actor.get_paint_opacity() == 0)
return false;
let urlId = this._findUrlAtPos(event);
if (urlId != -1) {
let url = this._urls[urlId].url;
@ -134,6 +143,9 @@ URLHighlighter.prototype = {
return false;
}));
this.actor.connect('motion-event', Lang.bind(this, function(actor, event) {
if (!actor.visible || actor.get_paint_opacity() == 0)
return false;
let urlId = this._findUrlAtPos(event);
if (urlId != -1 && !this._cursorChanged) {
global.set_cursor(Shell.Cursor.POINTING_HAND);
@ -145,6 +157,9 @@ URLHighlighter.prototype = {
return false;
}));
this.actor.connect('leave-event', Lang.bind(this, function() {
if (!this.actor.visible || this.actor.get_paint_opacity() == 0)
return;
if (this._cursorChanged) {
this._cursorChanged = false;
global.unset_cursor();
@ -269,7 +284,8 @@ FocusGrabber.prototype = {
let source = event.get_source();
switch (event.type()) {
case Clutter.EventType.BUTTON_PRESS:
if (!this.actor.contains(source) && !Main.keyboard.actor.contains(source))
if (!this.actor.contains(source) &&
!Main.layoutManager.keyboardBox.contains(source))
this.emit('button-pressed', source);
break;
case Clutter.EventType.KEY_PRESS:
@ -400,6 +416,7 @@ Notification.prototype = {
_init: function(source, title, banner, params) {
this.source = source;
this.title = title;
this.urgency = Urgency.NORMAL;
this.resident = false;
// 'transient' is a reserved keyword in JS, so we have to use an alternate variable name
@ -487,8 +504,11 @@ Notification.prototype = {
let oldFocus = global.stage.key_focus;
if (this._icon)
if (this._icon && (params.icon || params.clear)) {
this._icon.destroy();
this._icon = null;
}
// We always clear the content area if we don't have custom
// content because it might contain the @banner that didn't
// fit in the banner mode.
@ -514,6 +534,7 @@ Notification.prototype = {
if (!this._scrollArea && !this._actionArea && !this._imageBin)
this._table.remove_style_class_name('multi-line-notification');
if (!this._icon) {
this._icon = params.icon || this.source.createNotificationIcon();
this._table.add(this._icon, { row: 0,
col: 0,
@ -521,7 +542,9 @@ Notification.prototype = {
y_expand: false,
y_fill: false,
y_align: St.Align.START });
}
this.title = title;
title = title ? _fixMarkup(title.replace(/\n/g, ' '), params.titleMarkup) : '';
this._titleLabel.clutter_text.set_markup('<b>' + title + '</b>');
@ -776,11 +799,12 @@ Notification.prototype = {
},
_bannerBoxAllocate: function(actor, box, flags) {
let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(-1);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(-1);
let availWidth = box.x2 - box.x1;
let [titleMinW, titleNatW] = this._titleLabel.get_preferred_width(-1);
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
let titleBox = new Clutter.ActorBox();
let titleBoxW = Math.min(titleNatW, availWidth);
if (this._titleDirection == St.TextDirection.RTL) {
@ -1154,9 +1178,7 @@ SummaryItem.prototype = {
this.notificationStack = new St.BoxLayout({ name: 'summary-notification-stack',
vertical: true });
this.notificationStackView.add_actor(this.notificationStack);
this._notificationExpandedIds = [];
this._notificationDoneDisplayingIds = [];
this._notificationDestroyedIds = [];
this._stackedNotifications = [];
this._oldMaxScrollAdjustment = 0;
@ -1225,18 +1247,19 @@ SummaryItem.prototype = {
doneShowingNotificationStack: function() {
let notificationActors = this.notificationStack.get_children();
for (let i = 0; i < notificationActors.length; i++) {
notificationActors[i]._delegate.collapseCompleted();
notificationActors[i]._delegate.disconnect(this._notificationExpandedIds[i]);
notificationActors[i]._delegate.disconnect(this._notificationDoneDisplayingIds[i]);
notificationActors[i]._delegate.disconnect(this._notificationDestroyedIds[i]);
this.notificationStack.remove_actor(notificationActors[i]);
notificationActors[i]._delegate.setIconVisible(true);
notificationActors[i]._delegate.enableScrolling(true);
for (let i = 0; i < this._stackedNotifications.length; i++) {
let stackedNotification = this._stackedNotifications[i];
let notification = stackedNotification.notification;
notification.collapseCompleted();
notification.disconnect(stackedNotification.notificationExpandedId);
notification.disconnect(stackedNotification.notificationDoneDisplayingId);
notification.disconnect(stackedNotification.notificationDestroyedId);
if (notification.actor.get_parent() == this.notificationStack)
this.notificationStack.remove_actor(notification.actor);
notification.setIconVisible(true);
notification.enableScrolling(true);
}
this._notificationExpandedIds = [];
this._notificationDoneDisplayingIds = [];
this._notificationDestroyedIds = [];
this._stackedNotifications = [];
},
_notificationAddedToSource: function(source, notification) {
@ -1245,12 +1268,12 @@ SummaryItem.prototype = {
},
_appendNotificationToStack: function(notification) {
let notificationExpandedId = notification.connect('expanded', Lang.bind(this, this._contentUpdated));
this._notificationExpandedIds.push(notificationExpandedId);
let notificationDoneDisplayingId = notification.connect('done-displaying', Lang.bind(this, this._notificationDoneDisplaying));
this._notificationDoneDisplayingIds.push(notificationDoneDisplayingId);
let notificationDestroyedId = notification.connect('destroy', Lang.bind(this, this._notificationDestroyed));
this._notificationDestroyedIds.push(notificationDestroyedId);
let stackedNotification = {};
stackedNotification.notification = notification;
stackedNotification.notificationExpandedId = notification.connect('expanded', Lang.bind(this, this._contentUpdated));
stackedNotification.notificationDoneDisplayingId = notification.connect('done-displaying', Lang.bind(this, this._notificationDoneDisplaying));
stackedNotification.notificationDestroyedId = notification.connect('destroy', Lang.bind(this, this._notificationDestroyed));
this._stackedNotifications.push(stackedNotification);
if (!this.source.isChat)
notification.enableScrolling(false);
if (this.notificationStack.get_children().length > 0)
@ -1280,17 +1303,18 @@ SummaryItem.prototype = {
},
_notificationDestroyed: function(notification) {
let index = this.notificationStack.get_children().indexOf(notification.actor);
if (index >= 0) {
notification.disconnect(this._notificationExpandedIds[index]);
this._notificationExpandedIds.splice(index, 1);
notification.disconnect(this._notificationDoneDisplayingIds[index]);
this._notificationDoneDisplayingIds.splice(index, 1);
notification.disconnect(this._notificationDestroyedIds[index]);
this._notificationDestroyedIds.splice(index, 1);
this.notificationStack.remove_actor(notification.actor);
for (let i = 0; i < this._stackedNotifications.length; i++) {
if (this._stackedNotifications[i].notification == notification) {
let stackedNotification = this._stackedNotifications[i];
notification.disconnect(stackedNotification.notificationExpandedId);
notification.disconnect(stackedNotification.notificationDoneDisplayingId);
notification.disconnect(stackedNotification.notificationDestroyedId);
this._stackedNotifications.splice(i, 1);
this._contentUpdated();
break;
}
}
if (this.notificationStack.get_children().length > 0)
this.notificationStack.get_children()[0]._delegate.setIconVisible(true);
}
@ -1332,6 +1356,7 @@ MessageTray.prototype = {
this._summaryBin.opacity = 0;
this._summaryMotionId = 0;
this._trayMotionId = 0;
this._summaryBoxPointer = new BoxPointer.BoxPointer(St.Side.BOTTOM,
{ reactive: true,
@ -1371,12 +1396,15 @@ MessageTray.prototype = {
}));
this._focusGrabber.connect('escape-pressed', Lang.bind(this, this._escapeTray));
Main.layoutManager.keyboardBox.connect('notify::hover', Lang.bind(this, this._onKeyboardHoverChanged));
this._trayState = State.HIDDEN;
this._locked = false;
this._traySummoned = false;
this._useLongerTrayLeftTimeout = false;
this._trayLeftTimeoutId = 0;
this._pointerInTray = false;
this._pointerInKeyboard = false;
this._summaryState = State.HIDDEN;
this._summaryTimeoutId = 0;
this._pointerInSummary = false;
@ -1480,7 +1508,10 @@ MessageTray.prototype = {
// transient sources, which are removed after the notification is shown, but are
// not removed fast enough because of the callbacks to avoid the summary popping up.
// So we just don't add transient sources to this._newSummaryItems.
if (!source.isTransient)
// We don't want that to happen for chat sources neither, because they
// can be added when the user starts a chat from Empathy and they are not transient.
// The notification will popup on incoming message anyway. See bug #657249.
if (!source.isTransient && !source.isChat)
this._newSummaryItems.push(summaryItem);
source.connect('notify', Lang.bind(this, this._onNotify));
@ -1823,6 +1854,24 @@ MessageTray.prototype = {
}
},
_onKeyboardHoverChanged: function(keyboard) {
this._pointerInKeyboard = keyboard.hover;
if (!keyboard.hover) {
let event = Clutter.get_current_event();
if (event && event.type() == Clutter.EventType.LEAVE) {
let into = event.get_related();
if (into && this.actor.contains(into)) {
// Don't call _updateState, because pointerInTray is
// still false
return;
}
}
}
this._updateState();
},
_onStatusChanged: function(presence, status) {
this._backFromAway = (this._userStatus == GnomeSession.PresenceStatus.IDLE && this._userStatus != status);
this._userStatus = status;
@ -1887,7 +1936,7 @@ MessageTray.prototype = {
let notificationsPending = this._notificationQueue.length > 0 && (!this._busy || notificationUrgent);
let notificationPinned = this._pointerInTray && !this._pointerInSummary && !this._notificationRemoved;
let notificationExpanded = this._notificationBin.y < 0;
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked) || this._notificationRemoved;
let notificationExpired = (this._notificationTimeoutId == 0 && !(this._notification && this._notification.urgency == Urgency.CRITICAL) && !this._pointerInTray && !this._locked && !(this._pointerInKeyboard && notificationExpanded)) || this._notificationRemoved;
let canShowNotification = notificationsPending && this._summaryState == State.HIDDEN;
if (this._notificationState == State.HIDDEN) {
@ -2222,7 +2271,7 @@ MessageTray.prototype = {
_showSummaryBoxPointer: function() {
this._summaryBoxPointerItem = this._clickedSummaryItem;
this._summaryBoxPointerContentUpdatedId = this._summaryBoxPointerItem.connect('content-updated',
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
Lang.bind(this, this._onSummaryBoxPointerContentUpdated));
this._summaryBoxPointerDoneDisplayingId = this._summaryBoxPointerItem.connect('done-displaying-content',
Lang.bind(this, this._escapeTray));
if (this._clickedSummaryItemMouseButton == 1) {
@ -2245,6 +2294,8 @@ MessageTray.prototype = {
// _clickedSummaryItem.actor can change absolute position without changing allocation
this._summaryMotionId = this._summary.connect('allocation-changed',
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
this._trayMotionId = Main.layoutManager.trayBox.connect('notify::anchor-y',
Lang.bind(this, this._adjustSummaryBoxPointerPosition));
this._summaryBoxPointer.actor.opacity = 0;
this._summaryBoxPointer.actor.show();
@ -2257,6 +2308,13 @@ MessageTray.prototype = {
}));
},
_onSummaryBoxPointerContentUpdated: function() {
if (this._summaryBoxPointerItem.notificationStack.get_children().length == 0)
this._hideSummaryBoxPointer();
this._adjustSummaryBoxPointerPosition();
},
_adjustSummaryBoxPointerPosition: function() {
// The position of the arrow origin should be the same as center of this._clickedSummaryItem.actor
if (!this._clickedSummaryItem)
@ -2269,8 +2327,10 @@ MessageTray.prototype = {
if (this._clickedSummaryItemAllocationChangedId) {
this._clickedSummaryItem.actor.disconnect(this._clickedSummaryItemAllocationChangedId);
this._summary.disconnect(this._summaryMotionId);
Main.layoutManager.trayBox.disconnect(this._trayMotionId);
this._clickedSummaryItemAllocationChangedId = 0;
this._summaryMotionId = 0;
this._trayMotionId = 0;
}
if (this._clickedSummaryItem)
@ -2280,9 +2340,18 @@ MessageTray.prototype = {
},
_hideSummaryBoxPointer: function() {
// We should be sure to hide the box pointer if all notifications in it are destroyed while
// it is hiding, so that we don't show an an animation of an empty blob being hidden.
if (this._summaryBoxPointerState == State.HIDING &&
this._summaryBoxPointerItem.notificationStack.get_children().length == 0) {
this._summaryBoxPointer.actor.hide();
return;
}
this._summaryBoxPointerState = State.HIDING;
// Unset this._clickedSummaryItem if we are no longer showing the summary
if (this._summaryState != State.SHOWN)
// Unset this._clickedSummaryItem if we are no longer showing the summary or if
// this._clickedSummaryItem is still the item associated with the currently showing box pointer
if (this._summaryState != State.SHOWN || this._summaryBoxPointerItem == this._clickedSummaryItem)
this._unsetClickedSummaryItem();
this._focusGrabber.ungrabFocus();

View File

@ -110,9 +110,8 @@ ModalDialog.prototype = {
this._buttonLayout.destroy_children();
this._actionKeys = {};
let i = 0;
for (let index in buttons) {
let buttonInfo = buttons[index];
for (let i = 0; i < buttons.length; i ++) {
let buttonInfo = buttons[i];
let label = buttonInfo['label'];
let action = buttonInfo['action'];
let key = buttonInfo['key'];
@ -132,6 +131,8 @@ ModalDialog.prototype = {
else
x_alignment = St.Align.MIDDLE;
if (this._initialKeyFocus == this._dialogLayout ||
this._buttonLayout.contains(this._initialKeyFocus))
this._initialKeyFocus = buttonInfo.button;
this._buttonLayout.add(buttonInfo.button,
{ expand: true,
@ -144,11 +145,10 @@ ModalDialog.prototype = {
if (key)
this._actionKeys[key] = action;
i++;
}
// Fade in buttons if there weren't any before
if (!hadChildren && i > 0) {
if (!hadChildren && buttons.length > 0) {
this._buttonLayout.opacity = 0;
Tweener.addTween(this._buttonLayout,
{ opacity: 255,

View File

@ -91,6 +91,7 @@ NetworkSecretDialog.prototype = {
}
let secretTable = new St.Table({ style_class: 'network-dialog-secret-table' });
let initialFocusSet = false;
let pos = 0;
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
@ -109,6 +110,12 @@ NetworkSecretDialog.prototype = {
secret.valid = secret.value.length > 0;
if (reactive) {
if (!initialFocusSet) {
this.setInitialKeyFocus(secret.entry);
initialFocusSet = true;
}
secret.entry.clutter_text.connect('activate', Lang.bind(this, this._onOk));
secret.entry.clutter_text.connect('text-changed', Lang.bind(this, function() {
secret.value = secret.entry.get_text();
if (secret.validate)
@ -360,7 +367,7 @@ NetworkSecretDialog.prototype = {
case 'bluetooth':
content.title = _("Mobile broadband network password");
content.message = _("A password is required to connect to '%s'.").format(connectionSetting.get_id());
this._getMobileSecrets(content.secrets);
this._getMobileSecrets(content.secrets, connectionType);
break;
default:
log('Invalid connection type: ' + connectionType);

View File

@ -208,11 +208,11 @@ Overview.prototype = {
this._viewSelector.addViewTab('applications', _("Applications"), appView.actor, 'system-run');
// Default search providers
this._viewSelector.addSearchProvider(new AppDisplay.AppSearchProvider());
this._viewSelector.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this._viewSelector.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
this._viewSelector.addSearchProvider(new DocDisplay.DocSearchProvider());
this._viewSelector.addSearchProvider(new ContactDisplay.ContactSearchProvider());
this.addSearchProvider(new AppDisplay.AppSearchProvider());
this.addSearchProvider(new AppDisplay.SettingsSearchProvider());
this.addSearchProvider(new PlaceDisplay.PlaceSearchProvider());
this.addSearchProvider(new DocDisplay.DocSearchProvider());
this.addSearchProvider(new ContactDisplay.ContactSearchProvider());
// TODO - recalculate everything when desktop size changes
this._dash = new Dash.Dash();
@ -233,6 +233,14 @@ Overview.prototype = {
this._relayout();
},
addSearchProvider: function(provider) {
this._viewSelector.addSearchProvider(provider);
},
removeSearchProvider: function(provider) {
this._viewSelector.removeSearchProvider(provider);
},
setMessage: function(text, undoCallback, undoLabel) {
if (this.isDummy)
return;

View File

@ -16,7 +16,6 @@ const Layout = imports.ui.layout;
const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
const UserMenu = imports.ui.userMenu;
const DateMenu = imports.ui.dateMenu;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -28,29 +27,31 @@ const BUTTON_DND_ACTIVATION_TIMEOUT = 250;
const ANIMATED_ICON_UPDATE_TIMEOUT = 100;
const SPINNER_ANIMATION_TIME = 0.2;
const STANDARD_TRAY_ICON_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery'];
const STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION = {
const STANDARD_STATUS_AREA_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery', 'userMenu'];
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] = imports.ui.status.bluetooth.Indicator;
try {
STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] = imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const GDM_TRAY_ICON_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery'];
const GDM_TRAY_ICON_SHELL_IMPLEMENTATION = {
const GDM_STATUS_AREA_ORDER = ['a11y', 'display', 'keyboard', 'volume', 'battery', 'powerMenu'];
const GDM_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton
};
// To make sure the panel corners blend nicely with the panel,
@ -248,7 +249,7 @@ AppMenuButton.prototype = {
this._targetApp = null;
let bin = new St.Bin({ name: 'appMenu' });
this.actor.set_child(bin);
this.actor.add_actor(bin);
this.actor.reactive = false;
this._targetIsCurrent = false;
@ -292,8 +293,9 @@ AppMenuButton.prototype = {
this._spinner.actor.lower_bottom();
let tracker = Shell.WindowTracker.get_default();
let appSys = Shell.AppSystem.get_default();
tracker.connect('notify::focus-app', Lang.bind(this, this._sync));
tracker.connect('app-state-changed', Lang.bind(this, this._onAppStateChanged));
appSys.connect('app-state-changed', Lang.bind(this, this._onAppStateChanged));
global.window_manager.connect('switch-workspace', Lang.bind(this, this._sync));
@ -457,7 +459,7 @@ AppMenuButton.prototype = {
this._targetApp.request_quit();
},
_onAppStateChanged: function(tracker, app) {
_onAppStateChanged: function(appSys, app) {
let state = app.state;
if (state != Shell.AppState.STARTING) {
this._startingApps = this._startingApps.filter(function(a) {
@ -562,10 +564,10 @@ ActivitiesButton.prototype = {
PanelMenu.Button.prototype._init.call(this, 0.0);
let container = new Shell.GenericContainer();
container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
container.connect('allocate', Lang.bind(this, this._allocate));
this.actor.child = container;
container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
container.connect('allocate', Lang.bind(this, this._containerAllocate));
this.actor.add_actor(container);
this.actor.name = 'panelActivities';
/* Translators: If there is no suitable word for "Activities"
@ -597,15 +599,15 @@ ActivitiesButton.prototype = {
this._xdndTimeOut = 0;
},
_getPreferredWidth: function(actor, forHeight, alloc) {
_containerGetPreferredWidth: function(actor, forHeight, alloc) {
[alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
},
_getPreferredHeight: function(actor, forWidth, alloc) {
_containerGetPreferredHeight: function(actor, forWidth, alloc) {
[alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
},
_allocate: function(actor, box, flags) {
_containerAllocate: function(actor, box, flags) {
this._label.allocate(box, flags);
// The hot corner needs to be outside any padding/alignment
@ -763,16 +765,28 @@ PanelCorner.prototype = {
},
_boxStyleChanged: function() {
let button;
let side = this._side;
let rtlAwareContainer = this._box instanceof St.BoxLayout;
if (rtlAwareContainer &&
this._box.get_direction() == St.TextDirection.RTL) {
if (this._side == St.Side.LEFT)
button = this._findLeftmostButton(this._box);
side = St.Side.RIGHT;
else if (this._side == St.Side.RIGHT)
side = St.Side.LEFT;
}
let button;
if (side == St.Side.LEFT)
button = this._findLeftmostButton(this._box);
else if (side == St.Side.RIGHT)
button = this._findRightmostButton(this._box);
if (button) {
if (this._button && this._buttonStyleChangedSignalId)
if (this._button && this._buttonStyleChangedSignalId) {
this._button.disconnect(this._buttonStyleChangedSignalId);
this._button.style = null;
}
this._button = button;
@ -790,6 +804,10 @@ PanelCorner.prototype = {
let pseudoClass = button.get_style_pseudo_class();
this.actor.set_style_pseudo_class(pseudoClass);
}));
// The corner doesn't support theme transitions, so override
// the .panel-button default
button.style = 'transition-duration: 0';
}
},
@ -884,14 +902,6 @@ Panel.prototype = {
this.actor.remove_style_class_name('in-overview');
}));
if (global.session_type == Shell.SessionType.GDM) {
this._tray_icon_order = GDM_TRAY_ICON_ORDER;
this._tray_icon_shell_implementation = GDM_TRAY_ICON_SHELL_IMPLEMENTATION;
} else {
this._tray_icon_order = STANDARD_TRAY_ICON_ORDER;
this._tray_icon_shell_implementation = STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION;
}
this._menus = new PopupMenu.PopupMenuManager(this);
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
@ -942,21 +952,12 @@ Panel.prototype = {
this._menus.addMenu(this._dateMenu.menu);
/* right */
// System status applets live in statusBox, while legacy tray icons
// live in trayBox
// The trayBox is hidden when there are no tray icons.
this._trayBox = new St.BoxLayout({ name: 'legacyTray' });
this._statusBox = new St.BoxLayout({ name: 'statusTray' });
this._trayBox.hide();
this._rightBox.add(this._trayBox);
this._rightBox.add(this._statusBox);
if (global.session_type == Shell.SessionType.USER) {
this._userMenu = new UserMenu.UserMenuButton();
this._userMenu.actor.name = 'panelStatus';
this._rightBox.add(this._userMenu.actor);
if (global.session_type == Shell.SessionType.GDM) {
this._status_area_order = GDM_STATUS_AREA_ORDER;
this._status_area_shell_implementation = GDM_STATUS_AREA_SHELL_IMPLEMENTATION;
} else {
this._status_area_order = STANDARD_STATUS_AREA_ORDER;
this._status_area_shell_implementation = STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION;
}
Main.statusIconDispatcher.connect('status-icon-added', Lang.bind(this, this._onTrayIconAdded));
@ -1042,9 +1043,9 @@ Panel.prototype = {
},
startStatusArea: function() {
for (let i = 0; i < this._tray_icon_order.length; i++) {
let role = this._tray_icon_order[i];
let constructor = this._tray_icon_shell_implementation[role];
for (let i = 0; i < this._status_area_order.length; i++) {
let role = this._status_area_order[i];
let constructor = this._status_area_shell_implementation[role];
if (!constructor) {
// This icon is not implemented (this is a bug)
continue;
@ -1053,11 +1054,23 @@ Panel.prototype = {
let indicator = new constructor();
this.addToStatusArea(role, indicator, i);
}
},
// PopupMenuManager depends on menus being added in order for
// keyboard navigation
if (this._userMenu)
this._menus.addMenu(this._userMenu.menu);
_insertStatusItem: function(actor, position) {
let children = this._rightBox.get_children();
let i;
for (i = children.length - 1; i >= 0; i--) {
let rolePosition = children[i]._rolePosition;
if (position > rolePosition) {
this._rightBox.insert_actor(actor, i + 1);
break;
}
}
if (i == -1) {
// If we didn't find a position, we must be first
this._rightBox.insert_actor(actor, 0);
}
actor._rolePosition = position;
},
addToStatusArea: function(role, indicator, position) {
@ -1069,8 +1082,7 @@ Panel.prototype = {
if (!position)
position = 0;
this._statusBox.insert_actor(indicator.actor, position);
this._insertStatusItem(indicator.actor, position);
this._menus.addMenu(indicator.menu);
this._statusArea[role] = indicator;
@ -1083,39 +1095,24 @@ Panel.prototype = {
},
_onTrayIconAdded: function(o, icon, role) {
icon.height = PANEL_ICON_SIZE;
if (this._tray_icon_shell_implementation[role]) {
if (this._status_area_shell_implementation[role]) {
// This icon is legacy, and replaced by a Shell version
// Hide it
return;
}
// Figure out the index in our well-known order for this icon
let position = this._tray_icon_order.indexOf(role);
icon._rolePosition = position;
let children = this._trayBox.get_children();
let i;
// Walk children backwards, until we find one that isn't
// well-known, or one where we should follow
for (i = children.length - 1; i >= 0; i--) {
let rolePosition = children[i]._rolePosition;
if (!rolePosition || position > rolePosition) {
this._trayBox.insert_actor(icon, i + 1);
break;
}
}
if (i == -1) {
// If we didn't find a position, we must be first
this._trayBox.insert_actor(icon, 0);
}
// Make sure the trayBox is shown.
this._trayBox.show();
icon.height = PANEL_ICON_SIZE;
let buttonBox = new PanelMenu.ButtonBox();
let box = buttonBox.actor;
box.add_actor(icon);
this._insertStatusItem(box, this._status_area_order.indexOf(role));
},
_onTrayIconRemoved: function(o, icon) {
if (icon.get_parent() != null)
this._trayBox.remove_actor(icon);
let box = icon.get_parent();
if (box && box._delegate instanceof PanelMenu.ButtonBox)
box.destroy();
},
};

View File

@ -2,26 +2,110 @@
const Clutter = imports.gi.Clutter;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Lang = imports.lang;
const PopupMenu = imports.ui.popupMenu;
const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
function ButtonBox(params) {
this._init.apply(this, arguments);
};
ButtonBox.prototype = {
_init: function(params) {
params = Params.parse(params, { style_class: 'panel-button' }, true);
this.actor = new Shell.GenericContainer(params);
this.actor._delegate = this;
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.connect('style-changed', Lang.bind(this, this._onStyleChanged));
this._minHPadding = this._natHPadding = 0.0;
},
_onStyleChanged: function(actor) {
let themeNode = actor.get_theme_node();
this._minHPadding = themeNode.get_length('-minimum-hpadding');
this._natHPadding = themeNode.get_length('-natural-hpadding');
},
_getPreferredWidth: function(actor, forHeight, alloc) {
let children = actor.get_children();
let child = children.length > 0 ? children[0] : null;
if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_width(-1);
} else {
alloc.min_size = alloc.natural_size = 0;
}
alloc.min_size += 2 * this._minHPadding;
alloc.natural_size += 2 * this._natHPadding;
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let children = actor.get_children();
let child = children.length > 0 ? children[0] : null;
if (child) {
[alloc.min_size, alloc.natural_size] = child.get_preferred_height(-1);
} else {
alloc.min_size = alloc.natural_size = 0;
}
},
_allocate: function(actor, box, flags) {
let children = actor.get_children();
if (children.length == 0)
return;
let child = children[0];
let [minWidth, natWidth] = child.get_preferred_width(-1);
let [minHeight, natHeight] = child.get_preferred_height(-1);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let childBox = new Clutter.ActorBox();
if (natWidth + 2 * this._natHPadding <= availWidth) {
childBox.x1 = this._natHPadding;
childBox.x2 = availWidth - this._natHPadding;
} else {
childBox.x1 = this._minHPadding;
childBox.x2 = availWidth - this._minHPadding;
}
if (natHeight <= availHeight) {
childBox.y1 = Math.floor((availHeight - natHeight) / 2);
childBox.y2 = childBox.y1 + natHeight;
} else {
childBox.y1 = 0;
childBox.y2 = availHeight;
}
child.allocate(childBox, flags);
},
}
function Button(menuAlignment) {
this._init(menuAlignment);
}
Button.prototype = {
__proto__: ButtonBox.prototype,
_init: function(menuAlignment) {
this.actor = new St.Bin({ style_class: 'panel-button',
reactive: true,
ButtonBox.prototype._init.call(this, { reactive: true,
can_focus: true,
x_fill: true,
y_fill: false,
track_hover: true });
this.actor._delegate = this;
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
this.menu = new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP);
@ -112,7 +196,8 @@ SystemStatusButton.prototype = {
this._iconActor = new St.Icon({ icon_name: iconName,
icon_type: St.IconType.SYMBOLIC,
style_class: 'system-status-icon' });
this.actor.set_child(this._iconActor);
this.actor.add_actor(this._iconActor);
this.actor.add_style_class_name('panel-status-button');
this.setTooltip(tooltipText);
},

View File

@ -142,6 +142,7 @@ AuthenticationDialog.prototype = {
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onEntryActivate));
this._passwordBox.add(this._passwordEntry,
{expand: true });
this.setInitialKeyFocus(this._passwordEntry);
this._passwordBox.hide();
this._errorMessageLabel = new St.Label({ style_class: 'polkit-dialog-error-label' });
@ -186,13 +187,6 @@ AuthenticationDialog.prototype = {
this._session.connect('request', Lang.bind(this, this._onSessionRequest));
this._session.connect('show-error', Lang.bind(this, this._onSessionShowError));
this._session.connect('show-info', Lang.bind(this, this._onSessionShowInfo));
// Delay focus grab to avoid ModalDialog stealing focus with
// its buttons
this.connect('opened',
Lang.bind(this, function() {
this._passwordEntry.grab_key_focus();
}));
},
startAuthentication: function() {

View File

@ -35,6 +35,7 @@ PopupBaseMenuItem.prototype = {
params = Params.parse (params, { reactive: true,
activate: true,
hover: true,
sensitive: true,
style_class: null
});
this.actor = new Shell.GenericContainer({ style_class: 'popup-menu-item',
@ -52,11 +53,15 @@ PopupBaseMenuItem.prototype = {
this._columnWidths = null;
this._spacing = 0;
this.active = false;
this._activatable = params.reactive && params.activate;
this.sensitive = this._activatable && params.sensitive;
this.setSensitive(this.sensitive);
if (params.style_class)
this.actor.add_style_class_name(params.style_class);
if (params.reactive && params.activate) {
if (this._activatable) {
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
}
@ -117,6 +122,23 @@ PopupBaseMenuItem.prototype = {
}
},
setSensitive: function(sensitive) {
if (!this._activatable)
return;
if (this.sensitive == sensitive)
return;
this.sensitive = sensitive;
this.actor.reactive = sensitive;
this.actor.can_focus = sensitive;
if (sensitive)
this.actor.remove_style_pseudo_class('insensitive');
else
this.actor.add_style_pseudo_class('insensitive');
this.emit('sensitive-changed', sensitive);
},
destroy: function() {
this.actor.destroy();
this.emit('destroy');
@ -214,7 +236,7 @@ PopupBaseMenuItem.prototype = {
let child = this._children[i];
if (i > 0)
width += this._spacing;
let [min, natural] = child.actor.get_preferred_width(forHeight);
let [min, natural] = child.actor.get_preferred_width(-1);
width += natural;
}
}
@ -222,10 +244,25 @@ PopupBaseMenuItem.prototype = {
},
_getPreferredHeight: function(actor, forWidth, alloc) {
let height = 0;
let height = 0, x = 0, minWidth, childWidth;
for (let i = 0; i < this._children.length; i++) {
let child = this._children[i];
let [min, natural] = child.actor.get_preferred_height(-1);
if (this._columnWidths) {
if (child.span == -1) {
childWidth = 0;
for (let j = i; j < this._columnWidths.length; j++)
childWidth += this._columnWidths[j]
} else
childWidth = this._columnWidths[i];
} else {
if (child.span == -1)
childWidth = forWidth - x;
else
[minWidth, childWidth] = child.actor.get_preferred_width(-1);
}
x += childWidth;
let [min, natural] = child.actor.get_preferred_height(childWidth);
if (natural > height)
height = natural;
}
@ -282,8 +319,15 @@ PopupBaseMenuItem.prototype = {
availWidth += this._columnWidths[col++];
}
extraWidth = availWidth - naturalWidth;
} else {
if (child.span == -1) {
if (direction == St.TextDirection.LTR)
availWidth = box.x2 - x;
else
availWidth = x - box.x1;
} else {
availWidth = naturalWidth;
}
extraWidth = 0;
}
@ -291,7 +335,7 @@ PopupBaseMenuItem.prototype = {
if (child.expand) {
childBox.x1 = x;
childBox.x2 = x + availWidth;
} else if (child.align === St.Align.CENTER) {
} else if (child.align === St.Align.MIDDLE) {
childBox.x1 = x + Math.round(extraWidth / 2);
childBox.x2 = childBox.x1 + naturalWidth;
} else if (child.align === St.Align.END) {
@ -305,7 +349,7 @@ PopupBaseMenuItem.prototype = {
if (child.expand) {
childBox.x1 = x - availWidth;
childBox.x2 = x;
} else if (child.align === St.Align.CENTER) {
} else if (child.align === St.Align.MIDDLE) {
childBox.x1 = x - Math.round(extraWidth / 2);
childBox.x2 = childBox.x1 + naturalWidth;
} else if (child.align === St.Align.END) {
@ -319,7 +363,7 @@ PopupBaseMenuItem.prototype = {
}
}
let [minHeight, naturalHeight] = child.actor.get_preferred_height(-1);
let [minHeight, naturalHeight] = child.actor.get_preferred_height(childBox.x2 - childBox.x1);
childBox.y1 = Math.round(box.y1 + (height - naturalHeight) / 2);
childBox.y2 = childBox.y1 + naturalHeight;
@ -899,6 +943,17 @@ PopupMenuBase.prototype = {
this.emit('active-changed', null);
}
}));
menuItem._sensitiveChangeId = menuItem.connect('sensitive-changed', Lang.bind(this, function(menuItem, sensitive) {
if (!sensitive && this._activeMenuItem == menuItem) {
if (!this.actor.navigate_focus(menuItem.actor,
Gtk.DirectionType.TAB_FORWARD,
true))
this.actor.grab_key_focus();
} else if (sensitive && this._activeMenuItem == null) {
if (global.stage.get_key_focus() == this.actor)
menuItem.actor.grab_key_focus();
}
}));
menuItem._activateId = menuItem.connect('activate', Lang.bind(this, function (menuItem, event) {
this.emit('activate', menuItem);
this.close(true);
@ -906,6 +961,7 @@ PopupMenuBase.prototype = {
menuItem.connect('destroy', Lang.bind(this, function(emitter) {
menuItem.disconnect(menuItem._activateId);
menuItem.disconnect(menuItem._activeChangeId);
menuItem.disconnect(menuItem._sensitiveChangeId);
if (menuItem.menu) {
menuItem.menu.disconnect(menuItem._subMenuActivateId);
menuItem.menu.disconnect(menuItem._subMenuActiveChangeId);
@ -1507,6 +1563,10 @@ PopupComboMenu.prototype = {
}
this._getMenuItems()[position].actor.visible = visible;
},
getItemVisible: function(position) {
return this._getMenuItems()[position].actor.visible;
}
};
@ -1524,7 +1584,8 @@ PopupComboBoxMenuItem.prototype = {
this.addActor(this._itemBox);
let expander = new St.Label({ text: '\u2304' });
this.addActor(expander, { align: St.Align.END });
this.addActor(expander, { align: St.Align.END,
span: -1 });
this._menu = new PopupComboMenu(this.actor);
Main.uiGroup.add_actor(this._menu.actor);
@ -1533,6 +1594,8 @@ PopupComboBoxMenuItem.prototype = {
if (params.style_class)
this._menu.actor.add_style_class_name(params.style_class);
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this._activeItemPos = -1;
this._items = [];
},
@ -1551,6 +1614,33 @@ PopupComboBoxMenuItem.prototype = {
return null;
},
_onScrollEvent: function(actor, event) {
if (this._activeItemPos == -1)
return;
let position = this._activeItemPos;
let direction = event.get_scroll_direction();
if (direction == Clutter.ScrollDirection.DOWN) {
while (position < this._items.length - 1) {
position++;
if (this._menu.getItemVisible(position))
break;
}
} else if (direction == Clutter.ScrollDirection.UP) {
while (position > 0) {
position--;
if (this._menu.getItemVisible(position))
break;
}
}
if (position == this._activeItemPos)
return;
this.setActiveItem(position);
this.emit('active-item-changed', position);
},
activate: function(event) {
let topMenu = this._getTopMenu();
if (!topMenu)

View File

@ -112,6 +112,43 @@ function SearchProvider(title) {
SearchProvider.prototype = {
_init: function(title) {
this.title = title;
this.searchSystem = null;
this.searchAsync = false;
},
_asyncCancelled: function() {
},
startAsync: function() {
this.searchAsync = true;
},
tryCancelAsync: function() {
if (!this.searchAsync)
return;
this._asyncCancelled();
this.searchAsync = false;
},
/**
* addItems:
* @items: an array of result identifier strings representing
* items which match the last given search terms.
*
* This should be used for something that requires a bit more
* logic; it's designed to be an asyncronous way to add a result
* to the current search.
*/
addItems: function(items) {
if (!this.searchSystem)
throw new Error('Search provider not registered');
if (!items.length)
return;
this.tryCancelAsync();
this.searchSystem.addProviderItems(this, items);
},
/**
@ -315,9 +352,18 @@ SearchSystem.prototype = {
},
registerProvider: function (provider) {
provider.searchSystem = this;
this._providers.push(provider);
},
unregisterProvider: function (provider) {
let index = this._providers.indexOf(provider);
if (index == -1)
return;
provider.searchSystem = null;
this._providers.splice(index, 1);
},
getProviders: function() {
return this._providers;
},
@ -331,12 +377,23 @@ SearchSystem.prototype = {
this._previousResults = [];
},
addProviderItems: function(provider, items) {
this.emit('search-updated', provider, items);
},
updateSearch: function(searchString) {
searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
if (searchString == '')
return [];
return;
let terms = searchString.split(/\s+/);
this.updateSearchResults(terms);
},
updateSearchResults: function(terms) {
if (!terms)
return;
let isSubSearch = terms.length == this._previousTerms.length;
if (isSubSearch) {
for (let i = 0; i < terms.length; i++) {
@ -349,11 +406,11 @@ SearchSystem.prototype = {
let results = [];
if (isSubSearch) {
for (let i = 0; i < this._previousResults.length; i++) {
for (let i = 0; i < this._providers.length; i++) {
let [provider, previousResults] = this._previousResults[i];
provider.tryCancelAsync();
try {
let providerResults = provider.getSubsearchResultSet(previousResults, terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
} catch (error) {
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
@ -362,9 +419,9 @@ SearchSystem.prototype = {
} else {
for (let i = 0; i < this._providers.length; i++) {
let provider = this._providers[i];
provider.tryCancelAsync();
try {
let providerResults = provider.getInitialResultSet(terms);
if (providerResults.length > 0)
results.push([provider, providerResults]);
} catch (error) {
global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
@ -374,8 +431,7 @@ SearchSystem.prototype = {
this._previousTerms = terms;
this._previousResults = results;
return results;
}
this.emit('search-completed', results);
},
};
Signals.addSignalMethods(SearchSystem.prototype);

View File

@ -189,6 +189,8 @@ function SearchResults(searchSystem, openSearchSystem) {
SearchResults.prototype = {
_init: function(searchSystem, openSearchSystem) {
this._searchSystem = searchSystem;
this._searchSystem.connect('search-updated', Lang.bind(this, this._updateCurrentResults));
this._searchSystem.connect('search-completed', Lang.bind(this, this._updateResults));
this._openSearchSystem = openSearchSystem;
this.actor = new St.BoxLayout({ name: 'searchResults',
@ -223,9 +225,11 @@ SearchResults.prototype = {
this._selectedProvider = -1;
this._providers = this._searchSystem.getProviders();
this._providerMeta = [];
for (let i = 0; i < this._providers.length; i++)
this._providerMetaResults = {};
for (let i = 0; i < this._providers.length; i++) {
this.createProviderMeta(this._providers[i]);
this._providerMetaResults[this.providers[i].title] = [];
}
this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
this.actor.add(this._searchProvidersBox);
@ -290,11 +294,23 @@ SearchResults.prototype = {
}
resultDisplayBin.set_child(resultDisplay.actor);
this._providerMeta.push({ actor: providerBox,
this._providerMeta.push({ provider: provider,
actor: providerBox,
resultDisplay: resultDisplay });
this._content.add(providerBox);
},
destroyProviderMeta: function(provider) {
for (let i=0; i < this._providerMeta.length; i++) {
let meta = this._providerMeta[i];
if (meta.provider == provider) {
meta.actor.destroy();
this._providerMeta.splice(i, 1);
break;
}
}
},
_clearDisplay: function() {
this._selectedProvider = -1;
this._visibleResultsCount = 0;
@ -305,6 +321,12 @@ SearchResults.prototype = {
}
},
_clearDisplayForProvider: function(index) {
let meta = this._providerMeta[index];
meta.resultDisplay.clear();
meta.actor.hide();
},
reset: function() {
this._searchSystem.reset();
this._statusText.hide();
@ -319,15 +341,24 @@ SearchResults.prototype = {
this._statusText.show();
},
doSearch: function (searchString) {
this._searchSystem.updateSearch(searchString);
},
_metaForProvider: function(provider) {
return this._providerMeta[this._providers.indexOf(provider)];
},
updateSearch: function (searchString) {
let results = this._searchSystem.updateSearch(searchString);
this._clearDisplay();
_updateCurrentResults: function(searchSystem, provider, results) {
let terms = searchSystem.getTerms();
let meta = this._metaForProvider(provider);
meta.resultDisplay.clear();
meta.actor.show();
meta.resultDisplay.renderResults(results, terms);
return true;
},
_updateResults: function(searchSystem, results) {
if (results.length == 0) {
this._statusText.set_text(_("No matching results."));
this._statusText.show();
@ -337,7 +368,7 @@ SearchResults.prototype = {
this._statusText.hide();
}
let terms = this._searchSystem.getTerms();
let terms = searchSystem.getTerms();
this._openSearchSystem.setSearchTerms(terms);
// To avoid CSS transitions causing flickering
@ -349,10 +380,16 @@ SearchResults.prototype = {
for (let i = 0; i < results.length; i++) {
let [provider, providerResults] = results[i];
if (providerResults.length == 0) {
this._clearDisplayForProvider(i);
} else {
this._providerMetaResults[provider.title] = providerResults;
this._clearDisplayForProvider(i);
let meta = this._metaForProvider(provider);
meta.actor.show();
meta.resultDisplay.renderResults(providerResults, terms);
}
}
if (this._selectedOpenSearchButton == -1)
this.selectDown(false);

View File

@ -46,8 +46,12 @@ const GnomeShellIface = {
outSignature: ''
},
{ name: 'InstallRemoteExtension',
inSignature: 's',
inSignature: 'ss',
outSignature: ''
},
{ name: 'UninstallExtension',
inSignature: 's',
outSignature: 'b'
}
],
signals: [{ name: 'ExtensionStatusChanged',
@ -174,8 +178,12 @@ GnomeShell.prototype = {
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
},
InstallRemoteExtension: function(uuid, url) {
ExtensionSystem.installExtensionFromManifestURL(uuid, url);
InstallRemoteExtension: function(uuid, version_tag) {
ExtensionSystem.installExtensionFromUUID(uuid, version_tag);
},
UninstallExtension: function(uuid) {
return ExtensionSystem.uninstallExtensionFromUUID(uuid);
},
get OverviewActive() {
@ -189,7 +197,7 @@ GnomeShell.prototype = {
Main.overview.hide();
},
ApiVersion: 1,
ApiVersion: ExtensionSystem.API_VERSION,
ShellVersion: Config.PACKAGE_VERSION,

View File

@ -68,9 +68,9 @@ ATIndicator.prototype = {
// 'screen-reader-enabled');
// this.menu.addMenuItem(screenReader);
// let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
// 'screen-keyboard-enabled');
// this.menu.addMenuItem(screenKeyboard);
let screenKeyboard = this._buildItem(_("Screen Keyboard"), APPLICATIONS_SCHEMA,
'screen-keyboard-enabled');
this.menu.addMenuItem(screenKeyboard);
let visualBell = this._buildItemGConf(_("Visual Alerts"), client, KEY_VISUAL_BELL);
this.menu.addMenuItem(visualBell);

View File

@ -49,10 +49,11 @@ XKBIndicator.prototype = {
PanelMenu.Button.prototype._init.call(this, St.Align.START);
this._container = new Shell.GenericContainer();
this._container.connect('get-preferred-width', Lang.bind(this, this._get_preferred_width));
this._container.connect('get-preferred-height', Lang.bind(this, this._get_preferred_height));
this._container.connect('allocate', Lang.bind(this, this._allocate));
this.actor.set_child(this._container);
this._container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
this._container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
this._container.connect('allocate', Lang.bind(this, this._containerAllocate));
this.actor.add_actor(this._container);
this.actor.add_style_class_name('panel-status-button');
this._iconActor = new St.Icon({ icon_name: 'keyboard', icon_type: St.IconType.SYMBOLIC, style_class: 'system-status-icon' });
this._container.add_actor(this._iconActor);
@ -61,21 +62,23 @@ XKBIndicator.prototype = {
this._showFlags = false;
this._config = Gkbd.Configuration.get();
this._config.connect('changed', Lang.bind(this, this._sync_config));
this._config.connect('group-changed', Lang.bind(this, this._sync_group));
this._config.connect('changed', Lang.bind(this, this._syncConfig));
this._config.connect('group-changed', Lang.bind(this, this._syncGroup));
this._config.start_listen();
this._sync_config();
this._syncConfig();
if (global.session_type == Shell.SessionType.USER) {
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
this.menu.addAction(_("Show Keyboard Layout"), Lang.bind(this, function() {
Main.overview.hide();
Util.spawn(['gkbd-keyboard-display', '-g', String(this._config.get_current_group() + 1)]);
}));
}
this.menu.addSettingsAction(_("Region and Language Settings"), 'gnome-region-panel.desktop');
},
_adjust_group_names: function(names) {
_adjustGroupNames: function(names) {
// Disambiguate duplicate names with a subscript
// This is O(N^2) to avoid sorting names
// but N <= 4 so who cares?
@ -97,7 +100,7 @@ XKBIndicator.prototype = {
return names;
},
_sync_config: function() {
_syncConfig: function() {
this._showFlags = this._config.if_flags_shown();
if (this._showFlags) {
this._container.set_skip_paint(this._iconActor, false);
@ -119,7 +122,7 @@ XKBIndicator.prototype = {
for (let i = 0; i < this._labelActors.length; i++)
this._labelActors[i].destroy();
let short_names = this._adjust_group_names(this._config.get_short_group_names());
let short_names = this._adjustGroupNames(this._config.get_short_group_names());
this._selectedLayout = null;
this._layoutItems = [ ];
@ -144,10 +147,10 @@ XKBIndicator.prototype = {
this._container.set_skip_paint(shortLabel, true);
}
this._sync_group();
this._syncGroup();
},
_sync_group: function() {
_syncGroup: function() {
let selected = this._config.get_current_group();
if (this._selectedLayout) {
@ -170,10 +173,10 @@ XKBIndicator.prototype = {
this._selectedLayout = item;
},
_get_preferred_width: function(container, for_height, alloc) {
/* Here, and in _get_preferred_height, we need to query for the
height of all children, but we ignore the results for those
we don't actually display. */
_containerGetPreferredWidth: function(container, for_height, alloc) {
// Here, and in _containerGetPreferredHeight, we need to query
// for the height of all children, but we ignore the results
// for those we don't actually display.
let max_min_width = 0, max_natural_width = 0;
if (this._showFlags)
[max_min_width, max_natural_width] = this._iconActor.get_preferred_width(for_height);
@ -190,7 +193,7 @@ XKBIndicator.prototype = {
alloc.natural_size = max_natural_width;
},
_get_preferred_height: function(container, for_width, alloc) {
_containerGetPreferredHeight: function(container, for_width, alloc) {
let max_min_height = 0, max_natural_height = 0;
if (this._showFlags)
[max_min_height, max_natural_height] = this._iconActor.get_preferred_height(for_width);
@ -207,7 +210,7 @@ XKBIndicator.prototype = {
alloc.natural_size = max_natural_height;
},
_allocate: function(container, box, flags) {
_containerAllocate: function(container, box, flags) {
// translate box to (0, 0)
box.x2 -= box.x1;
box.x1 = 0;

View File

@ -1291,6 +1291,9 @@ NMDeviceWireless.prototype = {
apObj.accessPoints.splice(i, 1);
if (apObj.accessPoints.length == 0) {
if (this._activeNetwork == apObj)
this._activeNetwork = null;
if (apObj.item)
apObj.item.destroy();
@ -1480,6 +1483,11 @@ NMDeviceWireless.prototype = {
},
_createNetworkItem: function(apObj, position) {
if(!apObj.accessPoints || apObj.accessPoints.length == 0) {
// this should not happen, but I have no idea why it happens
return;
}
if(apObj.connections.length > 0) {
if (apObj.connections.length == 1)
apObj.item = this._createAPItem(apObj.connections[0], apObj, false);
@ -1742,13 +1750,6 @@ NMApplet.prototype = {
if (wrapperClass) {
let wrapper = new wrapperClass(this._client, device, this._connections);
wrapper._networkLostId = wrapper.connect('network-lost', Lang.bind(this, function(device) {
this._notifyForDevice(device, 'network-offline',
_("Connectivity lost"),
_("You're no longer connected to the network"),
// set critical urgency to popup the notification automatically
MessageTray.Urgency.CRITICAL);
}));
wrapper._activationFailedId = wrapper.connect('activation-failed', Lang.bind(this, function(device, reason) {
// XXX: nm-applet has no special text depending on reason
// but I'm not sure of this generic message
@ -1761,7 +1762,6 @@ NMApplet.prototype = {
this._syncSectionTitle(dev.category);
}));
wrapper._destroyId = wrapper.connect('destroy', function(wrapper) {
wrapper.disconnect(wrapper._networkLostId);
wrapper.disconnect(wrapper._activationFailedId);
wrapper.disconnect(wrapper._deviceStateChangedId);
wrapper.disconnect(wrapper._destroyId);
@ -1828,7 +1828,7 @@ NMApplet.prototype = {
if (!a._inited) {
a._notifyDefaultId = a.connect('notify::default', Lang.bind(this, this._updateIcon));
a._notifyDefault6Id = a.connect('notify::default6', Lang.bind(this, this._updateIcon));
a._notifyStateId = a.connect('notify::state', Lang.bind(this, this._updateIcon));
a._notifyStateId = a.connect('notify::state', Lang.bind(this, this._notifyActivated));
a._inited = true;
}
@ -1872,12 +1872,28 @@ NMApplet.prototype = {
if (a._primaryDevice)
a._primaryDevice.setActiveConnection(a);
if (a.state == NetworkManager.ActiveConnectionState.ACTIVATED
&& a._primaryDevice && a._primaryDevice._notification) {
a._primaryDevice._notification.destroy();
a._primaryDevice._notification = null;
}
}
}
this._mainConnection = activating || default_ip4 || default_ip6 || this._activeConnections[0] || null;
},
_notifyActivated: function(activeConnection) {
if (activeConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED
&& activeConnection._primaryDevice && activeConnection._primaryDevice._notification) {
activeConnection._primaryDevice._notification.destroy();
activeConnection._primaryDevice._notification = null;
}
this._updateIcon();
},
_readConnections: function() {
let connections = this._settings.list_connections();
for (let i = 0; i < connections.length; i++) {

View File

@ -118,7 +118,7 @@ Indicator.prototype = {
timestring = ngettext("%d minute remaining", "%d minutes remaining", minutes).format(minutes);
this._batteryItem.label.text = timestring;
}
this._primaryPercentage.text = Math.round(percentage) + '%';
this._primaryPercentage.text = C_("percent of battery remaining", "%d%%").format(Math.round(percentage));
this._batteryItem.actor.show();
} else {
this._hasPrimary = false;
@ -191,7 +191,7 @@ DeviceItem.prototype = {
this._box.add_actor(this._label);
this.addActor(this._box);
let percentLabel = new St.Label({ text: '%d%%'.format(Math.round(percentage)) });
let percentLabel = new St.Label({ text: C_("percent of battery remaining", "%d%%").format(Math.round(percentage)) });
this.addActor(percentLabel, { align: St.Align.END });
},

View File

@ -35,7 +35,6 @@ Indicator.prototype = {
this._control.connect('stream-added', Lang.bind(this, this._maybeShowInput));
this._control.connect('stream-removed', Lang.bind(this, this._maybeShowInput));
this._volumeMax = this._control.get_vol_max_norm();
this._volumeMaxAmplified = this._control.get_vol_max_amplified();
this._output = null;
this._outputVolumeId = 0;
@ -66,21 +65,13 @@ Indicator.prototype = {
this._control.open();
},
_getMaxVolume: function(property) {
if (this[property].get_can_decibel())
return this._volumeMaxAmplified;
else
return this._volumeMax;
},
_onScrollEvent: function(actor, event) {
let direction = event.get_scroll_direction();
let currentVolume = this._output.volume;
let maxVolume = this._getMaxVolume('_output');
if (direction == Clutter.ScrollDirection.DOWN) {
let prev_muted = this._output.is_muted;
this._output.volume = Math.max(0, currentVolume - maxVolume * VOLUME_ADJUSTMENT_STEP);
this._output.volume = Math.max(0, currentVolume - this._volumeMax * VOLUME_ADJUSTMENT_STEP);
if (this._output.volume < 1) {
this._output.volume = 0;
if (!prev_muted)
@ -89,7 +80,7 @@ Indicator.prototype = {
this._output.push_volume();
}
else if (direction == Clutter.ScrollDirection.UP) {
this._output.volume = Math.min(maxVolume, currentVolume + maxVolume * VOLUME_ADJUSTMENT_STEP);
this._output.volume = Math.min(this._volumeMax, currentVolume + this._volumeMax * VOLUME_ADJUSTMENT_STEP);
this._output.change_is_muted(false);
this._output.push_volume();
}
@ -171,11 +162,10 @@ Indicator.prototype = {
},
_volumeToIcon: function(volume) {
let maxVolume = this._getMaxVolume('_output');
if (volume <= 0) {
return 'audio-volume-muted';
} else {
let n = Math.floor(3 * volume / maxVolume) + 1;
let n = Math.floor(3 * volume / this._volumeMax) + 1;
if (n < 2)
return 'audio-volume-low';
if (n >= 3)
@ -189,7 +179,7 @@ Indicator.prototype = {
log ('Volume slider changed for %s, but %s does not exist'.format(property, property));
return;
}
let volume = value * this._getMaxVolume(property);
let volume = value * this._volumeMax;
let prev_muted = this[property].is_muted;
if (volume < 1) {
this[property].volume = 0;
@ -211,8 +201,7 @@ Indicator.prototype = {
_mutedChanged: function(object, param_spec, property) {
let muted = this[property].is_muted;
let slider = this[property+'Slider'];
let maxVolume = this._getMaxVolume(property);
slider.setValue(muted ? 0 : (this[property].volume / maxVolume));
slider.setValue(muted ? 0 : (this[property].volume / this._volumeMax));
if (property == '_output') {
if (muted)
this.setIcon('audio-volume-muted');
@ -222,8 +211,7 @@ Indicator.prototype = {
},
_volumeChanged: function(object, param_spec, property) {
let maxVolume = this._getMaxVolume(property);
this[property+'Slider'].setValue(this[property].volume / maxVolume);
this[property+'Slider'].setValue(this[property].volume / this._volumeMax);
if (property == '_output' && !this._output.is_muted)
this.setIcon(this._volumeToIcon(this._output.volume));
}

View File

@ -83,6 +83,9 @@ Client.prototype = {
this._chatSources = {};
this._chatState = Tp.ChannelChatState.ACTIVE;
// account path -> AccountNotification
this._accountNotifications = {};
// Set up a SimpleObserver, which will call _observeChannels whenever a
// channel matching its filters is detected.
// The second argument, recover, means _observeChannels will be run
@ -302,6 +305,8 @@ Client.prototype = {
Shell.get_tp_contacts(conn, [targetHandle],
contactFeatures,
Lang.bind(this, this._createAudioVideoSource, channel, context, dispatchOp));
context.delay();
},
_createAudioVideoSource: function(connection, contacts, failed, channel, context, dispatchOp) {
@ -335,6 +340,8 @@ Client.prototype = {
Shell.get_tp_contacts(conn, [targetHandle],
contactFeatures,
Lang.bind(this, this._createFileTransferSource, channel, context, dispatchOp));
context.delay();
},
_createFileTransferSource: function(connection, contacts, failed, channel, context, dispatchOp) {
@ -420,7 +427,6 @@ Client.prototype = {
/* Display notification to ask user to accept/reject request */
let source = this._ensureSubscriptionSource();
Main.messageTray.add(source);
let notif = new SubscriptionRequestNotification(source, contact);
source.notify(notif);
@ -430,6 +436,7 @@ Client.prototype = {
if (this._subscriptionSource == null) {
this._subscriptionSource = new MultiNotificationSource(
_("Subscription request"), 'gtk-dialog-question');
Main.messageTray.add(this._subscriptionSource);
this._subscriptionSource.connect('destroy', Lang.bind(this, function () {
this._subscriptionSource = null;
}));
@ -446,11 +453,18 @@ Client.prototype = {
return;
}
let notif = this._accountNotifications[account.get_object_path()];
if (notif)
return;
/* Display notification that account failed to connect */
let source = this._ensureAccountSource();
Main.messageTray.add(source);
let notif = new AccountNotification(source, account, connectionError);
notif = new AccountNotification(source, account, connectionError);
this._accountNotifications[account.get_object_path()] = notif;
notif.connect('destroy', Lang.bind(this, function() {
delete this._accountNotifications[account.get_object_path()];
}));
source.notify(notif);
},
@ -458,6 +472,7 @@ Client.prototype = {
if (this._accountSource == null) {
this._accountSource = new MultiNotificationSource(
_("Connection error"), 'gtk-dialog-error');
Main.messageTray.add(this._accountSource);
this._accountSource.connect('destroy', Lang.bind(this, function () {
this._accountSource = null;
}));
@ -532,13 +547,6 @@ ChatSource.prototype = {
createNotificationIcon: function() {
this._iconBox = new St.Bin({ style_class: 'avatar-box' });
this._iconBox._size = this.ICON_SIZE;
this._updateAvatarIcon();
return this._iconBox;
},
_updateAvatarIcon: function() {
let textureCache = St.TextureCache.get_default();
let file = this._contact.get_avatar_file();
@ -550,6 +558,13 @@ ChatSource.prototype = {
icon_type: St.IconType.FULLCOLOR,
icon_size: this._iconBox._size });
}
return this._iconBox;
},
_updateAvatarIcon: function() {
this._setSummaryIcon(this.createNotificationIcon());
this._notification.update(this._notification.title, null, { customContent: true, icon: this.createNotificationIcon() });
},
open: function(notification) {
@ -1019,7 +1034,7 @@ ChatNotification.prototype = {
IM name. */
let message = '<i>' + _("%s is now known as %s").format(oldAlias, newAlias) + '</i>';
let label = this._append({ body: text,
let label = this._append({ body: message,
group: 'meta',
styles: ['chat-meta-message'] });
@ -1426,8 +1441,7 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CONNECTION_LOST)]
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.ALREADY_CONNECTED)]
= _("This resource is already connected to the server");
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CONNECTION_REPLACED)]
= _("Connection has been replaced by a new connection using the "
+ "same resource");
= _("Connection has been replaced by a new connection using the same resource");
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.REGISTRATION_EXISTS)]
= _("The account already exists on the server");
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.SERVICE_BUSY)]
@ -1435,12 +1449,9 @@ _connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.SERVICE_BUSY)]
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_REVOKED)]
= _("Certificate has been revoked");
_connectionErrorMessages[Tp.error_get_dbus_name(Tp.Error.CERT_INSECURE)]
= _("Certificate uses an insecure cipher algorithm or is "
+ "cryptographically weak");
= _("Certificate uses an insecure cipher algorithm or is cryptographically weak");
_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");
= _("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,
@ -1452,17 +1463,12 @@ AccountNotification.prototype = {
_("Connection to %s failed").format(account.get_display_name()),
null, { customContent: true });
let message;
if (connectionError in _connectionErrorMessages) {
message = _connectionErrorMessages[connectionError];
} else {
message = _("Unknown reason");
}
this._label = new St.Label();
this.addActor(this._label);
this._updateMessage(connectionError);
this._account = account;
this.addBody(message);
this.addButton('reconnect', _("Reconnect"));
this.addButton('edit', _("Edit account"));
@ -1496,11 +1502,25 @@ AccountNotification.prototype = {
this._connectionStatusId = account.connect('notify::connection-status',
Lang.bind(this, function() {
if (account.connection_status != Tp.ConnectionStatus.DISCONNECTED)
let status = account.connection_status;
if (status == Tp.ConnectionStatus.CONNECTED) {
this.destroy();
} else if (status == Tp.ConnectionStatus.DISCONNECTED) {
this._updateMessage(account.connection_error);
}
}));
},
_updateMessage: function(connectionError) {
let message;
if (connectionError in _connectionErrorMessages) {
message = _connectionErrorMessages[connectionError];
} else {
message = _("Unknown reason");
}
this._label.set_text(message);
},
destroy: function() {
if (this._enabledId != 0) {
this._account.disconnect(this._enabledId);

View File

@ -5,6 +5,7 @@ const DBus = imports.dbus;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Tp = imports.gi.TelepathyGLib;
@ -22,7 +23,6 @@ const DISABLE_USER_SWITCH_KEY = 'disable-user-switching';
const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen';
const DISABLE_LOG_OUT_KEY = 'disable-log-out';
const WRAP_WIDTH = 150;
const DIALOG_ICON_SIZE = 64;
const IMStatus = {
@ -87,28 +87,20 @@ IMUserNameItem.prototype = {
this.label = new St.Label();
this.label.clutter_text.set_line_wrap(true);
this.label.clutter_text.set_ellipsize(Pango.EllipsizeMode.NONE);
this._wrapper.add_actor(this.label);
},
_wrapperGetPreferredWidth: function(actor, forHeight, alloc) {
[alloc.min_size, alloc.natural_size] = this.label.get_preferred_width(-1);
if (alloc.natural_size > WRAP_WIDTH)
alloc.natural_size = WRAP_WIDTH;
alloc.min_size = 1;
alloc.natural_size = 1;
},
_wrapperGetPreferredHeight: function(actor, forWidth, alloc) {
let minWidth, natWidth;
[alloc.min_size, alloc.natural_size] = this.label.get_preferred_height(forWidth);
[minWidth, natWidth] = this.label.get_preferred_width(-1);
if (natWidth > WRAP_WIDTH) {
alloc.min_size *= 2;
alloc.natural_size *= 2;
}
},
_wrapperAllocate: function(actor, box, flags) {
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this.label.allocate(box, flags);
}
};
@ -170,6 +162,7 @@ IMStatusChooserItem.prototype = {
this._presence.connect('StatusChanged',
Lang.bind(this, this._sessionStatusChanged));
this._currentPresence = undefined;
this._previousPresence = undefined;
this._accountMgr = Tp.AccountManager.dup()
@ -193,6 +186,10 @@ IMStatusChooserItem.prototype = {
this._userChangedId = this._user.connect('changed',
Lang.bind(this,
this._updateUser));
this.actor.connect('notify::mapped', Lang.bind(this, function() {
if (this.actor.mapped)
this._updateUser();
}));
},
// Override getColumnWidths()/setColumnWidths() to make the item
@ -202,9 +199,6 @@ IMStatusChooserItem.prototype = {
},
setColumnWidths: function(widths) {
this._columnWidths = PopupMenu.PopupBaseMenuItem.prototype.getColumnWidths.call(this);
let sectionWidths = this._section.getColumnWidths();
this._section.setColumnWidths(sectionWidths);
},
_updateUser: function() {
@ -226,6 +220,7 @@ IMStatusChooserItem.prototype = {
_setIconFromFile: function(iconFile) {
this._iconBin.set_style('background-image: url("' + iconFile + '");');
this._iconBin.child = null;
},
_setIconFromName: function(iconName) {
@ -249,23 +244,28 @@ IMStatusChooserItem.prototype = {
_statusForPresence: function(presence) {
switch(presence) {
case Tp.ConnectionPresenceType.AVAILABLE:
return _("Available");
return 'available';
case Tp.ConnectionPresenceType.BUSY:
return _("Busy");
return 'busy';
case Tp.ConnectionPresenceType.OFFLINE:
return _("Unavailable");
return 'offline';
case Tp.ConnectionPresenceType.HIDDEN:
return _("Hidden");
return 'hidden';
case Tp.ConnectionPresenceType.AWAY:
return _("Away");
return 'away';
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
return _("Idle");
return 'xa';
default:
return _("Unknown");
return 'unknown';
}
},
_IMStatusChanged: function(accountMgr, presence, status, message) {
if (presence == this._currentPresence)
return;
this._currentPresence = presence;
if (presence == Tp.ConnectionPresenceType.AVAILABLE)
this._presence.setStatus(GnomeSession.PresenceStatus.AVAILABLE);
@ -314,33 +314,35 @@ IMStatusChooserItem.prototype = {
this._accountMgr.set_all_requested_presences(newPresence, status, msg);
},
getIMPresenceForSessionStatus: function(sessionStatus) {
if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE)
return this._previousPresence;
if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
// Only change presence if the current one is "more present" than
// busy, or if coming back from idle
if (this._currentPresence == Tp.ConnectionPresenceType.AVAILABLE ||
this._currentPresence == Tp.ConnectionPresenceType.EXTENDED_AWAY)
return Tp.ConnectionPresenceType.BUSY;
}
if (sessionStatus == GnomeSession.PresenceStatus.IDLE) {
// Only change presence if the current one is "more present" than
// idle
if (this._currentPresence != Tp.ConnectionPresenceType.OFFLINE)
return Tp.ConnectionPresenceType.EXTENDED_AWAY;
}
return this._currentPresence;
},
_sessionStatusChanged: function(sessionPresence, sessionStatus) {
let [presence, s, msg] = this._accountMgr.get_most_available_presence();
let newPresence, status;
if (sessionStatus == GnomeSession.PresenceStatus.AVAILABLE) {
newPresence = this._previousPresence;
} else if (sessionStatus == GnomeSession.PresenceStatus.BUSY) {
// Only change presence if the current one is "more present" than
// busy, or if coming back from idle
if (presence == Tp.ConnectionPresenceType.AVAILABLE ||
presence == Tp.ConnectionPresenceType.EXTENDED_AWAY) {
newPresence = Tp.ConnectionPresenceType.BUSY;
} else {
return;
}
} else if (sessionStatus == GnomeSession.PresenceStatus.IDLE) {
// Only change presence if the current one is "more present" than
// idle
if (presence != Tp.ConnectionPresenceType.OFFLINE)
newPresence = Tp.ConnectionPresenceType.EXTENDED_AWAY;
else
return;
} else {
return;
}
let newPresence = this.getIMPresenceForSessionStatus(sessionStatus);
if (newPresence == undefined)
if (!newPresence || newPresence == presence)
return;
status = this._statusForPresence(newPresence);
@ -361,8 +363,8 @@ UserMenuButton.prototype = {
_init: function() {
PanelMenu.Button.prototype._init.call(this, 0.0);
let box = new St.BoxLayout({ name: 'panelStatusMenu' });
this.actor.set_child(box);
let box = new St.BoxLayout({ name: 'panelUserMenu' });
this.actor.add_actor(box);
this._lockdownSettings = new Gio.Settings({ schema: LOCKDOWN_SCHEMA });
@ -412,6 +414,7 @@ UserMenuButton.prototype = {
box.add(this._name, { y_align: St.Align.MIDDLE, y_fill: false });
this._userLoadedId = this._user.connect('notify::is-loaded', Lang.bind(this, this._updateUserName));
this._userChangedId = this._user.connect('changed', Lang.bind(this, this._updateUserName));
this._updateUserName();
this._createSubMenu();
this._userManager.connect('notify::is-loaded',
@ -515,8 +518,8 @@ UserMenuButton.prototype = {
},
_updateSwitch: function(presence, status) {
let active = status == GnomeSession.PresenceStatus.BUSY;
this._dontDisturbSwitch.setToggleState(active);
let active = status == GnomeSession.PresenceStatus.AVAILABLE;
this._notificationsSwitch.setToggleState(active);
},
_updatePresenceIcon: function(accountMgr, presence, status, message) {
@ -540,11 +543,12 @@ UserMenuButton.prototype = {
item = new IMStatusChooserItem();
item.connect('activate', Lang.bind(this, this._onMyAccountActivate));
this.menu.addMenuItem(item);
this._statusChooser = item;
item = new PopupMenu.PopupSwitchMenuItem(_("Do Not Disturb"));
item = new PopupMenu.PopupSwitchMenuItem(_("Notifications"));
item.connect('activate', Lang.bind(this, this._updatePresenceStatus));
this.menu.addMenuItem(item);
this._dontDisturbSwitch = item;
this._notificationsSwitch = item;
item = new PopupMenu.PopupSeparatorMenuItem();
this.menu.addMenuItem(item);
@ -587,8 +591,21 @@ UserMenuButton.prototype = {
},
_updatePresenceStatus: function(item, event) {
let status = item.state ? GnomeSession.PresenceStatus.BUSY
: GnomeSession.PresenceStatus.AVAILABLE;
let status;
if (item.state) {
status = GnomeSession.PresenceStatus.AVAILABLE;
} else {
status = GnomeSession.PresenceStatus.BUSY;
let [presence, s, msg] = this._account_mgr.get_most_available_presence();
let newPresence = this._statusChooser.getIMPresenceForSessionStatus(status);
if (newPresence != presence &&
newPresence == Tp.ConnectionPresenceType.BUSY)
Main.notify(_("Your chat status will be set to busy"),
_("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);
},

View File

@ -210,6 +210,11 @@ SearchTab.prototype = {
this._searchResults.createProviderMeta(provider);
},
removeSearchProvider: function(provider) {
this._searchSystem.unregisterProvider(provider);
this._searchResults.destroyProviderMeta(provider);
},
startSearch: function(event) {
global.stage.set_key_focus(this._text);
this._text.event(event, false);
@ -297,7 +302,7 @@ SearchTab.prototype = {
_doSearch: function () {
this._searchTimeoutId = 0;
let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
this._searchResults.updateSearch(text);
this._searchResults.doSearch(text);
return false;
}
@ -563,6 +568,10 @@ ViewSelector.prototype = {
addSearchProvider: function(provider) {
this._searchTab.addSearchProvider(provider);
},
removeSearchProvider: function(provider) {
this._searchTab.removeSearchProvider(provider);
}
};
Signals.addSignalMethods(ViewSelector.prototype);

View File

@ -19,47 +19,47 @@ const UNDIM_TIME = 0.250;
var dimShader = undefined;
function getDimShader() {
if (dimShader === null)
return null;
if (!dimShader) {
let source = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
try {
let shader = new Clutter.Shader();
shader.set_fragment_source(source, -1);
shader.compile();
dimShader = shader;
} catch (e) {
log(e.message);
dimShader = null;
}
}
function getDimShaderSource() {
if (!dimShader)
dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
return dimShader;
}
function getTopInvisibleBorder(metaWindow) {
let outerRect = metaWindow.get_outer_rect();
let inputRect = metaWindow.get_input_rect();
return outerRect.y - inputRect.y;
}
function WindowDimmer(actor) {
this._init(actor);
}
WindowDimmer.prototype = {
_init: function(actor) {
this.effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
this.effect.set_shader_source(getDimShaderSource());
this.actor = actor;
},
set dimFraction(fraction) {
this._dimFraction = fraction;
let shader = getDimShader();
if (!Meta.prefs_get_attach_modal_dialogs() || !shader) {
this.actor.set_shader(null);
if (!Meta.prefs_get_attach_modal_dialogs()) {
this.effect.enabled = false;
return;
}
if (fraction > 0.01) {
this.actor.set_shader(shader);
this.actor.set_shader_param_float('height', this.actor.get_height());
this.actor.set_shader_param_float('fraction', fraction);
} else
this.actor.set_shader(null);
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);
} else {
if (this.effect.actor)
this.actor.remove_effect(this.effect);
}
},
get dimFraction() {
@ -69,11 +69,11 @@ WindowDimmer.prototype = {
_dimFraction: 0.0
};
function getWindowDimmer(texture) {
if (!texture._windowDimmer)
texture._windowDimmer = new WindowDimmer(texture);
function getWindowDimmer(actor) {
if (!actor._windowDimmer)
actor._windowDimmer = new WindowDimmer(actor);
return texture._windowDimmer;
return actor._windowDimmer;
}
function WindowManager() {
@ -268,30 +268,28 @@ WindowManager.prototype = {
let actor = window.get_compositor_private();
if (!actor)
return;
let texture = actor.get_texture();
if (animate)
Tweener.addTween(getWindowDimmer(texture),
Tweener.addTween(getWindowDimmer(actor),
{ dimFraction: 1.0,
time: DIM_TIME,
transition: 'linear'
});
else
getWindowDimmer(texture).dimFraction = 1.0;
getWindowDimmer(actor).dimFraction = 1.0;
},
_undimWindow: function(window, animate) {
let actor = window.get_compositor_private();
if (!actor)
return;
let texture = actor.get_texture();
if (animate)
Tweener.addTween(getWindowDimmer(texture),
Tweener.addTween(getWindowDimmer(actor),
{ dimFraction: 0.0,
time: UNDIM_TIME,
transition: 'linear'
});
else
getWindowDimmer(texture).dimFraction = 0.0;
getWindowDimmer(actor).dimFraction = 0.0;
},
_mapWindow : function(shellwm, actor) {
@ -528,22 +526,22 @@ WindowManager.prototype = {
shellwm.completed_switch_workspace();
},
_startAppSwitcher : function(shellwm, binding, window, backwards) {
_startAppSwitcher : function(shellwm, binding, mask, window, backwards) {
/* prevent a corner case where both popups show up at once */
if (this._workspaceSwitcherPopup != null)
this._workspaceSwitcherPopup.actor.hide();
let tabPopup = new AltTab.AltTabPopup();
if (!tabPopup.show(backwards, binding))
if (!tabPopup.show(backwards, binding, mask))
tabPopup.destroy();
},
_startA11ySwitcher : function(shellwm, binding, window, backwards) {
Main.ctrlAltTabManager.popup(backwards);
_startA11ySwitcher : function(shellwm, binding, mask, window, backwards) {
Main.ctrlAltTabManager.popup(backwards, mask);
},
_showWorkspaceSwitcher : function(shellwm, binding, window, backwards) {
_showWorkspaceSwitcher : function(shellwm, binding, mask, window, backwards) {
if (global.screen.n_workspaces == 1)
return;

View File

@ -102,6 +102,12 @@ WindowClone.prototype = {
this._windowClone = new Clutter.Clone({ source: realWindow.get_texture(),
x: -borderX,
y: -borderY });
// We expect this.actor to be used for all interaction rather than
// this._windowClone; as the former is reactive and the latter
// is not, this just works for most cases. However, for DND all
// actors are picked, so DND operations would operate on the clone.
// To avoid this, we hide it from pick.
Shell.util_set_hidden_from_pick(this._windowClone, true);
this.origX = realWindow.x + borderX;
this.origY = realWindow.y + borderY;

View File

@ -567,8 +567,6 @@ WorkspacesDisplay.prototype = {
this._updateAlwaysZoom();
Main.layoutManager.connect('monitors-changed', Lang.bind(this, this._updateAlwaysZoom));
global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
Main.xdndHandler.connect('drag-begin', Lang.bind(this, function(){
this._alwaysZoomOut = true;
@ -581,6 +579,7 @@ WorkspacesDisplay.prototype = {
this._switchWorkspaceNotifyId = 0;
this._nWorkspacesChangedId = 0;
this._itemDragBeginId = 0;
this._itemDragCancelledId = 0;
this._itemDragEndId = 0;
@ -612,6 +611,9 @@ WorkspacesDisplay.prototype = {
global.screen.connect('restacked',
Lang.bind(this, this._onRestacked));
if (this._nWorkspacesChangedId == 0)
this._nWorkspacesChangedId = global.screen.connect('notify::n-workspaces',
Lang.bind(this, this._workspacesChanged));
if (this._itemDragBeginId == 0)
this._itemDragBeginId = Main.overview.connect('item-drag-begin',
Lang.bind(this, this._dragBegin));

View File

@ -1,6 +1,7 @@
af
an
ar
as
be
bg
bn
@ -37,6 +38,7 @@ ms
nb
nl
nn
or
pa
pl
pt

View File

@ -1,15 +1,18 @@
data/gnome-shell.desktop.in.in
data/org.gnome.shell.gschema.xml.in
js/gdm/loginDialog.js
js/gdm/powerMenu.js
js/misc/util.js
js/ui/appDisplay.js
js/ui/appFavorites.js
js/ui/autorunManager.js
js/ui/calendar.js
js/ui/contactDisplay.js
js/ui/dash.js
js/ui/dateMenu.js
js/ui/docDisplay.js
js/ui/endSessionDialog.js
js/ui/extensionSystem.js
js/ui/keyboard.js
js/ui/lookingGlass.js
js/ui/messageTray.js

1022
po/af.po

File diff suppressed because it is too large Load Diff

1616
po/as.po Normal file

File diff suppressed because it is too large Load Diff

1015
po/be.po

File diff suppressed because it is too large Load Diff

908
po/bg.po

File diff suppressed because it is too large Load Diff

1059
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1117
po/cs.po

File diff suppressed because it is too large Load Diff

1135
po/da.po

File diff suppressed because it is too large Load Diff

923
po/de.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1271
po/eo.po

File diff suppressed because it is too large Load Diff

935
po/es.po

File diff suppressed because it is too large Load Diff

1154
po/eu.po

File diff suppressed because it is too large Load Diff

975
po/fa.po

File diff suppressed because it is too large Load Diff

1278
po/fi.po

File diff suppressed because it is too large Load Diff

1131
po/fr.po

File diff suppressed because it is too large Load Diff

881
po/gl.po

File diff suppressed because it is too large Load Diff

1193
po/gu.po

File diff suppressed because it is too large Load Diff

932
po/he.po

File diff suppressed because it is too large Load Diff

1202
po/hi.po

File diff suppressed because it is too large Load Diff

1085
po/hu.po

File diff suppressed because it is too large Load Diff

908
po/id.po

File diff suppressed because it is too large Load Diff

996
po/it.po

File diff suppressed because it is too large Load Diff

1175
po/ja.po

File diff suppressed because it is too large Load Diff

1091
po/ko.po

File diff suppressed because it is too large Load Diff

1109
po/lt.po

File diff suppressed because it is too large Load Diff

1031
po/lv.po

File diff suppressed because it is too large Load Diff

843
po/nb.po

File diff suppressed because it is too large Load Diff

1555
po/or.po Normal file

File diff suppressed because it is too large Load Diff

955
po/pa.po

File diff suppressed because it is too large Load Diff

1081
po/pl.po

File diff suppressed because it is too large Load Diff

1117
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

965
po/ru.po

File diff suppressed because it is too large Load Diff

1036
po/sk.po

File diff suppressed because it is too large Load Diff

1284
po/sl.po

File diff suppressed because it is too large Load Diff

1226
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

944
po/sv.po

File diff suppressed because it is too large Load Diff

1146
po/ta.po

File diff suppressed because it is too large Load Diff

1135
po/te.po

File diff suppressed because it is too large Load Diff

921
po/vi.po

File diff suppressed because it is too large Load Diff

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