Compare commits

...

150 Commits

Author SHA1 Message Date
ef200512cd Adapt to Mutter background changes
The rewrite of Mutter's background code (see bug 735637) requires
corresponding changes here - we no longer need to layer multiple
MetaBackgroundActors together.

The general strategy is that a BackgroundSource object is created
per GSettings schema, and keeps either one Background/MetaBackground pair,
or, for animation, a Background/Metabackground pair for each monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=735638
2014-08-28 16:38:12 -04:00
3526bc0f0a Updated Telugu Translation 2014-08-27 10:47:14 +05:30
079809af1d workspace: Remove tweens of overlay.title before animate again
Currently we are removing tweens of the button and border, but not from
the title. That causes the title to be in wrong positions sometimes when
dragging windows on the overview, given that the slider is moving and
therefore the windows + overlay are moving too.
To avoid that, remove tweens of the title as well.
2014-08-26 19:35:25 +02:00
26719b02e4 Updated French translation 2014-08-26 11:25:46 +00:00
3a45ddcaad Updated Oriya translation 2014-08-26 10:58:12 +00:00
f839100bc2 committed file 2014-08-26 16:19:41 +05:30
c93767768c perf: fix wallpaper style for overridden background
The code that loads SHELL_BACKGROUND_IMAGE, which is used to load the
performance background was loading it in WALLPAPER mode, not ZOOM
mode. Zoom mode is what we use for the actual GNOME defaultiwallpaper
and what we want to test: the background will be scaled except when
the resolution matches the 2560x1440 default backgrounds.

https://bugzilla.gnome.org/show_bug.cgi?id=735385
2014-08-25 20:28:57 -04:00
0011755b41 Updated Galician translations 2014-08-25 23:08:17 +02:00
ec932b2306 screenShield: Fix typo in comment
And remove outdated reference to gnome-screensaver

https://bugzilla.gnome.org/show_bug.cgi?id=735190
2014-08-21 22:49:58 +02:00
1c0c38574d search: Remove unused function 2014-08-20 18:41:18 +02:00
78b81650f5 Bump version to 3.13.90
Update NEWS.
2014-08-20 02:17:04 +02:00
62bfde45aa search: Fix default drag actor source
Another unnoticed fallout from commit 792b963bda ...
2014-08-19 20:34:08 +02:00
5b624a34b8 location: Only show menu when geolocation is in use
Users can now toggle geolocation off/on from privacy panel of
gnome-control-center so we don't need to clutter the menu with a
settings that most users won't touch most of the time.

https://bugzilla.gnome.org/show_bug.cgi?id=731122
2014-08-19 19:20:47 +01:00
9c008ab998 iconGrid: Move code around a bit
The scale passed to _updateChildrenScale is exclusively computed from
properties, so it can be moved into the function itself - as the scale
now becomes a mere detail, rename to a more appropriate _updateIconSizes
at the same time.
2014-08-19 19:46:45 +02:00
6edcd82103 tweener: Also consider delay when disabling animations
'time' is not the only timing parameter for tweens, in order to
really disable animations, we need to override 'delay' as well.
2014-08-19 19:46:44 +02:00
d5aa276c41 search: Fix custom drag actor source
The existing code broke when commit 792b963bda changed the custom
result actor hook to return an object instead of an actor - stop
trying to go through a _delegate to make it work again.
2014-08-19 19:12:02 +02:00
d54efe0838 runDialog: catch the case where no completion is available
Just return null, instead of failing with an exception later trying to
call substr() on null.

https://bugzilla.gnome.org/show_bug.cgi?id=735062
2014-08-19 09:39:51 -07:00
d0fe1211f2 search: Fix visibility of "more" icon
Since commit 19749bb37f, the icon is always visible - ooops.
2014-08-19 18:13:40 +02:00
3e20843d9c dateMenu: Try to use the default calendar application
Commit 14ceb10555 changed the "Open Calendar" item to open the
"recommended" calendar application rather than the default one to
avoid problems with MIME subclassing (namely falling back to the
default text editor when no calendar app is installed).
With this change however, the application launched does no longer
necessarily match the one configured in Settings, which is unexpected.
To avoid both problems, use the default calendar application again,
but only if it is in the list of recommended applications.

https://bugzilla.gnome.org/show_bug.cgi?id=722333
2014-08-19 18:13:40 +02:00
7c9d90b0aa TelepathyClient: fix history trimming
We need to put the actual actors in the history, not just the labels,
otherwise all emptyLine (which are not messages but are not empty
either) and all lines with a timestamp will get stuck in the scrollback.

https://bugzilla.gnome.org/show_bug.cgi?id=733899
2014-08-19 16:48:13 +02:00
b6e6e097b7 PortalHelper: fix portals that don't redirect properly
We assumed that either a portal would give us a target URI, or we
would eventually reach the URI of our choice (which is http://www.gnome.org)

This is not always the case: even after a successful login we may
stay in a confirmation page, so make sure that every time we see a
redirect we trigger a connectivity check (or queue one for when
the user closes the window)

https://bugzilla.gnome.org/show_bug.cgi?id=733848
2014-08-19 15:29:22 +02:00
3842981c35 SearchEntry: replace the ID with a style class
This way extension authors can create entries that look and feel
like the overview search entry.

https://bugzilla.gnome.org/show_bug.cgi?id=733813
2014-08-19 15:29:22 +02:00
926177785d search: add support for default disabled search providers
Search providers that should be disabled by default come with
a DefaultDisabled=true key in their keyfile, and are enabled
with the "enabled" whitelist, not with the "disabled" blacklist.

https://bugzilla.gnome.org/show_bug.cgi?id=734110
2014-08-19 15:29:22 +02:00
7d80647170 popupMenu: Remove unused function 2014-08-19 15:23:00 +02:00
c2a21bb885 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2014-08-19 19:17:46 +08:00
eaff1e9290 perf-tool: Remove dead code 2014-08-18 22:58:30 +02:00
93c5e6d97e altTab: Fix WindowSwitcherPopup
The "backwards" parameter needs to be dropped here as well.
2014-08-18 13:34:32 -04:00
20fc9735fa Add a special background to use for performance testing
Performance testing was producing inconsistent values at different
times in the day since the GNOME default background is animated and
sometimes has a single layer, and sometimes two blended layers.

So we have consistent numbers, install a simple animated background
with GNOME Shell that has 40-year long transition ending in 2030,a
and set an environment variable in gnome-shell-perf-tool so that the
background is override with that background. (The background depends
on files installed by gnome-backgrounds; we assume that the person
running performance tests is doing so within the scope of a full
GNOME install.)

https://bugzilla.gnome.org/show_bug.cgi?id=734610
2014-08-18 10:54:42 -04:00
d450b74e10 Remove 'backwards' argument from SwitcherPopup:_keyPressHandler
All derived classes are already checking explicitly for action names
(FOO and FOO_BACKWARDS). mutter used to have a META_KEY_BINDING_REVERSES
flag for keybindings which required special handling of "shift"+FOO as
FOO_BACKWARDS, but this has been removed now, so this special handling
is no longer necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=732296
2014-08-17 19:33:22 +02:00
e8fa2b6417 Stop using Meta.KeyBindingFlags.REVERSES for IM switch keybinding
When this flag is set on a MetaKeyBinding, mutter will know that
the keybinding has an associated reverse keybinding triggered with
the shift modifier. However, an undesirable side-effect is that
gnome-control-center keyboard panel does not know that this 'shift'
is reserved for these reverse keybindings and cannot detect
conflicting bindings in this case.
This 'reverse' logic can now be handled at a higher level (in gcc keyboard
panel) so this commit removes it from gnome-shell so that they do not
conflict.

https://bugzilla.gnome.org/show_bug.cgi?id=732296
2014-08-17 19:33:22 +02:00
c459ef6888 Use new meta_key_binding_is_reversed() method
Now that mutter gives a way to check if a MetaKeyBinding was marked as
'reversed' or not, gnome-shell does not have to hardcode that a
MetaKeyBinding using a shift modifier is reversed, it can directly check
if the appropriate flag is set.

https://bugzilla.gnome.org/show_bug.cgi?id=732296
2014-08-17 19:33:22 +02:00
d1a3a000af appDisplay: sync page when changing adjustment
We were setting the value of adjustment on size changes, but we weren't
changing the page value, so adjustment and page value was not in sync.

To fix it, make sure adjustment of the view is in sync with the page
value.

https://bugzilla.gnome.org/show_bug.cgi?id=734680
2014-08-15 23:07:25 +02:00
5ce8980db3 shell-global: Remove grab notifier
With the window menus gone, it is no longer possible to have a GTK+ grab
in-process, so remove our code that was tracking GTK+ grabs.
2014-08-14 10:59:43 -04:00
8c32cff6fc Updated Friulian translation 2014-08-14 06:06:24 +02:00
bc99db9fd3 Updated Assamese translation 2014-08-13 15:40:14 +00:00
a5eae8e3d8 Updated Assamese translation 2014-08-13 12:04:42 +00:00
82a764ee93 Updated Dutch translation 2014-08-12 23:17:25 +02:00
ce2c90a534 location: Move settings to gsettings-desktop-schemas
Since these settings are now going to be accessed by
gnome-control-center as well, its more appropriate for them to live in
gsettings-desktop-schemas.

https://bugzilla.gnome.org/show_bug.cgi?id=734483
2014-08-10 17:56:52 +01:00
28cc0da151 hwtest.js: Fix median computation
By default Array.prototype.sort() sorts all values by converting
them to strings, even numbers!
2014-08-10 09:25:10 +02:00
f1957dccb7 location: Separate setting for enabling/disabling
Having the on/off setting be backed by a boolean in dconf makes sense
anyway but this is mainly to be able to remember the max accuracy set
before user disabled geolocation so that when they enable it next time,
we have the max accuracy level on same value as before.

There hasn't been a real need for this but now we are about to add
geolocation settings in control center and it'll be easiser for
control-center to simply toggle a boolean property rather than to have
to know about and deal with accuracy levels.

Later we might also want to add accuracy level settings to privacy panel
so keeping the accuracy level setting around still. However we no longer
support 'off' accuracy level as the new boolean property covers that.

This also implies that we no longer track available accuracy level,
which made the code a bit hard to follow/maintain.

https://bugzilla.gnome.org/show_bug.cgi?id=734483
2014-08-09 15:59:41 +01:00
0af4dc0b4c Remove explicit ENABLE_EXPERIMENTAL_API switches
Those are already defined globally via the Makefile, and newer
compiler versions complain about redefining those symbols.
2014-08-08 17:58:37 +02:00
687e1ebf69 workspace: Fade in instead of zoom to return desktop
The zooming animation of the windows looks nice when animating
from the workspace display page, but looks weird from other pages
like apps page or search page since the windows come from nowhere
with an initial position not known to the user.

Instead of that just fade the desktop with the windows in its
original position.

https://bugzilla.gnome.org/show_bug.cgi?id=732901
2014-08-08 16:40:41 +02:00
805b686576 overviewControls: don't override explicit calls to slideIn
Currently we are overriding the explicit calls to slideIn
given that it's called also with the signal of showing overview.

It was necessary because of the bug that previous patch fixed,
so now we can just delete that.

https://bugzilla.gnome.org/show_bug.cgi?id=732901
2014-08-08 16:40:41 +02:00
101daf6791 workspaceThumbnails: allow requesting size at any time
The slide of thumbnailWorkspace is shown when entering overview,
connecting to the same signal that creates the thumbnails, the showing
signal of overview, but, to make the slide animation we need to know how
much width the slider has.  To do that we ask the thumbnailsWorkspace
about its width, but given that it connects to the same signal it could
ask the width without having created the thumbnails yet, so reporting a
width of 0 and confusing the slide animation.

Currently it works because gjs calls the callbacks following the order
of the clients connecting that signal, and the thumbnailsWorskpace is
connected before the slide ones.

To avoid that we allow to request the preferred size of the
thumbnailsBox at any time with any number of thumbnails. The only thing
required is to make sure the porthole is accessible when requesting the
preferred size.

https://bugzilla.gnome.org/show_bug.cgi?id=732901
2014-08-08 16:40:41 +02:00
5d12ab415c viewSelector: Remove duplicate call to showPage
We were calling twice showPage() with the correct page, here and in
show() / zoomFromOverview given that _resetShowAppsbutton was called
from the signal 'showing' of overview.  Given that the call to
_resetShowAppsbutton is only actually used when hiding the overview we
can actually put the checked state of the button to false when animating
from overview so it shows the workspace page, causing the same behavior
of _resetShowAppsbutton without all the shenanigans of resetting when
the hiding overview signal is triggered.

https://bugzilla.gnome.org/show_bug.cgi?id=732901
2014-08-08 16:40:41 +02:00
0810ab62db Port to cogl_texture_2d_new_from_data 2014-08-07 14:49:55 -04:00
6f00d81abf texture-cache: Port to modern Cogl 2014-08-07 14:49:55 -04:00
4184edc7f8 texture-cache: Remove FBO path for padding icons
GtkIconTheme now pads icons when it loads them to make sure that they
are square, so this code is effectively dead.
2014-08-07 14:49:55 -04:00
05f9f991d8 st: Adapt the mutter implementation for create_texture_material
This is the new API that uses set_null_texture instead of a dummy texture.
2014-08-07 14:49:54 -04:00
3df7ef6ce6 shell: Define COGL_ENABLE_EXPERIMENTAL_API and related defines globally
This allows us to use new Cogl APIs without having to define things in
every .c/.h file manually.
2014-08-07 14:49:54 -04:00
d836194e31 appDisplay: Remove pointless return value
StButton::clicked does not have a return type, so don't return anything.
2014-08-07 18:41:28 +02:00
8ed3e2117f Add Software to the end of the dash
https://bugzilla.gnome.org/show_bug.cgi?id=734406
2014-08-07 14:19:55 +02:00
62fcda5d91 Updated Basque language 2014-08-07 12:36:21 +02:00
0a780376f3 Updated Basque language 2014-08-07 12:31:50 +02:00
efb9f167bd messageTray: Fix RTL handling in notifications
Commit 234b90ac86 replaced a member variable with a "local"
one, except that it wasn't that local after all ...
2014-08-06 16:10:27 +02:00
eb69f3aa76 networkAgent: Use Clutter.GridLayout
Clutter.TableLayout has been deprecated, so move to the recommended
replacement.
2014-08-06 15:23:21 +02:00
c15a885418 keyring: Use Clutter.GridLayout
Clutter.TableLayout has been deprecated, so move to the recommended
replacement.
2014-08-06 15:23:21 +02:00
fe60db64e0 appDisplay: Use Clutter.GridLayout
Clutter.TableLayout has been deprecated, so move to the recommended
replacement.
2014-08-06 15:23:21 +02:00
b90cc5ff26 calendar: Port events to Clutter.GridLayout
Clutter.TableLayout has been deprecated, so move to the recommended
replacement.
2014-08-06 15:23:21 +02:00
e9f95ca605 calendar: Use Clutter.GridLayout
Clutter.TableLayout has been deprecated, so move to the recommended
replacement.
2014-08-06 15:23:21 +02:00
017c2468ee popupMenu: Remove unused imports 2014-08-06 15:23:21 +02:00
8c6a2874ff workspace: Fix style 2014-08-06 15:23:21 +02:00
557130d2f2 workspace: Remove unused parameter 2014-08-06 15:23:20 +02:00
84cbbafaae appDisplay: Don't grow indicators more than the parent
Currently the indicators are a BoxLayout inside a BinLayout in AllView.
BinLayout doesn't have any size constraint, so if the indicators request
a bigger size than AllView the entire overview is grown, causing the
overview to go crazy.

To avoid that, create an actor for the page indicators that request as
minimum size 0, and as a natural size, the sum of all indicators natural
sizes. Then we clip_to_allocation, so it doesn't grow more than the
parent.

https://bugzilla.gnome.org/show_bug.cgi?id=723496
2014-08-06 09:41:29 +02:00
72a663f554 windowManager: Fix destroy animation
Guess who didn't test his destroy animation that he pushed without any
review!!! It wasn't me!
2014-08-03 15:30:06 -04:00
7c762ef9df Updated Greek translation 2014-08-02 09:33:20 +00:00
3182aba744 AppDisplay: don't show a "New Window" menu item if not possible
If the application reports itself as single window (through
an explicit indication in the desktop file or some heuristics),
not show a "New window" item that doesn't actually open a new window.

https://bugzilla.gnome.org/show_bug.cgi?id=722554
2014-08-01 11:45:18 +02:00
e6339fbb45 doap: add <programming-language> 2014-07-31 17:48:46 +02:00
a6d8c25494 panel: Avoid _onEvent() to be called twice
Both Panel.ActivitiesButton and its parent class Panel.MenuButton would
attempt to connect their own _onEvent() function to Clutter::event,
which counterintuitively was connecting the child class' _onEvent()
function twice.

So, actually chain up on the signal handler, and don't connect twice
to the signal. Both methods were calling this.menu.close(), so only
do that on the parent class handler, since we're chaining up and doing
the right thing now.

https://bugzilla.gnome.org/show_bug.cgi?id=733840
2014-07-31 17:43:09 +02:00
cd4eda8bef ScreenShield: remove obsolete comment and hack
We don't need to wait to until the stage window is mapped to take
the modal grab, because that code now runs in a startup-prepared
signal handler, which in turn runs some time after the mainloop
has started and well after the stage window is mapped.

https://bugzilla.gnome.org/show_bug.cgi?id=711682
2014-07-31 16:54:47 +02:00
a0bd4a02e4 Fix accidental gvc downgrade 2014-07-31 16:54:34 +02:00
42b54aaa21 grabHelper: handle touch events during grab modality
The "pointer emulating" touch sequence will be handled in order to dismiss
the grab, while the others are just propagated.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-31 10:55:25 +02:00
bbfa616f27 grabHelper: consume the press/motion/release sequence if a press dismisses the grab
The grab would previously just consume the button release, while propagating
motion events, possibly down to clients in wayland. This would produce
inconsistent streams there.

On pointer events, the inconsistency would just be having clients receiving
events with the button 1 set in the mask, with no implicit grab. When touch
events are handled, this would be more hindering as the client would receive
touch_motion events with no prior touch_down nor later touch_up, something
never supposed to happen.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-31 10:55:11 +02:00
7e31015ba2 doap category core 2014-07-30 16:31:48 +02:00
aa2fc3c858 WindowManager: update animation timings after designer review
Lapo, Jakub and Allan all agree with this.

https://bugzilla.gnome.org/show_bug.cgi?id=732857
2014-07-29 14:55:51 +02:00
d4f0b5bdf3 WindowManager: improve destroy window animation
The animation is the same for modal dialogs, but it is now
run for non modal dialogs too (matching the new behavior on
show).
In addition, we run a destroy animation for normal windows,
if they use CSD (there are technical limitations that prevent
running animations after destroy on server decorated windows)

https://bugzilla.gnome.org/show_bug.cgi?id=732857
2014-07-29 14:55:48 +02:00
eda27d5194 WindowManager: improve minimize/map animations
Using the parameters from Elementary's Gala, which is generally
considered a DE that cares about eye-candy.

https://bugzilla.gnome.org/show_bug.cgi?id=732857
2014-07-29 14:53:28 +02:00
589e6c29f3 loginDialog: Push a modal for LOCK_SCREEN
So that we're in the correct keybinding mode.
2014-07-27 08:18:51 -04:00
4b46533ce8 loginDialog: Fix the removal from the ctrlAltTabManager
When we ported away from ModalDialog, we forgot to change this one
reference to the dialog layout. Change it now.
2014-07-27 08:12:27 -04:00
6687b9b739 layout: re-allocate keyboard box when monitor config changes
For example, because we are changing orientation.

https://bugzilla.gnome.org/show_bug.cgi?id=733790
2014-07-26 17:45:55 +02:00
91c4408d23 shell-recorder: Don't use XI2 in the recorder to query the pointer
Just use the normal MetaCursorTracker, which works under Wayland.
2014-07-26 10:51:48 -04:00
83adb2a864 clutter.paintCompletedTimestamp: cogl_flush() before glFinish()
Calling glFinish() doesn't give us a reliable timestamp unless we
flush Cogl rendering to GL first.
2014-07-26 16:46:45 +02:00
5918faddf7 Updated Lithuanian translation 2014-07-25 22:54:13 +03:00
916c02a2f5 hwtest: Handle rename of gedit desktop file
It's now org.gnome.gedit.desktop not gedit.desktop.
2014-07-25 10:40:45 +02:00
a84fb99c0a keyboard: Handle touch events
Handle touch events, so that an interacted button locks to a single sequence,
but multiple sequences are free to interact with multiple key buttons.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:44:14 +02:00
69d5cef3b2 keyboard: Use common code to create regular and extension key buttons
The code is almost the same, so pull this out to a generic _makeKey(), and
use it from both places.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:26:56 +02:00
38d05a8285 panel: Make the "Activities" button react to touch events
https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:23:17 +02:00
f8899cf274 appDisplay: Allow clicks/long presses through touch events
The long press code has been refactored so it can be used on both pointer and
touch events, and the click gesture has been made to account for button=0.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
dbbf4097a5 slider: React to touch events
The slider locks to the first interacting sequence, and ignores events from
any other.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
acb1497f4f backgroundMenu: Allow for long presses on touch devices
These don't have a button set. Also, popup the menu relative to gesture
reported coordinates, and not relative to the pointer position everytime.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
e545ec59b9 panelMenu: Interact to touch events
No sequence checks are done, these UI elements promptly trigger a grab that
will cancel ongoing touches and redirect later ones somewhere else, so that
works as a barrier to multi-toggling.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
da26a9daf8 popupMenu: dismiss the menu on touch events
No sequence checks are done, just any touch outside will dismiss the popup.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
a2f263dcbb st-button: Handle touch events
On touch events, StButton becomes locked to a single sequence, so no multiple
touches can trigger it simultaneously.

https://bugzilla.gnome.org/show_bug.cgi?id=733633
2014-07-24 18:15:02 +02:00
ce5cd3bf30 st-scroll-view-fade: Refuse to work without GLSL
Disable the effect when GLSL is not available otherwise we will
crash later.

https://bugzilla.gnome.org/show_bug.cgi?id=733623
2014-07-24 16:51:03 +02:00
9a05aea76f lightbox: Do not assume GLSL is available
Some hardware does not support it causing crashes in cogl during paint.

https://bugzilla.gnome.org/show_bug.cgi?id=733623
2014-07-24 16:51:02 +02:00
c9f6d5e2a1 Bump version to 3.13.4
Update NEWS.
2014-07-23 13:02:10 +02:00
eba2b999ed popupMenu: Fix PopupImageMenuItem
https://bugzilla.gnome.org/show_bug.cgi?id=733540
2014-07-23 10:24:18 +02:00
cceac0d8fb appFavorites: Automatically update desktop file names in user settings
This adds a table with mappings for GNOME apps that have recently
renamed their desktop files, and uses that to update the desktop names
saved in user settings with the new values.

https://bugzilla.gnome.org/show_bug.cgi?id=729429
2014-07-22 14:18:06 +02:00
14eedf8651 Updated Spanish translation 2014-07-22 12:31:23 +02:00
9c6180afa2 system: Fix orientation lock never appearing
Typos meant that the orientation service was never detected as running
and that the orientation lock menu item didn't appear.

https://bugzilla.gnome.org/show_bug.cgi?id=733498
2014-07-21 14:35:27 +02:00
f1b1dbcb00 Updated Norwegian bokmål translation from Åka Sikrom. 2014-07-21 13:50:39 +02:00
ee23b8dbe0 Updated Norwegian bokmål translation from Åka Sikrom. 2014-07-21 13:48:46 +02:00
c9e00bee08 plugin: Use the clutter xdisplay for has_swap_events
The filter now runs on the backend connection.
2014-07-19 18:51:56 +02:00
9970671bb1 Search: Don't use IconGrid width for maxDisplayedResults
Currently to know how many results we could show for GridResults
we use the width of the bin containing those results. Since it's
expanding it shouldn't be a problem. But it becomes a problem when
no results are displayed, thus the container becomes hidden and
it losts its allocation.
In the next introduction of terms in search we call again
maxDisplayedResults but it doesn't have allocation yet, and therefore no
results are displayed (currently a bug on IconGrid makes the min size =
one icon, so actually we show one and only one icon in this case).

To solve that use the parent container which contains the search results
of all providers or the text label with not displayed results, so it
always have the real available width to calculate maxDisplayedResults.

Thanks Alban Browaeys for the debugging footwork.

https://bugzilla.gnome.org/show_bug.cgi?id=732416
2014-07-19 18:12:43 +02:00
bb4502dca8 Updated Brazilian Portuguese translation 2014-07-18 16:25:29 +00:00
d77c7a407c extensionPrefs: Respect 'disable-extension-version-validation' setting 2014-07-18 10:47:02 +02:00
554001c0ed appDisplay: Move focus to popup only when necessary
Unlike for the main app view, where we only move the key focus once the
users starts navigating, the key focus is moved immediately when opening
a folder popup. This is unexpected, so make app folders consistent with
the main view.
As arrow keys will not work while the container itself has key focus, we
handle those explicitly by translating them to TAB_FORWARD and
TAB_BACKWARD respectively.

https://bugzilla.gnome.org/show_bug.cgi?id=731477
2014-07-17 20:41:24 +02:00
4d153bc96f Updated Hebrew translation 2014-07-17 09:49:16 +03:00
476394809a Mark a string to be translatable
And replace three points ('...') with the
unicode character '…'.
2014-07-17 09:48:26 +03:00
b6f3e15037 Add support for meta_restart() and MetaDisplay::restart
Support was added to Mutter to allow it to trigger a restart
to allow for restarts when switching in or out of stereo mode.

Hook up to the new signals on MetaDisplay to show the restart
message and reexec. Meta.is_restart() is used to suppress
the startup animation.

This also allows us to do 'Alt-F2 r' restarts more cleanly
without a visual flash and animation.

https://bugzilla.gnome.org/show_bug.cgi?id=733026
2014-07-16 18:04:19 -04:00
46c86e093c hwtest.js: Don't parse JSON with regexps
Use JSON.parse() to parse systemd log records, rather than using
regexps.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 13:22:13 -04:00
c6350aa557 Add --hwtest option to gnome-shell-perf-helper
Add a --hwtest option to gnome-shell-perf-helper which runs the
tests in perf/hwtest.js with the appropriate environment, and then
logs the results using the 'gnome-hwtest-log' utility which is
available in the hardware testing environent.

(For development of hwtest.js in a normal environment, run the tests
as: gnome-shell-perf-tool --perf=hwtest --extra-filter=Gedit)

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:37:48 -04:00
4e56af39da Add a new hwtest script
Add a performance test script that is used by the GNOME Hardware Testing
Project to measure metrics to be reported to perf.gnome.org.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:37:48 -04:00
9fff972946 perf: add a ShellGlobal property to call glFinish and log the time
It's useful to know how long frames are taking to render on the GPU.
This is impossible to measure in the normal case because frames may
parallelize with previous frames, but by calling glFinish() at the
end of the frame, we can create a (somewhat artificial, but useful)
environment where we have a meaningful timestamp for the frame
finishing drawing.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:37:48 -04:00
e30925995f Make frame-timestamp logging optional
Instead of always logging frame timestamps for every frame - which
was using >26 bytes of memory per frame, or 5MB per hour of continuous
redrawing - make frame timestamps something that defaults off and is
turned turned on using a new ShellGlobal::frame-timestamps property by
the perf scripts.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:33:59 -04:00
f0d4260c81 ShellPerfLog: Use monotonic timestamps for logging
Use g_get_monotonic_time() (that is, CLOCK_MONOTONIC) timestamps,
rather than gettimeofday() values.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:33:59 -04:00
a7f82745c6 shell-perf-helper: Add an option for continual redraws
Add an option for windows created with Scripting.createTestWindow()
to continually redraw themselves; this is for testing performance
of application updates.

https://bugzilla.gnome.org/show_bug.cgi?id=732350
2014-07-16 10:33:59 -04:00
a6fa6519d5 Updated Greek translation 2014-07-16 10:54:09 +00:00
a944dca60e overview: Remove wrong comment 2014-07-14 22:05:51 +02:00
fdc443aebe viewSelector: Going to the apps grid is a swipe from the left, not right 2014-07-14 14:02:46 -04:00
7e08e1e0e7 Updated Brazilian Portuguese translation 2014-07-14 16:24:06 +00:00
bd7938e02f Updated German translation 2014-07-09 22:28:21 +00:00
a583f45cc6 viewSelector: Synthesize a new event with correct source for search
We currently replay events that should start a search to the search
entry, which is fairly dodgy. Synthesize a new event with the correct
source actor instead, which is a bit less evil.
2014-07-09 12:23:30 +02:00
1071ac5d25 notificationDaemon: Group tray icon stuff together 2014-07-08 15:39:46 -04:00
45793d0e47 panel: Fix style 2014-07-08 15:38:35 -04:00
ea3866a07a main: Fix code style 2014-07-08 14:29:50 -04:00
e41879a5c4 windowManager: Switch the focused application on 3-finger hold + tap
The gesture action only cycles through the applications in the current
workspace.
2014-07-08 12:06:14 -04:00
24dc926660 windowManager: Switch workspaces on 4-finger drag
The workspace to switch is obtained from the direction received
by the WorkspaceSwitchAction gesture.
2014-07-08 12:06:14 -04:00
932b895127 viewSelector: Show the overview on 3-finger pinch gestures 2014-07-08 12:06:14 -04:00
9c4ffc4bf3 viewSelector: Add left edge drag gesture to show the app picker 2014-07-08 12:06:12 -04:00
1ea2e2bcab backgroundMenu: Release the click gesture if a grab operation begun
If an active grab on pointer events happens during multi-touch operations,
all non-pointer-emulating touches will be muted. This may leave the
Clutter.ClickAction incomplete if triggered by one of those sequences,
just to have a gesture take over and trigger a compositor grab, which would
leave the capture-event handler stuck eating events.

So listen for grab-op-begin from the display, and ensure the action is
released if such grab begins.
and the capture event handler stuck.
2014-07-08 12:01:43 -04:00
a8b15dd2cf gitignore: Add portal helper generated files 2014-07-08 16:15:19 +02:00
b1b8147ab8 Updated Russian translation 2014-07-08 17:18:44 +04:00
39c210abed ibusCandidatePopup: Fix default candidate index labels
The first 10 candidates are supposed to be shortcutted with the
keyboard keys 1 through 0 so the 10th index should be '0', not 'a'.

https://bugzilla.gnome.org/show_bug.cgi?id=702944
2014-07-08 11:31:15 +02:00
4bb2a364d3 overview: Avoid repositioning windows while returning to desktop
When returning to the desktop from overview we always show the
workspaceDisplay, given that is which have the windows clones to allow
animations.
The problem becomes when previous that we were at some other
page, like Search or AppDisplay. The problem is that when showing the
workspaceDisplay the windows are repositioned. That's wanted except
when returning from overview, since that causes unwanted animations
of the windows.
To avoid that just not reposition the windows if leaving the overview.
2014-07-07 17:37:24 +02:00
6d3ebdcb5e update Punjabi Translation - back for 3.14 2014-07-05 23:23:36 -05:00
e865db57e0 extension-tool: Fix multi-monitor handling in example extension 2014-07-05 11:22:46 +02:00
19ba9a98b8 Updated Chinese (Taiwan) translation 2014-07-04 12:24:13 +00:00
4a39af7f98 overview: Reorder functions for better context 2014-07-03 16:15:25 +02:00
c326aad9d7 overview: Delete false comment 2014-07-03 16:15:04 +02:00
dc94f7b9f5 notificationdaemon: fix gtk protocol for newer glib
The new protocol uses a "priority" string instead of the "urgent"
boolean.
2014-07-01 21:57:29 +02:00
e5be41b667 Updated Galician translations 2014-07-01 17:56:24 +02:00
775bd961b6 hidpi: Scale fonts on wayland
On X11 we don't need to scale up fonts because font scaling is already handled
by clutter based xft-dpi. On wayland we need to set the resolution by ourselves
so do that when the scale factor changes.

https://bugzilla.gnome.org/show_bug.cgi?id=732537
2014-07-01 12:02:19 +02:00
3c67d012e7 Updated Spanish translation 2014-06-30 13:50:32 +02:00
2fbd8f063e Scripting: catch errors from shell-perf-helper
When calling remote D-Bus methods, handle exceptions, log them
and exit, rather than just proceeding as if nothing happened.

https://bugzilla.gnome.org/show_bug.cgi?id=732349
2014-06-29 18:27:54 -04:00
f285f2c69f Scripting.createTestWindow(): take params
Take a parameter object rather than a long parameter list containing
multiple booleans.

https://bugzilla.gnome.org/show_bug.cgi?id=732349
2014-06-29 18:27:54 -04:00
e375e1a857 perf: fix bug in code to print out metrics
We don't normally hit the code in scripting.js to print metrics
because shell-perf-tool bypasses it, but there was a left-over
in the code that no longer works. Also add in the units to the
output.

https://bugzilla.gnome.org/show_bug.cgi?id=732349
2014-06-29 18:27:54 -04:00
910c95fa9b Scripting: exit if the perf script throws an error during collection
If an exception occurs while collecting parameters, exit rather than
just leaving the shell running in the main loop.

https://bugzilla.gnome.org/show_bug.cgi?id=732349
2014-06-29 18:27:54 -04:00
b95c0682b0 js/Makefile.am: Fix dependency generation with srcdir != builddir
If reusing an existing separate builddir, the generation of dependencies
for the JS resource file would fail because it couldn't find misc/config.js,
resulting in the resource file not being regenerated.

https://bugzilla.gnome.org/show_bug.cgi?id=732348
2014-06-29 18:27:53 -04:00
9f460a36f6 recorder: Fix typo
Both stage width and height are meant to be tracked.
2014-06-28 00:47:53 +02:00
98 changed files with 11895 additions and 8640 deletions

4
.gitignore vendored
View File

@ -24,10 +24,13 @@ data/gnome-shell-wayland.desktop.in
data/gnome-shell-extension-prefs.desktop
data/gnome-shell-extension-prefs.desktop.in
data/gschemas.compiled
data/perf-background.xml
data/org.gnome.shell.gschema.xml
data/org.gnome.shell.gschema.valid
data/org.gnome.shell.evolution.calendar.gschema.xml
data/org.gnome.shell.evolution.calendar.gschema.valid
data/org.gnome.Shell.PortalHelper.desktop
data/org.gnome.Shell.PortalHelper.service
docs/reference/*/*.args
docs/reference/*/*.bak
docs/reference/*/*.hierarchy
@ -80,6 +83,7 @@ src/gnome-shell-extension-tool
src/gnome-shell-hotplug-sniffer
src/gnome-shell-perf-helper
src/gnome-shell-perf-tool
src/gnome-shell-portal-helper
src/hotplug-sniffer/org.gnome.Shell.HotplugSniffer.service
src/run-js-test
src/test-recorder

58
NEWS
View File

@ -1,3 +1,61 @@
3.13.90
=======
* Make use of GLSL optional [Adel; #733623]
* Update on-screen-keyboard position on monitor changes [Cosimo; #733790]
* Improve window manager animations [Giovanni; #732857]
* Handle touch events [Carlos G.; #733633]
* Try to not show "New Window" action for single-window apps
[Giovanni; #722554]
* Fix overview exceeding screen size with many apps installed
[Carlos S.; #723496]
* Add Software to default favorites [Mathieu; #734406]
* Improve app picker <-> desktop transition [Carlos S.; #732901]
* Remove <shift>-magic for switcher popups [Christophe; #732296]
* Add a special background to use for performance testing [Owen; #734610]
* Add support for default disabled search providers [Giovanni; #734110]
* Fix portals that don't redirect properly [Giovanni; #733848]
* Fix history trimming in chat notifications [Giovanni; #733899]
* Try to use default calendar application [Florian; #722333]
* Only show location menu when geolocation is in use [Zeeshan; #731122]
* Misc. bug fixes and cleanups [Giovanni, Carlos G., Zeeshan, Carlos S.,
Cosimo; #711682, #733840, #734483, #734680, #733813, #735062]
Contributors:
Zeeshan Ali (Khattak), Mathieu Bridon, Giovanni Campagna, Cosimo Cecchi,
Piotr Drąg, Christophe Fergeau, Adel Gadllah, Carlos Garnacho,
Florian Müllner, Carlos Soriano, Jasper St. Pierre, Olav Vitters,
Owen W. Taylor
Translations:
Aurimas Černius [lt], MarMav [el], Inaki Larranaga Murgoitio [eu],
Reinout van Schouwen [nl], ngoswami [as], Fabio Tomat [fur],
Chao-Hsiung Liao [zh_HK, zh_TW]
3.13.4
======
* Handle portal login requests [Giovanni; #704416]
* Scale fonts on wayland on hiDPI devices [Adel; #732537]
* Fix default ibus candidate index labels [Rui; #702944]
* Add gestures for various system actions [Carlos G.]
* Add performance test script for the perf.gnome.org [Owen; #732350]
* Use new restart framework to improve restart visuals [Owen; #733026]
* Improve keynav in app folder popups [Carlos S.; #731477]
* Fix truncation of app search results [Carlos S.; #732416]
* Automatically update renamed desktop files in favorites [Kalev; #729429]
* Misc. bug fixes and cleanups [Giovanni, Yosef, Owen, Bastien, Javier;
#729823, #726401, #732301, #732348, #732349, #733498, #733540]
Contributors:
Giovanni Campagna, Adel Gadllah, Carlos Garnacho, Javier Hernández,
Kalev Lember, Rui Matos, Florian Müllner, Bastien Nocera, Yosef Or Boczko,
Carlos Soriano, Jasper St. Pierre, Owen W. Taylor
Translations:
Yuri Myasoedov [ru], Daniel Mustieles [es], Fran Diéguez [gl],
Cheng-Chia Tseng [zh_TW], A S Alam [pa], Benjamin Steinwender [de],
Enrico Nicoletto [pt_BR], MarMav [el], Yosef Or Boczko [he],
Kjartan Maraas [nb]
3.13.3
======
* Don't allow closing windows with attached modals [Florian; #729886]

View File

@ -1,5 +1,5 @@
AC_PREREQ(2.63)
AC_INIT([gnome-shell],[3.13.3],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_INIT([gnome-shell],[3.13.90],[https://bugzilla.gnome.org/enter_bug.cgi?product=gnome-shell],[gnome-shell])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([src/shell-global.c])
@ -76,7 +76,7 @@ AC_MSG_RESULT($enable_systemd)
CLUTTER_MIN_VERSION=1.15.90
GOBJECT_INTROSPECTION_MIN_VERSION=0.10.1
GJS_MIN_VERSION=1.39.0
MUTTER_MIN_VERSION=3.13.3
MUTTER_MIN_VERSION=3.13.90
GTK_MIN_VERSION=3.7.9
GIO_MIN_VERSION=2.37.0
LIBECAL_MIN_VERSION=3.5.3

View File

@ -74,6 +74,13 @@ dist_theme_DATA = \
theme/ws-switch-arrow-up.png \
theme/ws-switch-arrow-down.png
backgrounddir = $(pkgdatadir)
background_DATA = perf-background.xml
perf-background.xml: perf-background.xml.in
$(AM_V_GEN) sed -e "s|@datadir[@]|$(datadir)|" \
$< > $@ || rm $@
keysdir = @GNOME_KEYBINDINGS_KEYSDIR@
keys_in_files = 50-gnome-shell-system.xml.in
keys_DATA = $(keys_in_files:.xml.in=.xml)
@ -106,6 +113,7 @@ EXTRA_DIST = \
$(menu_DATA) \
$(convert_DATA) \
$(keys_in_files) \
perf-background.xml.in \
org.gnome.Shell.PortalHelper.desktop.in \
org.gnome.Shell.PortalHelper.service.in \
org.gnome.shell.gschema.xml.in.in
@ -117,6 +125,7 @@ CLEANFILES += \
$(desktop_DATA) \
$(keys_DATA) \
$(gsettings_SCHEMAS) \
perf-background.xml \
gschemas.compiled \
org.gnome.shell.gschema.valid \
org.gnome.shell.gschema.xml.in

View File

@ -31,7 +31,7 @@
</_description>
</key>
<key name="favorite-apps" type="as">
<default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Documents.desktop' ]</default>
<default>[ 'epiphany.desktop', 'evolution.desktop', 'empathy.desktop', 'rhythmbox.desktop', 'shotwell.desktop', 'libreoffice-writer.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Documents.desktop', 'org.gnome.Software.desktop' ]</default>
<_summary>List of desktop file IDs for favorite applications</_summary>
<_description>
The applications corresponding to these identifiers
@ -74,7 +74,6 @@
<child name="calendar" schema="org.gnome.shell.calendar"/>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
<child name="location" schema="org.gnome.shell.location"/>
</schema>
<schema id="org.gnome.shell.calendar" path="/org/gnome/shell/calendar/"
@ -144,32 +143,6 @@
</key>
</schema>
<enum id="org.gnome.shell.geoclue.AccuracyLevel">
<value value="0" nick="off"/>
<value value="1" nick="country"/>
<value value="4" nick="city"/>
<value value="5" nick="neighborhood"/>
<value value="6" nick="street"/>
<value value="8" nick="exact"/>
</enum>
<schema id="org.gnome.shell.location"
path="/org/gnome/shell/location/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="max-accuracy-level" enum="org.gnome.shell.geoclue.AccuracyLevel">
<default>'exact'</default>
<_summary>The maximum accuracy level of location.</_summary>
<_description>
Configures the maximum level of location accuracy applications are
allowed to see. Valid options are 'off' (disable location tracking),
'country', 'city', 'neighborhood', 'street', and 'exact' (typically
requires GPS receiver). Please keep in mind that this only controls
what GeoClue will allow applications to see and they can find user's
location on their own using network resources (albeit with street-level
accuracy at best).
</_description>
</key>
</schema>
<schema id="org.gnome.shell.app-switcher"
path="/org/gnome/shell/app-switcher/"
gettext-domain="@GETTEXT_PACKAGE@">

View File

@ -0,0 +1,31 @@
<!-- With an animated background, performance will differ depending on whether
one layer or two layers are being blended together. This messes up our
benchmarks. We could just benchmark a single image, but since blended
images are present for much of the day with the GNOME default background,
we want to make sure that also performs well; for that reason we ship
an "animated" background that animates super-slowly to use during
performance tests; it will be in the blended state until 2030. -->
<background>
<starttime>
<year>1990</year>
<month>1</month>
<day>1</day>
<hour>0</hour>
<minute>00</minute>
<second>00</second>
</starttime>
<!-- One transition that takes 40 years -->
<transition type="overlay">
<duration>1261440000.0</duration>
<from>@datadir@/backgrounds/gnome/adwaita-morning.jpg</from>
<to>@datadir@/backgrounds/gnome/adwaita-day.jpg</to>
</transition>
<!-- A single slide doesn't work, so another slide for 1 minute after 40 years -->
<static>
<duration>60</duration>
<file>/usr/share/backgrounds/gnome/Sandstone.jpg</file>
</static>
</background>

View File

@ -478,7 +478,7 @@ StScrollBar StButton#vhandle:active {
/* Common radii */
#searchEntry,
.search-entry,
.modal-dialog-button,
.notification-button,
.hotplug-notification-item,
@ -500,7 +500,7 @@ StScrollBar StButton#vhandle:active {
/* Entries */
#searchEntry,
.search-entry,
.login-dialog StEntry,
.notification StEntry,
.modal-dialog StEntry {
@ -512,7 +512,7 @@ StScrollBar StButton#vhandle:active {
padding: 4px 12px;
}
#searchEntry,
.search-entry,
.login-dialog StEntry,
.run-dialog-entry,
.notification StEntry {
@ -524,8 +524,8 @@ StScrollBar StButton#vhandle:active {
box-shadow: inset 0px 2px 4px rgba(0,0,0,0.6);
}
#searchEntry:focus,
#searchEntry:hover,
.search-entry:focus,
.search-entry:hover,
.login-dialog StEntry:focus,
.notification StEntry:focus,
.modal-dialog StEntry {
@ -542,18 +542,18 @@ StScrollBar StButton#vhandle:active {
border: 2px solid #3465a4;
}
#searchEntry {
.search-entry {
border-color: rgba(245,245,245,0.3);
color: rgb(192, 192, 192);
caret-color: rgb(192, 192, 192);
}
#searchEntry:hover {
.search-entry:hover {
color: rgb(128, 128, 128);
caret-color: rgb(128, 128, 128);
}
#searchEntry:focus {
.search-entry:focus {
color: rgb(64, 64, 64);
caret-color: rgb(64, 64, 64);
font-weight: bold;
@ -917,7 +917,7 @@ StScrollBar StButton#vhandle:active {
/* Search Box */
#searchEntry {
.search-entry {
width: 320px;
}
@ -926,8 +926,8 @@ StScrollBar StButton#vhandle:active {
color: #c0c0c0;
}
#searchEntry:hover .search-entry-icon,
#searchEntry:focus .search-entry-icon {
.search-entry:hover .search-entry-icon,
.search-entry:focus .search-entry-icon {
color: #8d8f8a;
}
@ -2092,6 +2092,11 @@ StScrollBar StButton#vhandle:active {
font-size: 10pt;
}
/* Restart message */
.restart-message {
font-size: 14pt;
}
/* ShellMountOperation Dialogs */
.shell-mount-operation-icon {
icon-size: 48px;

View File

@ -27,7 +27,9 @@ its dependencies to build from tarballs.</description>
<download-page rdf:resource="http://download.gnome.org/sources/gnome-shell/" />
<bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=gnome-shell" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
<category rdf:resource="http://api.gnome.org/doap-extensions#core" />
<programming-language>JavaScript</programming-language>
<programming-language>C</programming-language>
<maintainer>
<foaf:Person>

View File

@ -13,7 +13,7 @@ misc/config.js: misc/config.js.in Makefile
-e "s|[@]sysconfdir@|$(sysconfdir)|g" \
$< > $@
js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/js-resources.gresource.xml)
js_resource_files = $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate-dependencies $(srcdir)/js-resources.gresource.xml)
js-resources.h: js-resources.gresource.xml $(js_resource_files) misc/config.js
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) --sourcedir=$(builddir) --generate --c-name shell_js_resources $<
js-resources.c: js-resources.gresource.xml $(js_resource_files) misc/config.js

View File

@ -54,15 +54,17 @@ const Application = new Lang.Class({
this._startupUuid = null;
this._loaded = false;
this._skipMainWindow = false;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
},
_extensionAvailable: function(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
if (!extension)
return false;
if (ExtensionUtils.isOutOfDate(extension))
if (checkVersion && ExtensionUtils.isOutOfDate(extension))
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))

View File

@ -926,6 +926,8 @@ const LoginDialog = new Lang.Class({
this.actor.show();
this.actor.opacity = 0;
Main.pushModal(this.actor, { keybindingMode: Shell.KeyBindingMode.LOGIN_SCREEN });
Tweener.addTween(this.actor,
{ opacity: 255,
time: 1,
@ -935,7 +937,8 @@ const LoginDialog = new Lang.Class({
},
close: function() {
Main.ctrlAltTabManager.removeGroup(this.dialogLayout);
Main.popModal(this.actor);
Main.ctrlAltTabManager.removeGroup(this.actor);
},
cancel: function() {

View File

@ -25,6 +25,7 @@
<file>misc/util.js</file>
<file>perf/core.js</file>
<file>perf/hwtest.js</file>
<file>portalHelper/main.js</file>

View File

@ -72,6 +72,9 @@ function run() {
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
// Enable recording of timestamps for different points in the frame cycle
global.frame_timestamps = true;
Main.overview.connect('shown', function() {
Scripting.scriptEvent('overviewShowDone');
});
@ -87,7 +90,10 @@ function run() {
yield Scripting.destroyTestWindows();
for (let k = 0; k < config.count; k++)
yield Scripting.createTestWindow(config.width, config.height, config.alpha, config.maximized);
yield Scripting.createTestWindow({ width: config.width,
height: config.height,
alpha: config.alpha,
maximized: config.maximized });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);

308
js/perf/hwtest.js Normal file
View File

@ -0,0 +1,308 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Meta = imports.gi.Meta;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
const Shell = imports.gi.Shell;
let METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
overviewShowTime:
{ description: "Time to switch to overview view, first time",
units: "us" },
applicationsShowTime:
{ description: "Time to switch to applications view, first time",
units: "us" },
mainViewRedrawTime:
{ description: "Time to redraw the main view, full screen",
units: "us" },
overviewRedrawTime:
{ description: "Time to redraw the overview, full screen, 5 windows",
units: "us" },
applicationRedrawTime:
{ description: "Time to redraw frame with a maximized application update",
units: "us" },
geditStartTime:
{ description: "Time from gedit launch to window drawn",
units: "us" },
}
function waitAndDraw(milliseconds) {
let cb;
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame',
function(timeline, frame) {
global.stage.queue_redraw();
});
timeline.connect('completed',
function() {
timeline.stop();
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function waitSignal(object, signal) {
let cb;
let id = object.connect(signal, function() {
object.disconnect(id);
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
}
function extractBootTimestamp() {
let sp = Gio.Subprocess.new(['journalctl', '-b',
'MESSAGE_ID=7d4958e842da4a758f6c1cdc7b36dcc5',
'UNIT=graphical.target',
'-o',
'json'],
Gio.SubprocessFlags.STDOUT_PIPE);
let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) {
let [line, length] = datastream.read_line_utf8(null);
if (line === null)
break;
let fields = JSON.parse(line);
result = Number(fields['__MONOTONIC_TIMESTAMP']);
}
datastream.close(null);
return result;
}
function run() {
Scripting.defineScriptEvent("desktopShown", "Finished initial animation");
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
Scripting.defineScriptEvent("mainViewDrawStart", "Drawing main view");
Scripting.defineScriptEvent("mainViewDrawDone", "Ending timing main view drawing");
Scripting.defineScriptEvent("overviewDrawStart", "Drawing overview");
Scripting.defineScriptEvent("overviewDrawDone", "Ending timing overview drawing");
Scripting.defineScriptEvent("redrawTestStart", "Drawing application window");
Scripting.defineScriptEvent("redrawTestDone", "Ending timing application window drawing");
Scripting.defineScriptEvent("collectTimings", "Accumulate frame timings from redraw tests");
Scripting.defineScriptEvent("geditLaunch", "gedit application launch");
Scripting.defineScriptEvent("geditFirstFrame", "first frame of gedit window drawn");
yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown');
Gtk.Settings.get_default().gtk_enable_animations = false;
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
yield Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart');
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
yield Scripting.sleep(1000);
Main.overview.hide();
yield Scripting.waitLeisure();
////////////////////////////////////////
// Tests of redraw speed
////////////////////////////////////////
global.frame_timestamps = true;
global.frame_finish_timestamp = true;
for (let k = 0; k < 5; k++)
yield Scripting.createTestWindow(640, 480,
{ maximized: true });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('mainViewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('mainViewDrawDone');
Main.overview.show();
Scripting.waitLeisure();
yield Scripting.sleep(1500);
Scripting.scriptEvent('overviewDrawStart');
yield waitAndDraw(1000);
Scripting.scriptEvent('overviewDrawDone');
yield Scripting.destroyTestWindows();
Main.overview.hide();
yield Scripting.createTestWindow(640, 480,
{ maximized: true,
redraws: true});
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestStart');
yield Scripting.sleep(1000);
Scripting.scriptEvent('redrawTestDone');
yield Scripting.sleep(1000);
Scripting.scriptEvent('collectTimings');
yield Scripting.destroyTestWindows();
global.frame_timestamps = false;
global.frame_finish_timestamp = false;
yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop');
Scripting.scriptEvent('geditLaunch');
app.activate();
let windows = app.get_windows();
if (windows.length > 0)
throw new Error('gedit was already running');
while (windows.length == 0) {
yield waitSignal(global.display, 'window-created');
windows = app.get_windows();
}
let actor = windows[0].get_compositor_private();
yield waitSignal(actor, 'first-frame');
Scripting.scriptEvent('geditFirstFrame');
yield Scripting.sleep(1000);
windows[0].delete(global.get_current_time());
yield Scripting.sleep(1000);
Gtk.Settings.get_default().gtk_enable_animations = true;
}
let overviewShowStart;
let applicationsShowStart;
let stagePaintStart;
let redrawTiming;
let redrawTimes = {};
let geditLaunchTime;
function script_desktopShown(time) {
let bootTimestamp = extractBootTimestamp();
METRICS.timeToDesktop.value = time - bootTimestamp;
}
function script_overviewShowStart(time) {
overviewShowStart = time;
}
function script_overviewShowDone(time) {
METRICS.overviewShowTime.value = time - overviewShowStart;
}
function script_applicationsShowStart(time) {
applicationsShowStart = time;
}
function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart;
}
function script_mainViewDrawStart(time) {
redrawTiming = 'mainView';
}
function script_mainViewDrawDone(time) {
redrawTiming = null;
}
function script_overviewDrawStart(time) {
redrawTiming = 'overview';
}
function script_overviewDrawDone(time) {
redrawTiming = null;
}
function script_redrawTestStart(time) {
redrawTiming = 'application';
}
function script_redrawTestDone(time) {
redrawTiming = null;
}
function script_collectTimings(time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort(function(a, b) { return a - b });
let len = times.length;
let median;
if (len == 0)
median = -1;
else if (len % 2 == 1)
median = times[(len - 1)/ 2];
else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[timing + 'RedrawTime'].value = median;
}
}
function script_geditLaunch(time) {
geditLaunchTime = time;
}
function script_geditFirstFrame(time) {
METRICS.geditStartTime.value = time - geditLaunchTime;
}
function clutter_stagePaintStart(time) {
stagePaintStart = time;
}
function clutter_paintCompletedTimestamp(time) {
if (redrawTiming != null && stagePaintStart != null) {
if (!(redrawTiming in redrawTimes))
redrawTimes[redrawTiming] = [];
redrawTimes[redrawTiming].push(time - stagePaintStart);
}
stagePaintStart = null;
}

View File

@ -49,13 +49,14 @@ const PortalWindow = new Lang.Class({
_init: function(application, url, timestamp, doneCallback) {
this.parent({ application: application });
if (url) {
this._uri = new Soup.URI(uri);
} else {
if (!url) {
url = 'http://www.gnome.org';
this._uri = null;
this._everSeenRedirect = false;
this._originalUrlWasGnome = true;
} else {
this._originalUrlWasGnome = false;
}
this._uri = new Soup.URI(url);
this._everSeenRedirect = false;
this._originalUrl = url;
this._doneCallback = doneCallback;
this._lastRecheck = 0;
@ -110,37 +111,7 @@ const PortalWindow = new Lang.Class({
let request = decision.get_request();
let uri = new Soup.URI(request.get_uri());
if (this._uri != null) {
if (!uri.host_equal(uri, this._uri)) {
// We *may* have finished here, but we don't know for
// sure. Tell gnome-shell to run another connectivity check
// (but ratelimit the checks, we don't want to spam
// gnome.org for portals that have 10 or more internal
// redirects - and unfortunately they exist)
// If we hit the rate limit, we also queue a recheck
// when the window is closed, just in case we miss the
// final check and don't realize we're connected
// This should not be a problem in the cancelled logic,
// because if the user doesn't want to start the login,
// we should not see any redirect at all, outside this._uri
let now = GLib.get_monotonic_time();
let shouldRecheck = (now - this._lastRecheck) >
CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT;
if (shouldRecheck) {
this._lastRecheck = now;
this._recheckAtExit = false;
this._doneCallback(PortalHelperResult.RECHECK);
} else {
this._recheckAtExit = true;
}
}
// Update the URI, in case of chained redirects, so we still
// think we're doing the login until gnome-shell kills us
this._uri = uri;
} else {
if (!uri.host_equal(this._uri) && this._originalUrlWasGnome) {
if (uri.get_host() == 'www.gnome.org' && this._everSeenRedirect) {
// Yay, we got to gnome!
decision.ignore();
@ -151,6 +122,34 @@ const PortalWindow = new Lang.Class({
}
}
// We *may* have finished here, but we don't know for
// sure. Tell gnome-shell to run another connectivity check
// (but ratelimit the checks, we don't want to spam
// nmcheck.gnome.org for portals that have 10 or more internal
// redirects - and unfortunately they exist)
// If we hit the rate limit, we also queue a recheck
// when the window is closed, just in case we miss the
// final check and don't realize we're connected
// This should not be a problem in the cancelled logic,
// because if the user doesn't want to start the login,
// we should not see any redirect at all, outside this._uri
let now = GLib.get_monotonic_time();
let shouldRecheck = (now - this._lastRecheck) >
CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT;
if (shouldRecheck) {
this._lastRecheck = now;
this._recheckAtExit = false;
this._doneCallback(PortalHelperResult.RECHECK);
} else {
this._recheckAtExit = true;
}
// Update the URI, in case of chained redirects, so we still
// think we're doing the login until gnome-shell kills us
this._uri = uri;
decision.use();
return true;
},

View File

@ -151,13 +151,13 @@ const AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length);
},
_keyPressHandler: function(keysym, backwards, action) {
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
this._select(this._selectedIndex, backwards ? this._previousWindow() : this._nextWindow());
this._select(this._selectedIndex, this._nextWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_GROUP_BACKWARD) {
this._select(this._selectedIndex, this._previousWindow());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS) {
this._select(backwards ? this._previous() : this._next());
this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous());
} else if (this._thumbnailsFocused) {
@ -400,9 +400,9 @@ const WindowSwitcherPopup = new Lang.Class({
this._select(1);
},
_keyPressHandler: function(keysym, backwards, action) {
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(backwards ? this._previous() : this._next());
this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_WINDOWS_BACKWARD) {
this._select(this._previous());
} else {

View File

@ -181,17 +181,35 @@ const BaseAppView = new Lang.Class({
});
Signals.addSignalMethods(BaseAppView.prototype);
const PageIndicatorsActor = new Lang.Class({
Name:'PageIndicatorsActor',
Extends: St.BoxLayout,
_init: function() {
this.parent({ style_class: 'page-indicators',
vertical: true,
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
reactive: true,
clip_to_allocation: true });
},
vfunc_get_preferred_height: function(forWidth) {
// We want to request the natural height of all our children as our
// natural height, so we chain up to St.BoxLayout, but we only request 0
// as minimum height, since it's not that important if some indicators
// are not shown
let [, natHeight] = this.parent(forWidth);
return [0, natHeight];
}
});
const PageIndicators = new Lang.Class({
Name:'PageIndicators',
_init: function() {
this.actor = new St.BoxLayout({ style_class: 'page-indicators',
vertical: true,
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.CENTER,
reactive: true });
this.actor = new PageIndicatorsActor();
this._nPages = 0;
this._currentPage = undefined;
@ -612,6 +630,7 @@ const AllView = new Lang.Class({
if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) {
this._adjustment.value = 0;
this._currentPage = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this,
function() {
this._pageIndicators.setNPages(this._grid.nPages());
@ -946,7 +965,7 @@ const FolderView = new Lang.Class({
},
createFolderIcon: function(size) {
let layout = new Clutter.TableLayout();
let layout = new Clutter.GridLayout();
let icon = new St.Widget({ layout_manager: layout,
style_class: 'app-folder-icon' });
layout.hookup_style(icon);
@ -962,7 +981,7 @@ const FolderView = new Lang.Class({
} else {
bin = new St.Bin({ width: subSize, height: subSize });
}
layout.pack(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2));
layout.attach(bin, rtl ? (i + 1) % 2 : i % 2, Math.floor(i / 2), 1, 1);
}
return icon;
@ -1253,6 +1272,51 @@ const AppFolderPopup = new Lang.Class({
}));
this._grabHelper = new GrabHelper.GrabHelper(this.actor);
this._grabHelper.addActor(Main.layoutManager.overviewGroup);
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
},
_onKeyPress: function(actor, event) {
if (global.stage.get_key_focus() != actor)
return Clutter.EVENT_PROPAGATE;
// Since we need to only grab focus on one item child when the user
// actually press a key we don't use navigate_focus when opening
// the popup.
// Instead of that, grab the focus on the AppFolderPopup actor
// and actually moves the focus to a child only when the user
// actually press a key.
// It should work with just grab_key_focus on the AppFolderPopup
// actor, but since the arrow keys are not wrapping_around the focus
// is not grabbed by a child when the widget that has the current focus
// is the same that is requesting focus, so to make it works with arrow
// keys we need to connect to the key-press-event and navigate_focus
// when that happens using TAB_FORWARD or TAB_BACKWARD instead of arrow
// keys
// Use TAB_FORWARD for down key and right key
// and TAB_BACKWARD for up key and left key on ltr
// languages
let direction;
let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR;
switch (event.get_key_symbol()) {
case Clutter.Down:
direction = Gtk.DirectionType.TAB_FORWARD;
break;
case Clutter.Right:
direction = isLtr ? Gtk.DirectionType.TAB_FORWARD :
Gtk.DirectionType.TAB_BACKWARD;
break;
case Clutter.Up:
direction = Gtk.DirectionType.TAB_BACKWARD;
break;
case Clutter.Left:
direction = isLtr ? Gtk.DirectionType.TAB_BACKWARD :
Gtk.DirectionType.TAB_FORWARD;
break;
default:
return Clutter.EVENT_PROPAGATE;
}
return actor.navigate_focus(null, direction, false);
},
toggle: function() {
@ -1278,8 +1342,6 @@ const AppFolderPopup = new Lang.Class({
this._boxPointer.show(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE);
this.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
this.emit('open-state-changed', true);
},
@ -1339,7 +1401,9 @@ const AppIcon = new Lang.Class({
this.actor.label_actor = this.icon.label;
this.actor.connect('leave-event', Lang.bind(this, this._onLeaveEvent));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('clicked', Lang.bind(this, this._onClicked));
this.actor.connect('popup-menu', Lang.bind(this, this._onKeyboardPopupMenu));
@ -1395,17 +1459,26 @@ const AppIcon = new Lang.Class({
this.actor.remove_style_class_name('running');
},
_setPopupTimeout: function() {
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu();
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(this._menuTimeoutId, '[gnome-shell] this.popupMenu');
},
_onLeaveEvent: function(actor, event) {
this.actor.fake_release();
this._removeMenuTimeout();
},
_onButtonPress: function(actor, event) {
let button = event.get_button();
if (button == 1) {
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT,
Lang.bind(this, function() {
this._menuTimeoutId = 0;
this.popupMenu();
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(this._menuTimeoutId, '[gnome-shell] this.popupMenu');
this._setPopupTimeout();
} else if (button == 3) {
this.popupMenu();
return Clutter.EVENT_STOP;
@ -1413,16 +1486,22 @@ const AppIcon = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_onTouchEvent: function (actor, event) {
if (event.type() == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return Clutter.EVENT_PROPAGATE;
},
_onClicked: function(actor, button) {
this._removeMenuTimeout();
if (button == 1) {
if (button == 0 || button == 1) {
this._onActivate(Clutter.get_current_event());
} else if (button == 2) {
this.app.open_new_window(-1);
Main.overview.hide();
}
return false;
},
_onKeyboardPopupMenu: function() {
@ -1567,12 +1646,14 @@ const AppIconMenu = new Lang.Class({
if (!this._source.app.is_window_backed()) {
this._appendSeparator();
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
}));
this._appendSeparator();
if (this._source.app.can_open_new_window()) {
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', Lang.bind(this, function() {
this._source.app.open_new_window(-1);
this.emit('activate-window', null);
}));
this._appendSeparator();
}
let appInfo = this._source.app.get_app_info();
let actions = appInfo.list_actions();

View File

@ -6,6 +6,26 @@ const Signals = imports.signals;
const Main = imports.ui.main;
const RENAMED_DESKTOP_IDS = {
'baobab.desktop': 'org.gnome.baobab.desktop',
'cheese.desktop': 'org.gnome.Cheese.desktop',
'dconf-editor.desktop': 'ca.desrt.dconf-editor.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'gcalctool.desktop': 'gnome-calculator.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'gnome-chess.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.Application.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
};
const AppFavorites = new Lang.Class({
Name: 'AppFavorites',
@ -24,6 +44,21 @@ const AppFavorites = new Lang.Class({
reload: function() {
let ids = global.settings.get_strv(this.FAVORITE_APPS_KEY);
// Map old desktop file names to the current ones
let updated = false;
ids = ids.map(function (id) {
let newId = RENAMED_DESKTOP_IDS[id];
if (newId !== undefined) {
updated = true;
return newId;
}
return id;
});
// ... and write back the updated desktop file names
if (updated)
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
let appSys = Shell.AppSystem.get_default();
let apps = ids.map(function (id) {
return appSys.lookup_app(id);

View File

@ -1,5 +1,103 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
// READ THIS FIRST
// Background handling is a maze of objects, both objects in this file, and
// also objects inside Mutter. They all have a role.
//
// BackgroundManager
// The only object that other parts of GNOME Shell deal with; a
// BackgroundManager creates background actors and adds them to
// the specified container. When the background is changed by the
// user it will fade out the old actor and fade in the new actor.
// (This is separate from the fading for an animated background,
// since using two actors is quite inefficient.)
//
// MetaBackgroundImage
// An object represented an image file that will be used for drawing
// the background. MetaBackgroundImage objects asynchronously load,
// so they are first created in an unloaded state, then later emit
// a ::loaded signal when the Cogl object becomes available.
//
// MetaBackgroundImageCache
// A cache from filename to MetaBackgroundImage.
//
// BackgroundSource
// An object that is created for each GSettings schema (separate
// settings schemas are used for the lock screen and main background),
// and holds a reference to shared Background objects.
//
// MetaBackground
// Holds the specification of a background - a background color
// or gradient and one or two images blended together.
//
// Background
// JS delegate object that Connects a MetaBackground to the GSettings
// schema for the background.
//
// Animation
// A helper object that handles loading a XML-based animation; it is a
// wrapper for GnomeDesktop.BGSlideShow
//
// MetaBackgroundActor
// An actor that draws the background for a single monitor
//
// BackgroundActor
// JS delegate object for MetaBackgroundActor.
//
// BackgroundCache
// A cache of Settings schema => BackgroundSource and of a single Animation.
// Also used to share file monitors.
//
// A static image, background color or gradient is relatively straightforward. The
// calling code creates a separate BackgroundManager for each monitor. Since they
// are created for the same GSettings schema, they will use the same BackgroundSource
// object, which provides a single Background and correspondingly a single
// MetaBackground object.
//
// BackgroundManager--- ----- BackgroundManager
// BackgroundActor \./ BackgroundActor
// | | \ | / | |
// | | BackgroundSource | | looked up in BackgroundCache
// | \ | / |
// | `-------Background-------` |
// MetaBackgroundActor | MetaBackgroundActor
// \ | /
// `--------- MetaBackground-------`
// |
// MetaBackgroundImage looked up in MetaBackgroundImageCache
//
// The animated case is tricker because the animation XML file can specify different
// files for different monitor resolutions and aspect ratios. For this reason,
// the BackgroundSource provides different Background share a single Animation object,
// which tracks the animation, but use different MetaBackground objects. In the
// common case, the different MetaBackground objects will be created for the
// same filename and look up the *same* MetaBackgroundImage object, so there is
// little wasted memory:
//
// BackgroundManager--- ----- BackgroundManager
// BackgroundActor \./ BackgroundActor
// | | \ | / | |
// | | BackgroundSource | | looked up in BackgroundCache
// | \ / \ / |
// | Background Background |
// | | \ / | |
// | | Animation | | looked up in BackgroundCache
// MetaBackg|oundActor MetaB|ckgroundActor
// | | | |
// | | | |
// MetaBackground MetaBackground
// \ /
// MetaBackgroundImage looked up in MetaBackgroundImageCache
// MetaBackgroundImage
//
// But the case of different filenames and different background images
// is possible as well:
// ....
// MetaBackground MetaBackground
// | |
// MetaBackgroundImage MetaBackgroundImage
// MetaBackgroundImage MetaBackgroundImage
const Clutter = imports.gi.Clutter;
const GDesktopEnums = imports.gi.GDesktopEnums;
const Gio = imports.gi.Gio;
@ -36,235 +134,25 @@ const BackgroundCache = new Lang.Class({
Name: 'BackgroundCache',
_init: function() {
this._patterns = [];
this._images = [];
this._pendingFileLoads = [];
this._fileMonitors = {};
this._pendingFileLoads = [];
this._fileMonitors = {};
this._backgroundSources = {};
},
getPatternContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
color: null,
secondColor: null,
shadingType: null,
effects: Meta.BackgroundEffects.NONE });
let content = null;
let candidateContent = null;
for (let i = 0; i < this._patterns.length; i++) {
if (this._patterns[i].get_shading() != params.shadingType)
continue;
if (!params.color.equal(this._patterns[i].get_color()))
continue;
if (params.shadingType != GDesktopEnums.BackgroundShading.SOLID &&
!params.secondColor.equal(this._patterns[i].get_second_color()))
continue;
candidateContent = this._patterns[i];
if (params.effects != this._patterns[i].effects)
continue;
break;
}
if (candidateContent) {
content = candidateContent.copy(params.monitorIndex, params.effects);
} else {
content = new Meta.Background({ meta_screen: global.screen,
monitor: params.monitorIndex,
effects: params.effects });
if (params.shadingType == GDesktopEnums.BackgroundShading.SOLID) {
content.load_color(params.color);
} else {
content.load_gradient(params.shadingType, params.color, params.secondColor);
}
}
this._patterns.push(content);
return content;
},
_monitorFile: function(filename) {
monitorFile: function(filename) {
if (this._fileMonitors[filename])
return;
let file = Gio.File.new_for_path(filename);
let monitor = file.monitor(Gio.FileMonitorFlags.NONE, null);
let signalId = monitor.connect('changed',
Lang.bind(this, function() {
for (let i = 0; i < this._images.length; i++) {
if (this._images[i].get_filename() == filename)
this._images.splice(i, 1);
}
monitor.disconnect(signalId);
this.emit('file-changed', filename);
}));
monitor.connect('changed',
Lang.bind(this, function() {
this.emit('file-changed', filename);
}));
this._fileMonitors[filename] = monitor;
},
_removeContent: function(contentList, content) {
let index = contentList.indexOf(content);
if (index < 0)
throw new Error("Trying to remove invalid content: " + content);
contentList.splice(index, 1);
},
removePatternContent: function(content) {
this._removeContent(this._patterns, content);
},
removeImageContent: function(content) {
let filename = content.get_filename();
let hasOtherUsers = this._images.some(function(content) { return filename == content.get_filename(); });
if (!hasOtherUsers)
delete this._fileMonitors[filename];
this._removeContent(this._images, content);
},
_attachCallerToFileLoad: function(caller, fileLoad) {
fileLoad.callers.push(caller);
if (!caller.cancellable)
return;
caller.cancellable.connect(Lang.bind(this, function() {
let idx = fileLoad.callers.indexOf(caller);
fileLoad.callers.splice(idx, 1);
if (fileLoad.callers.length == 0) {
fileLoad.cancellable.cancel();
let idx = this._pendingFileLoads.indexOf(fileLoad);
this._pendingFileLoads.splice(idx, 1);
}
}));
},
_loadImageContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
style: null,
filename: null,
effects: Meta.BackgroundEffects.NONE,
cancellable: null,
onFinished: null });
let caller = { monitorIndex: params.monitorIndex,
effects: params.effects,
cancellable: params.cancellable,
onFinished: params.onFinished };
for (let i = 0; i < this._pendingFileLoads.length; i++) {
let fileLoad = this._pendingFileLoads[i];
if (fileLoad.filename == params.filename &&
fileLoad.style == params.style) {
this._attachCallerToFileLoad(caller, fileLoad);
return;
}
}
let fileLoad = { filename: params.filename,
style: params.style,
cancellable: new Gio.Cancellable(),
callers: [] };
this._attachCallerToFileLoad(caller, fileLoad);
let content = new Meta.Background({ meta_screen: global.screen });
content.load_file_async(params.filename,
params.style,
params.cancellable,
Lang.bind(this,
function(object, result) {
try {
content.load_file_finish(result);
this._monitorFile(params.filename);
} catch(e) {
content = null;
}
for (let i = 0; i < fileLoad.callers.length; i++) {
let caller = fileLoad.callers[i];
if (caller.onFinished) {
let newContent;
if (content) {
newContent = content.copy(caller.monitorIndex, caller.effects);
this._images.push(newContent);
}
caller.onFinished(newContent);
}
}
let idx = this._pendingFileLoads.indexOf(fileLoad);
this._pendingFileLoads.splice(idx, 1);
}));
},
getImageContent: function(params) {
params = Params.parse(params, { monitorIndex: 0,
style: null,
filename: null,
effects: Meta.BackgroundEffects.NONE,
cancellable: null,
onFinished: null });
let content = null;
let candidateContent = null;
for (let i = 0; i < this._images.length; i++) {
if (this._images[i].get_style() != params.style)
continue;
if (this._images[i].get_filename() != params.filename)
continue;
if (params.style == GDesktopEnums.BackgroundStyle.SPANNED &&
this._images[i].monitor != params.monitorIndex)
continue;
candidateContent = this._images[i];
if (params.effects != this._images[i].effects)
continue;
break;
}
if (candidateContent) {
content = candidateContent.copy(params.monitorIndex, params.effects);
if (params.cancellable && params.cancellable.is_cancelled())
content = null;
else
this._images.push(content);
if (params.onFinished)
params.onFinished(content);
} else {
this._loadImageContent({ filename: params.filename,
style: params.style,
effects: params.effects,
monitorIndex: params.monitorIndex,
cancellable: params.cancellable,
onFinished: params.onFinished });
}
},
getAnimation: function(params) {
params = Params.parse(params, { filename: null,
onLoaded: null });
@ -282,7 +170,6 @@ const BackgroundCache = new Lang.Class({
let animation = new Animation({ filename: params.filename });
animation.load(Lang.bind(this, function() {
this._monitorFile(params.filename);
this._animationFilename = params.filename;
this._animation = animation;
@ -294,6 +181,31 @@ const BackgroundCache = new Lang.Class({
GLib.Source.set_name_by_id(id, '[gnome-shell] params.onLoaded');
}
}));
},
getBackgroundSource: function(layoutManager, settingsSchema) {
// The layoutManager is always the same one; we pass in it since
// Main.layoutManager may not be set yet
if (!(settingsSchema in this._backgroundSources)) {
this._backgroundSources[settingsSchema] = new BackgroundSource(layoutManager, settingsSchema);
this._backgroundSources[settingsSchema]._useCount = 1;
} else {
this._backgroundSources[settingsSchema]._useCount++;
}
return this._backgroundSources[settingsSchema];
},
releaseBackgroundSource: function(settingsSchema) {
if (settingsSchema in this._backgroundSources) {
let source = this._backgroundSources[settingsSchema];
source._useCount--;
if (source._useCount == 0) {
delete this._backgroundSources[settingsSchema];
source.destroy();
}
}
}
});
Signals.addSignalMethods(BackgroundCache.prototype);
@ -310,26 +222,18 @@ const Background = new Lang.Class({
_init: function(params) {
params = Params.parse(params, { monitorIndex: 0,
layoutManager: Main.layoutManager,
effects: Meta.BackgroundEffects.NONE,
settings: null });
this.actor = new Meta.BackgroundGroup();
this.actor._delegate = this;
settings: null,
filename: null,
style: null });
this._destroySignalId = this.actor.connect('destroy',
Lang.bind(this, this._destroy));
this.background = new Meta.Background({ 'meta-screen': global.screen });
this._settings = params.settings;
this._filename = params.filename;
this._style = params.style;
this._monitorIndex = params.monitorIndex;
this._layoutManager = params.layoutManager;
this._effects = params.effects;
this._fileWatches = {};
this._pattern = null;
// contains a single image for static backgrounds and
// two images (from and to) for slide shows
this._images = {};
this._brightness = 1.0;
this._vignetteSharpness = 0.2;
this._cancellable = new Gio.Cancellable();
this.isLoaded = false;
@ -340,7 +244,7 @@ const Background = new Lang.Class({
this._load();
},
_destroy: function() {
destroy: function() {
this._cancellable.cancel();
if (this._updateAnimationTimeoutId) {
@ -355,28 +259,6 @@ const Background = new Lang.Class({
}
this._fileWatches = null;
if (this._pattern) {
if (this._pattern.content)
this._cache.removePatternContent(this._pattern.content);
this._pattern.destroy();
this._pattern = null;
}
keys = Object.keys(this._images);
for (i = 0; i < keys.length; i++) {
let actor = this._images[keys[i]];
if (actor.content)
this._cache.removeImageContent(actor.content);
actor.destroy();
this._images[keys[i]] = null;
}
this.actor.disconnect(this._destroySignalId);
this._destroySignalId = 0;
if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0;
@ -405,22 +287,17 @@ const Background = new Lang.Class({
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
let content = this._cache.getPatternContent({ monitorIndex: this._monitorIndex,
effects: this._effects,
color: color,
secondColor: secondColor,
shadingType: shadingType });
this._pattern = new Meta.BackgroundActor();
this.actor.add_child(this._pattern);
this._pattern.content = content;
if (shadingType == GDesktopEnums.BackgroundShading.SOLID)
this.background.set_color(color);
else
this.background.set_gradient(shadingType, color, secondColor);
},
_watchCacheFile: function(filename) {
_watchFile: function(filename) {
if (this._fileWatches[filename])
return;
this._cache.monitorFile(filename);
let signalId = this._cache.connect('file-changed',
Lang.bind(this, function(cache, changedFile) {
if (changedFile == filename) {
@ -430,82 +307,46 @@ const Background = new Lang.Class({
this._fileWatches[filename] = signalId;
},
_ensureImage: function(index) {
if (this._images[index])
return;
let actor = new Meta.BackgroundActor();
// The background pattern is the first actor in
// the group, and all images should be above that.
this.actor.insert_child_at_index(actor, index + 1);
this._images[index] = actor;
},
_updateImage: function(index, content, filename) {
content.brightness = this._brightness;
content.vignette_sharpness = this._vignetteSharpness;
let image = this._images[index];
if (image.content)
this._cache.removeImageContent(image.content);
image.content = content;
this._watchCacheFile(filename);
},
_updateAnimationProgress: function() {
if (this._images[1])
this._images[1].opacity = this._animation.transitionProgress * 255;
this._queueUpdateAnimation();
},
_updateAnimation: function() {
this._updateAnimationTimeoutId = 0;
this._animation.update(this._layoutManager.monitors[this._monitorIndex]);
let files = this._animation.keyFrameFiles;
if (files.length == 0) {
let finish = Lang.bind(this, function() {
this._setLoaded();
if (files.length > 1) {
this.background.set_blend(files[0], files[1],
this._animation.transitionProgress,
this._style);
} else if (files.length > 0) {
this.background.set_filename(files[0], this._style);
} else {
this.background.set_filename(null, this._style);
}
this._queueUpdateAnimation();
return;
}
});
let cache = Meta.BackgroundImageCache.get_default();
let numPendingImages = files.length;
let images = [];
for (let i = 0; i < files.length; i++) {
if (this._images[i] && this._images[i].content &&
this._images[i].content.get_filename() == files[i]) {
this._watchFile(files[i]);
let image = cache.load(files[i]);
images.push(image);
if (image.is_loaded()) {
numPendingImages--;
if (numPendingImages == 0)
this._updateAnimationProgress();
continue;
finish();
} else {
let id = image.connect('loaded',
Lang.bind(this, function() {
image.disconnect(id);
numPendingImages--;
if (numPendingImages == 0)
finish();
}));
}
this._cache.getImageContent({ monitorIndex: this._monitorIndex,
effects: this._effects,
style: this._style,
filename: files[i],
cancellable: this._cancellable,
onFinished: Lang.bind(this, function(content, i) {
numPendingImages--;
if (!content) {
this._setLoaded();
if (numPendingImages == 0)
this._updateAnimationProgress();
return;
}
this._ensureImage(i);
this._updateImage(i, content, files[i]);
if (numPendingImages == 0) {
this._setLoaded();
this._updateAnimationProgress();
}
}, i)
});
}
},
@ -549,25 +390,26 @@ const Background = new Lang.Class({
}
this._updateAnimation();
this._watchCacheFile(filename);
this._watchFile(filename);
})
});
},
_loadImage: function(filename) {
this._cache.getImageContent({ monitorIndex: this._monitorIndex,
effects: this._effects,
style: this._style,
filename: filename,
cancellable: this._cancellable,
onFinished: Lang.bind(this, function(content) {
if (content) {
this._ensureImage(0);
this._updateImage(0, content, filename);
}
this._setLoaded();
})
});
this.background.set_filename(filename, this._style);
this._watchFile(filename);
let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(filename);
if (image.is_loaded())
this._setLoaded();
else {
let id = image.connect('loaded',
Lang.bind(this, function() {
this._setLoaded();
image.disconnect(id);
}));
}
},
_loadFile: function(filename) {
@ -582,25 +424,58 @@ const Background = new Lang.Class({
this._loadPattern();
this._style = this._settings.get_enum(BACKGROUND_STYLE_KEY);
if (this._style == GDesktopEnums.BackgroundStyle.NONE) {
if (!this._filename) {
this._setLoaded();
return;
}
let uri = this._settings.get_string(PICTURE_URI_KEY);
let filename;
if (GLib.uri_parse_scheme(uri) != null)
filename = Gio.File.new_for_uri(uri).get_path();
else
filename = uri;
this._loadFile(this._filename);
},
});
Signals.addSignalMethods(Background.prototype);
if (!filename) {
const BackgroundActor = new Lang.Class({
Name: 'Background',
_init: function(params) {
params = Params.parse(params, { background: null,
monitorIndex: 0,
vignette: false });
this.actor = new Meta.BackgroundActor({ 'meta-screen': global.screen,
'monitor': params.monitorIndex,
'background': params.background.background });
this.actor._delegate = this;
this._vignette = params.vignette;
this._brightness = 1.0;
this._vignetteSharpness = 0.2;
if (this._vignette)
this.actor.add_vignette(this._vignetteSharpness, this._brightness);
if (params.background.isLoaded) {
this._setLoaded();
return;
} else {
let loadedSignalId = params.background.connect('loaded',
Lang.bind(this, function() {
params.background.disconnect(loadedSignalId);
this._setLoaded();
}));
}
},
this._loadFile(filename);
_setLoaded: function() {
if (this.isLoaded)
return;
this.isLoaded = true;
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
this.emit('loaded');
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(id, '[gnome-shell] this.emit');
},
get brightness() {
@ -609,15 +484,8 @@ const Background = new Lang.Class({
set brightness(factor) {
this._brightness = factor;
if (this._pattern && this._pattern.content)
this._pattern.content.brightness = factor;
let keys = Object.keys(this._images);
for (let i = 0; i < keys.length; i++) {
let image = this._images[keys[i]];
if (image && image.content)
image.content.brightness = factor;
}
if (this._vignette)
this.actor.add_vignette(this._brightness, this._vignetteSharpness);
},
get vignetteSharpness() {
@ -626,47 +494,115 @@ const Background = new Lang.Class({
set vignetteSharpness(sharpness) {
this._vignetteSharpness = sharpness;
if (this._pattern && this._pattern.content)
this._pattern.content.vignette_sharpness = sharpness;
let keys = Object.keys(this._images);
for (let i = 0; i < keys.length; i++) {
let image = this._images[keys[i]];
if (image && image.content)
image.content.vignette_sharpness = sharpness;
}
if (this._vignette)
this.actor.add_vignette(this._brightness, this._vignetteSharpness);
}
});
Signals.addSignalMethods(Background.prototype);
Signals.addSignalMethods(BackgroundActor.prototype);
let _systemBackground;
const SystemBackground = new Lang.Class({
Name: 'SystemBackground',
_init: function() {
this._cache = getBackgroundCache();
this.actor = new Meta.BackgroundActor();
let filename = global.datadir + '/theme/noise-texture.png';
this._cache.getImageContent({ style: GDesktopEnums.BackgroundStyle.WALLPAPER,
filename: global.datadir + '/theme/noise-texture.png',
effects: Meta.BackgroundEffects.NONE,
onFinished: Lang.bind(this, function(content) {
this.actor.content = content;
this.emit('loaded');
})
});
if (_systemBackground == null) {
_systemBackground = new Meta.Background({ 'meta-screen': global.screen });
_systemBackground.set_filename(filename, GDesktopEnums.BackgroundStyle.WALLPAPER);
}
this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
},
this.actor = new Meta.BackgroundActor({ 'meta-screen': global.screen,
'monitor': 0,
'background': _systemBackground });
_onDestroy: function() {
let content = this.actor.content;
if (content)
this._cache.removeImageContent(content);
let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(filename);
if (image.is_loaded()) {
image = null;
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, Lang.bind(this, function() {
this.emit('loaded');
return GLib.SOURCE_REMOVE;
}));
GLib.Source.set_name_by_id(id, '[gnome-shell] SystemBackground.loaded');
} else {
let id = image.connect('loaded',
Lang.bind(this, function() {
this.emit('loaded');
image.disconnect(id);
image = null;
}));
}
},
});
Signals.addSignalMethods(SystemBackground.prototype);
const BackgroundSource = new Lang.Class({
Name: 'BackgroundSource',
_init: function(layoutManager, settingsSchema) {
// Allow override the background image setting for performance testing
this._layoutManager = layoutManager;
this._overrideImage = GLib.getenv('SHELL_BACKGROUND_IMAGE');
this._settings = new Gio.Settings({ schema_id: settingsSchema });
this._backgrounds = [];
},
getBackground: function(monitorIndex) {
let filename = null;
let style;
if (this._overrideImage != null) {
filename = this._overrideImage;
style = GDesktopEnums.BackgroundStyle.ZOOM; // Hardcode
} else {
style = this._settings.get_enum(BACKGROUND_STYLE_KEY);
if (style != GDesktopEnums.BackgroundStyle.NONE) {
let uri = this._settings.get_string(PICTURE_URI_KEY);
if (GLib.uri_parse_scheme(uri) != null)
filename = Gio.File.new_for_uri(uri).get_path();
else
filename = uri;
}
}
// Animated backgrounds are (potentially) per-monitor, since
// they can have variants that depend on the aspect ratio and
// size of the monitor; for other backgrounds we can use the
// same background object for all monitors.
if (filename == null || !filename.endsWith('.xml'))
monitorIndex = 0;
if (!(monitorIndex in this._backgrounds)) {
let background = new Background({
monitorIndex: monitorIndex,
layoutManager: this._layoutManager,
settings: this._settings,
filename: filename,
style: style
});
let changedId = background.connect('changed', Lang.bind(this, function() {
background.disconnect(changedId);
background.destroy();
delete this._backgrounds[monitorIndex];
}));
this._backgrounds[monitorIndex] = background;
}
return this._backgrounds[monitorIndex];
},
destroy: function() {
for (let monitorIndex in this._backgrounds)
this._backgrounds[monitorIndex].destroy();
this._backgrounds = null;
}
});
const Animation = new Lang.Class({
Name: 'Animation',
@ -724,14 +660,17 @@ const BackgroundManager = new Lang.Class({
params = Params.parse(params, { container: null,
layoutManager: Main.layoutManager,
monitorIndex: null,
effects: Meta.BackgroundEffects.NONE,
vignette: false,
controlPosition: true,
settingsSchema: BACKGROUND_SCHEMA });
this._settings = new Gio.Settings({ schema_id: params.settingsSchema });
let cache = getBackgroundCache();
this._settingsSchema = params.settingsSchema;
this._backgroundSource = cache.getBackgroundSource(params.layoutManager, params.settingsSchema);
this._container = params.container;
this._layoutManager = params.layoutManager;
this._effects = params.effects;
this._vignette = params.vignette;
this._monitorIndex = params.monitorIndex;
this._controlPosition = params.controlPosition;
@ -740,6 +679,10 @@ const BackgroundManager = new Lang.Class({
},
destroy: function() {
let cache = getBackgroundCache();
cache.releaseBackgroundSource(this._settingsSchema);
this._backgroundSource = null;
if (this._newBackground) {
this._newBackground.actor.destroy();
this._newBackground = null;
@ -786,35 +729,35 @@ const BackgroundManager = new Lang.Class({
},
_createBackground: function() {
let background = new Background({ monitorIndex: this._monitorIndex,
layoutManager: this._layoutManager,
effects: this._effects,
settings: this._settings });
this._container.add_child(background.actor);
let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new BackgroundActor({ background: background,
monitorIndex: this._monitorIndex,
vignette: this._vignette });
this._container.add_child(backgroundActor.actor);
let monitor = this._layoutManager.monitors[this._monitorIndex];
background.actor.set_size(monitor.width, monitor.height);
backgroundActor.actor.set_size(monitor.width, monitor.height);
if (this._controlPosition) {
background.actor.set_position(monitor.x, monitor.y);
background.actor.lower_bottom();
backgroundActor.actor.set_position(monitor.x, monitor.y);
backgroundActor.actor.lower_bottom();
}
background.changeSignalId = background.connect('changed', Lang.bind(this, function() {
background.disconnect(background.changeSignalId);
background.changeSignalId = 0;
let changeSignalId = background.connect('changed', Lang.bind(this, function() {
background.disconnect(changeSignalId);
changeSignalId = null;
this._updateBackground();
}));
background.actor.connect('destroy', Lang.bind(this, function() {
if (background.changeSignalId)
background.disconnect(background.changeSignalId);
backgroundActor.actor.connect('destroy', Lang.bind(this, function() {
if (changeSignalId)
background.disconnect(changeSignalId);
if (background.loadedSignalId)
background.disconnect(background.loadedSignalId);
if (backgroundActor.loadedSignalId)
background.disconnect(loadedSignalId);
}));
return background;
return backgroundActor;
},
});
Signals.addSignalMethods(BackgroundManager.prototype);

View File

@ -33,8 +33,7 @@ function addBackgroundMenu(actor, layoutManager) {
actor._backgroundManager = new PopupMenu.PopupMenuManager({ actor: actor });
actor._backgroundManager.addMenu(actor._backgroundMenu);
function openMenu() {
let [x, y] = global.get_pointer();
function openMenu(x, y) {
Main.layoutManager.setDummyCursorGeometry(x, y, 0, 0);
actor._backgroundMenu.open(BoxPointer.PopupAnimation.NONE);
}
@ -42,22 +41,32 @@ function addBackgroundMenu(actor, layoutManager) {
let clickAction = new Clutter.ClickAction();
clickAction.connect('long-press', function(action, actor, state) {
if (state == Clutter.LongPressState.QUERY)
return action.get_button() == 1 && !actor._backgroundMenu.isOpen;
return ((action.get_button() == 0 ||
action.get_button() == 1) &&
!actor._backgroundMenu.isOpen);
if (state == Clutter.LongPressState.ACTIVATE) {
openMenu();
let [x, y] = action.get_coords();
openMenu(x, y);
actor._backgroundManager.ignoreRelease();
}
return true;
});
clickAction.connect('clicked', function(action) {
if (action.get_button() == 3)
openMenu();
if (action.get_button() == 3) {
let [x, y] = action.get_coords();
openMenu(x, y);
}
});
actor.add_action(clickAction);
let grabOpBeginId = global.display.connect('grab-op-begin', function () {
clickAction.release();
});
actor.connect('destroy', function() {
actor._backgroundMenu.destroy();
actor._backgroundMenu = null;
actor._backgroundManager = null;
global.display.disconnect(grabOpBeginId);
});
}

View File

@ -409,7 +409,7 @@ const Calendar = new Lang.Class({
this._shouldDateGrabFocus = false;
this.actor = new St.Widget({ style_class: 'calendar',
layout_manager: new Clutter.TableLayout(),
layout_manager: new Clutter.GridLayout(),
reactive: true });
this.actor.connect('scroll-event',
@ -447,8 +447,7 @@ const Calendar = new Lang.Class({
// Top line of the calendar '<| September 2009 |>'
this._topBox = new St.BoxLayout();
layout.pack(this._topBox, 0, 0);
layout.set_span(this._topBox, offsetCols + 7, 1);
layout.attach(this._topBox, 0, 0, offsetCols + 7, 1);
this._backButton = new St.Button({ style_class: 'calendar-change-month-back',
accessible_name: _("Previous month"),
@ -485,7 +484,7 @@ const Calendar = new Lang.Class({
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.pack(label, col, 1);
layout.attach(label, col, 1, 1, 1);
iter.setTime(iter.getTime() + MSECS_IN_DAY);
}
@ -657,14 +656,14 @@ const Calendar = new Lang.Class({
col = 6 - (7 + iter.getDay() - this._weekStart) % 7;
else
col = offsetCols + (7 + iter.getDay() - this._weekStart) % 7;
layout.pack(button, col, row);
layout.attach(button, col, row, 1, 1);
this._buttons.push(button);
if (this._useWeekdate && iter.getDay() == 4) {
let label = new St.Label({ text: _getCalendarWeekForDate(iter).toString(),
style_class: 'calendar-day-base calendar-week-number'});
layout.pack(label, rtl ? 7 : 0, row);
layout.attach(label, rtl ? 7 : 0, row, 1, 1);
}
iter.setTime(iter.getTime() + MSECS_IN_DAY);
@ -707,7 +706,7 @@ const EventsList = new Lang.Class({
Name: 'EventsList',
_init: function() {
let layout = new Clutter.TableLayout();
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
this.actor = new St.Widget({ style_class: 'events-table',
layout_manager: layout });
layout.hookup_style(this.actor);
@ -730,36 +729,34 @@ const EventsList = new Lang.Class({
dayString = '';
let dayLabel = new St.Label({ style_class: 'events-day-dayname',
text: dayString });
text: dayString,
x_align: Clutter.ActorAlign.END,
y_align: Clutter.ActorAlign.START });
dayLabel.clutter_text.line_wrap = false;
dayLabel.clutter_text.ellipsize = false;
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
let layout = this.actor.layout_manager;
layout.pack(dayLabel, rtl ? 2 : 0, index);
layout.child_set(dayLabel, { x_expand: false,
x_align: Clutter.TableAlignment.END,
y_align: Clutter.TableAlignment.START });
layout.attach(dayLabel, rtl ? 2 : 0, index, 1, 1);
let clockFormat = this._desktopSettings.get_string(CLOCK_FORMAT_KEY);
let timeString = _formatEventTime(event, clockFormat);
let timeLabel = new St.Label({ style_class: 'events-day-time',
text: timeString });
text: timeString,
y_align: Clutter.ActorAlign.START });
timeLabel.clutter_text.line_wrap = false;
timeLabel.clutter_text.ellipsize = false;
layout.pack(timeLabel, 1, index);
layout.child_set(timeLabel, { x_expand: false,
y_align: Clutter.TableAlignment.START });
layout.attach(timeLabel, 1, index, 1, 1);
let titleLabel = new St.Label({ style_class: 'events-day-task',
text: event.summary });
text: event.summary,
x_expand: true });
titleLabel.clutter_text.line_wrap = true;
titleLabel.clutter_text.ellipsize = false;
layout.pack(titleLabel, rtl ? 0 : 2, index);
layout.child_set(titleLabel, { x_expand: true });
layout.attach(titleLabel, rtl ? 0 : 2, index, 1, 1);
},
_addPeriod: function(header, index, begin, end, includeDayName, showNothingScheduled) {
@ -770,8 +767,7 @@ const EventsList = new Lang.Class({
let label = new St.Label({ style_class: 'events-day-header', text: header });
let layout = this.actor.layout_manager;
layout.pack(label, 0, index);
layout.child_set(label, { column_span: 3, x_expand: false });
layout.attach(label, 0, index, 3, 1);
index++;
for (let n = 0; n < events.length; n++) {

View File

@ -80,44 +80,46 @@ const KeyringDialog = new Lang.Class({
},
_buildControlTable: function() {
let layout = new Clutter.TableLayout();
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
let table = new St.Widget({ style_class: 'keyring-dialog-control-table',
layout_manager: layout });
layout.hookup_style(table);
let row = 0;
if (this.prompt.password_visible) {
let label = new St.Label({ style_class: 'prompt-dialog-password-label' });
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.set_text(_("Password:"));
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
layout.attach(label, 0, row, 1, 1);
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true });
can_focus: true,
x_expand: true });
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', Lang.bind(this, this._onPasswordActivate));
layout.pack(this._passwordEntry, 1, row);
layout.attach(this._passwordEntry, 1, row, 1, 1);
row++;
} else {
this._passwordEntry = null;
}
if (this.prompt.confirm_visible) {
var label = new St.Label(({ style_class: 'prompt-dialog-password-label' }));
var label = new St.Label(({ style_class: 'prompt-dialog-password-label',
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER }));
label.set_text(_("Type again:"));
layout.pack(label, 0, row);
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
layout.attach(label, 0, row, 1, 1);
this._confirmEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: '',
can_focus: true });
can_focus: true,
x_expand: true });
this._confirmEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._confirmEntry, { isPassword: true });
this._confirmEntry.clutter_text.connect('activate', Lang.bind(this, this._onConfirmActivate));
layout.pack(this._confirmEntry, 1, row);
layout.attach(this._confirmEntry, 1, row, 1, 1);
row++;
} else {
this._confirmEntry = null;
@ -130,15 +132,15 @@ const KeyringDialog = new Lang.Class({
let choice = new CheckBox.CheckBox();
this.prompt.bind_property('choice-label', choice.getLabelActor(), 'text', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('choice-chosen', choice.actor, 'checked', GObject.BindingFlags.SYNC_CREATE | GObject.BindingFlags.BIDIRECTIONAL);
layout.pack(choice.actor, 1, row);
layout.attach(choice.actor, 1, row, 1, 1);
row++;
}
let warning = new St.Label({ style_class: 'prompt-dialog-error-label' });
let warning = new St.Label({ style_class: 'prompt-dialog-error-label',
x_align: Clutter.ActorAlign.START });
warning.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
warning.clutter_text.line_wrap = true;
layout.pack(warning, 1, row);
layout.child_set(warning, { x_fill: false, x_align: Clutter.TableAlignment.START });
layout.attach(warning, 1, row, 1, 1);
this.prompt.bind_property('warning-visible', warning, 'visible', GObject.BindingFlags.SYNC_CREATE);
this.prompt.bind_property('warning', warning, 'text', GObject.BindingFlags.SYNC_CREATE);

View File

@ -72,7 +72,7 @@ const NetworkSecretDialog = new Lang.Class({
expand: true });
}
let layout = new Clutter.TableLayout();
let layout = new Clutter.GridLayout({ orientation: Clutter.Orientation.VERTICAL });
let secretTable = new St.Widget({ style_class: 'network-dialog-secret-table',
layout_manager: layout });
layout.hookup_style(secretTable);
@ -83,14 +83,17 @@ const NetworkSecretDialog = new Lang.Class({
for (let i = 0; i < this._content.secrets.length; i++) {
let secret = this._content.secrets[i];
let label = new St.Label({ style_class: 'prompt-dialog-password-label',
text: secret.label });
text: secret.label,
x_align: Clutter.ActorAlign.START,
y_align: Clutter.ActorAlign.CENTER });
label.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
let reactive = secret.key != null;
secret.entry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: secret.value, can_focus: reactive,
reactive: reactive });
reactive: reactive,
x_expand: true });
ShellEntry.addContextMenu(secret.entry,
{ isPassword: secret.password });
@ -118,14 +121,12 @@ const NetworkSecretDialog = new Lang.Class({
secret.valid = true;
if (rtl) {
layout.pack(secret.entry, 0, pos);
layout.pack(label, 1, pos);
layout.attach(secret.entry, 0, pos, 1, 1);
layout.attach(label, 1, pos, 1, 1);
} else {
layout.pack(label, 0, pos);
layout.pack(secret.entry, 1, pos);
layout.attach(label, 0, pos, 1, 1);
layout.attach(secret.entry, 1, pos, 1, 1);
}
layout.child_set(label, { x_expand: false, y_fill: false,
x_align: Clutter.TableAlignment.START });
pos++;
if (secret.password)

View File

@ -863,13 +863,6 @@ const ChatNotification = new Lang.Class({
for (let i = 0; i < expired.length; i++)
expired[i].actor.destroy();
}
let groups = this._contentArea.get_children();
for (let i = 0; i < groups.length; i++) {
let group = groups[i];
if (group.get_n_children() == 0)
group.destroy();
}
},
/**
@ -911,16 +904,19 @@ const ChatNotification = new Lang.Class({
this._lastGroup = group;
let emptyLine = new St.Label({ style_class: 'chat-empty-line' });
this.addActor(emptyLine);
this._history.unshift({ actor: emptyLine, time: timestamp,
realMessage: false });
}
this._lastMessageBox = new St.BoxLayout({ vertical: false });
this._lastMessageBox.add(body, props.childProps);
this.addActor(this._lastMessageBox);
let lineBox = new St.BoxLayout({ vertical: false });
lineBox.add(body, props.childProps);
this.addActor(lineBox);
this._lastMessageBox = lineBox;
this.updated();
let timestamp = props.timestamp;
this._history.unshift({ actor: body, time: timestamp,
this._history.unshift({ actor: lineBox, time: timestamp,
realMessage: group != 'meta' });
if (!props.noTimestamp) {

View File

@ -156,11 +156,11 @@ const CtrlAltTabPopup = new Lang.Class({
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_PANELS)
this._select(backwards ? this._previous() : this._next());
this._select(this._next());
else if (action == Meta.KeyBindingAction.SWITCH_PANELS_BACKWARD)
this._select(backwards ? this._next() : this._previous());
this._select(this._previous());
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)

View File

@ -211,10 +211,13 @@ const DateMenuButton = new Lang.Class({
return this._calendarApp;
let apps = Gio.AppInfo.get_recommended_for_type('text/calendar');
if (apps && (apps.length > 0))
this._calendarApp = apps[0];
else
if (apps && (apps.length > 0)) {
let app = Gio.AppInfo.get_default_for_type('text/calendar', false);
let defaultInRecommended = apps.some(function(a) { return a.equal(app); });
this._calendarApp = defaultInRecommended ? app : apps[0];
} else {
this._calendarApp = null;
}
return this._calendarApp;
},

View File

@ -283,12 +283,22 @@ const GrabHelper = new Lang.Class({
return Clutter.EVENT_STOP;
}
let motion = type == Clutter.EventType.MOTION;
let press = type == Clutter.EventType.BUTTON_PRESS;
let release = type == Clutter.EventType.BUTTON_RELEASE;
let button = press || release;
if (release && this._ignoreRelease) {
this._ignoreRelease = false;
let touchUpdate = type == Clutter.EventType.TOUCH_UPDATE;
let touchBegin = type == Clutter.EventType.TOUCH_BEGIN;
let touchEnd = type == Clutter.EventType.TOUCH_END;
let touch = touchUpdate || touchBegin || touchEnd;
if (touch && !global.display.is_pointer_emulating_sequence (event.get_event_sequence()))
return Clutter.EVENT_PROPAGATE;
if (this._ignoreUntilRelease && (motion || release || touch)) {
if (release || touchEnd)
this._ignoreUntilRelease = false;
return Clutter.EVENT_STOP;
}
@ -298,11 +308,12 @@ const GrabHelper = new Lang.Class({
if (Main.keyboard.shouldTakeEvent(event))
return Clutter.EVENT_PROPAGATE;
if (button) {
// If we have a press event, ignore the next event,
// which should be a release event.
if (press)
this._ignoreRelease = true;
if (button || touchBegin) {
// If we have a press event, ignore the next
// motion/release events.
if (press || touchBegin)
this._ignoreUntilRelease = true;
let i = this._actorInGrabStack(event.get_source()) + 1;
this.ungrab({ actor: this._grabStack[i].actor, isUser: true });
return Clutter.EVENT_STOP;

View File

@ -11,6 +11,9 @@ const Main = imports.ui.main;
const MAX_CANDIDATES_PER_PAGE = 16;
const DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ];
const CandidateArea = new Lang.Class({
Name: 'CandidateArea',
@ -89,7 +92,7 @@ const CandidateArea = new Lang.Class({
if (!visible)
continue;
box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : '%x'.format(i + 1));
box._indexLabel.text = ((indexes && indexes[i]) ? indexes[i] : DEFAULT_INDEX_LABELS[i]);
box._candidateLabel.text = candidates[i];
}

View File

@ -524,12 +524,13 @@ const IconGrid = new Lang.Class({
this._updateSpacingForSize(availWidth, availHeight);
}
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() { this._updateChildrenScale(scale); }));
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
Lang.bind(this, this._updateIconSizes));
},
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateChildrenScale: function(scale) {
_updateIconSizes: function() {
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale);
for (let i in this._items) {
this._items[i].icon.setIconSize(newIconSize);

View File

@ -52,8 +52,7 @@ const Key = new Lang.Class({
_init : function(key) {
this._key = key;
this.actor = this._makeKey();
this.actor = this._makeKey(key, GLib.markup_escape_text(key.label, -1));
this._extended_keys = this._key.get_extended_keys();
this._extended_keyboard = null;
@ -76,20 +75,38 @@ const Key = new Lang.Class({
}
},
_makeKey: function () {
let label = GLib.markup_escape_text(this._key.label, -1);
_makeKey: function (key, label) {
let button = new St.Button ({ label: label,
style_class: 'keyboard-key' });
button.key_width = this._key.width;
button.connect('button-press-event', Lang.bind(this,
function () {
this._key.press();
key.press();
return Clutter.EVENT_PROPAGATE;
}));
button.connect('button-release-event', Lang.bind(this,
function () {
this._key.release();
key.release();
return Clutter.EVENT_PROPAGATE;
}));
button.connect('touch-event', Lang.bind(this,
function (actor, event) {
let device = event.get_device();
let sequence = event.get_event_sequence();
if (!this._touchPressed &&
event.type() == Clutter.EventType.TOUCH_BEGIN) {
device.sequence_grab(sequence, actor);
this._touchPressed = true;
key.press();
} else if (this._touchPressed &&
event.type() == Clutter.EventType.TOUCH_END &&
device.sequence_get_grabbed_actor(sequence) == actor) {
device.sequence_ungrab(sequence);
this._touchPressed = false;
key.release();
}
return Clutter.EVENT_PROPAGATE;
}));
@ -112,18 +129,9 @@ const Key = new Lang.Class({
for (let i = 0; i < this._extended_keys.length; ++i) {
let extended_key = this._extended_keys[i];
let label = this._getUnichar(extended_key);
let key = new St.Button({ label: label, style_class: 'keyboard-key' });
let key = this._makeKey(extended_key, label);
key.extended_key = extended_key;
key.connect('button-press-event', Lang.bind(this,
function () {
extended_key.press();
return Clutter.EVENT_PROPAGATE;
}));
key.connect('button-release-event', Lang.bind(this,
function () {
extended_key.release();
return Clutter.EVENT_PROPAGATE;
}));
this._extended_keyboard.add(key);
}
this._boxPointer.bin.add_actor(this._extended_keyboard);

View File

@ -408,6 +408,12 @@ const LayoutManager = new Lang.Class({
}
},
_updateKeyboardBox: function() {
this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
},
_updateBoxes: function() {
this.screenShieldGroup.set_position(0, 0);
this.screenShieldGroup.set_size(global.screen_width, global.screen_height);
@ -417,6 +423,8 @@ const LayoutManager = new Lang.Class({
if (this.keyboardIndex < 0)
this.keyboardIndex = this.primaryIndex;
else
this._updateKeyboardBox();
this.trayBox.set_position(this.bottomMonitor.x,
this.bottomMonitor.y + this.bottomMonitor.height);
@ -541,9 +549,7 @@ const LayoutManager = new Lang.Class({
set keyboardIndex(v) {
this._keyboardIndex = v;
this.keyboardBox.set_position(this.keyboardMonitor.x,
this.keyboardMonitor.y + this.keyboardMonitor.height);
this.keyboardBox.set_size(this.keyboardMonitor.width, -1);
this._updateKeyboardBox();
},
get keyboardIndex() {
@ -597,7 +603,9 @@ const LayoutManager = new Lang.Class({
reactive: true });
this.addChrome(this._coverPane);
if (Main.sessionMode.isGreeter) {
if (Meta.is_restart()) {
// On restart, we don't do an animation
} else if (Main.sessionMode.isGreeter) {
this.panelBox.translation_y = -this.panelBox.height;
} else {
this._updateBackgrounds();
@ -636,7 +644,9 @@ const LayoutManager = new Lang.Class({
},
_startupAnimation: function() {
if (Main.sessionMode.isGreeter)
if (Meta.is_restart())
this._startupAnimationComplete();
else if (Main.sessionMode.isGreeter)
this._startupAnimationGreeter();
else
this._startupAnimationSession();

View File

@ -105,8 +105,8 @@ const Lightbox = new Lang.Class({
this._container = container;
this._children = container.get_children();
this._fadeFactor = params.fadeFactor;
this._radialEffect = params.radialEffect;
if (params.radialEffect)
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
if (this._radialEffect)
this.actor = new RadialShaderQuad({ x: 0,
y: 0,
reactive: params.inhibitEvents });

View File

@ -18,6 +18,7 @@ const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const OsdWindow = imports.ui.osdWindow;
const Overview = imports.ui.overview;
const Panel = imports.ui.panel;
@ -167,6 +168,16 @@ function _initializeUI() {
overview.toggle();
}));
global.display.connect('show-restart-message', function(display, message) {
showRestartMessage(message);
return true;
});
global.display.connect('restart', function() {
global.reexec_self();
return true;
});
// Provide the bus object for gnome-session to
// initiate logouts.
EndSessionDialog.init();
@ -233,8 +244,7 @@ function _loadDefaultStylesheet() {
* Returns: A file path that contains the theme CSS,
* null if using the default
*/
function getThemeStylesheet()
{
function getThemeStylesheet() {
return _cssStylesheet;
}
@ -245,8 +255,7 @@ function getThemeStylesheet()
*
* Set the theme CSS file that the shell will load
*/
function setThemeStylesheet(cssStylesheet)
{
function setThemeStylesheet(cssStylesheet) {
_cssStylesheet = cssStylesheet;
}
@ -608,3 +617,28 @@ function queueDeferredWork(workId) {
GLib.Source.set_name_by_id(_deferredTimeoutId, '[gnome-shell] _runAllDeferredWork');
}
}
const RestartMessage = new Lang.Class({
Name: 'RestartMessage',
Extends: ModalDialog.ModalDialog,
_init : function(message) {
this.parent({ shellReactive: true,
styleClass: 'restart-message',
shouldFadeIn: false,
destroyOnClose: true });
let label = new St.Label({ text: message });
this.contentLayout.add(label, { x_fill: false,
y_fill: false,
x_align: St.Align.MIDDLE,
y_align: St.Align.MIDDLE });
this.buttonLayout.hide();
}
});
function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);
restartMessage.open();
}

View File

@ -922,7 +922,7 @@ const Notification = new Lang.Class({
let [titleMinH, titleNatH] = this._titleLabel.get_preferred_height(availWidth);
let [bannerMinW, bannerNatW] = this._bannerLabel.get_preferred_width(availWidth);
let rtl = (this._titleDirection == Clutter.TextDirection.RTL);
let rtl = (this._table.text_direction == Clutter.TextDirection.RTL);
let x = rtl ? availWidth : 0;
if (this._secondaryIcon) {

View File

@ -43,6 +43,7 @@ const ModalDialog = new Lang.Class({
styleClass: null,
keybindingMode: Shell.KeyBindingMode.SYSTEM_MODAL,
shouldFadeIn: true,
shouldFadeOut: true,
destroyOnClose: true });
this.state = State.CLOSED;
@ -50,6 +51,7 @@ const ModalDialog = new Lang.Class({
this._keybindingMode = params.keybindingMode;
this._shellReactive = params.shellReactive;
this._shouldFadeIn = params.shouldFadeIn;
this._shouldFadeOut = params.shouldFadeOut;
this._destroyOnClose = params.destroyOnClose;
this._group = new St.Widget({ visible: false,
@ -307,6 +309,15 @@ const ModalDialog = new Lang.Class({
return true;
},
_closeComplete: function() {
this.state = State.CLOSED;
this._group.hide();
this.emit('closed');
if (this._destroyOnClose)
this.destroy();
},
close: function(timestamp) {
if (this.state == State.CLOSED || this.state == State.CLOSING)
return;
@ -315,20 +326,16 @@ const ModalDialog = new Lang.Class({
this.popModal(timestamp);
this._savedKeyFocus = null;
Tweener.addTween(this._group,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
function() {
this.state = State.CLOSED;
this._group.hide();
this.emit('closed');
if (this._destroyOnClose)
this.destroy();
})
});
if (this._shouldFadeOut)
Tweener.addTween(this._group,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: Lang.bind(this,
this._closeComplete)
})
else
this._closeComplete();
},
// Drop modal status without closing the dialog; this makes the

View File

@ -120,15 +120,12 @@ const FdoNotificationDaemon = new Lang.Class({
this._nextNotificationId = 1;
Shell.WindowTracker.get_default().connect('notify::focus-app', Lang.bind(this, this._onFocusAppChanged));
Main.overview.connect('hidden', Lang.bind(this, this._onFocusAppChanged));
this._trayManager = new Shell.TrayManager();
this._trayIconAddedId = this._trayManager.connect('tray-icon-added', Lang.bind(this, this._onTrayIconAdded));
this._trayIconRemovedId = this._trayManager.connect('tray-icon-removed', Lang.bind(this, this._onTrayIconRemoved));
Shell.WindowTracker.get_default().connect('notify::focus-app',
Lang.bind(this, this._onFocusAppChanged));
Main.overview.connect('hidden',
Lang.bind(this, this._onFocusAppChanged));
this._trayManager.manage_screen(global.screen, Main.messageTray.actor);
},
@ -692,6 +689,12 @@ const FdoNotificationDaemonSource = new Lang.Class({
}
});
const PRIORITY_URGENCY_MAP = {
low: MessageTray.Urgency.LOW,
normal: MessageTray.Urgency.NORMAL,
high: MessageTray.Urgency.HIGH,
urgent: MessageTray.Urgency.CRITICAL
};
const GtkNotificationDaemonNotification = new Lang.Class({
Name: 'GtkNotificationDaemonNotification',
@ -705,12 +708,20 @@ const GtkNotificationDaemonNotification = new Lang.Class({
"body": body,
"icon": gicon,
"urgent": urgent,
"priority": priority,
"buttons": buttons,
"default-action": defaultAction,
"default-action-target": defaultActionTarget } = notification;
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
if (priority) {
let urgency = PRIORITY_URGENCY_MAP[priority.unpack()];
this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL);
} else if (urgent) {
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
} else {
this.setUrgency(MessageTray.Urgency.NORMAL);
}
if (buttons) {
buttons.deep_unpack().forEach(Lang.bind(this, function(button) {

View File

@ -185,7 +185,7 @@ const Overview = new Lang.Class({
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
let bgManager = new Background.BackgroundManager({ container: this._backgroundGroup,
monitorIndex: i,
effects: Meta.BackgroundEffects.VIGNETTE });
vignette: true });
this._bgManagers.push(bgManager);
}
},
@ -242,7 +242,7 @@ const Overview = new Lang.Class({
opacity: 0 });
this._overview.add_actor(this._panelGhost);
this._searchEntry = new St.Entry({ name: 'searchEntry',
this._searchEntry = new St.Entry({ style_class: 'search-entry',
/* Translators: this is the text displayed
in the search entry when no search is
active; it should not exceed ~30
@ -425,8 +425,6 @@ const Overview = new Lang.Class({
this.emit('windows-restacked', stackIndices);
},
//// Public methods ////
beginItemDrag: function(source) {
this.emit('item-drag-begin');
this._inDrag = true;
@ -455,23 +453,6 @@ const Overview = new Lang.Class({
this._inDrag = false;
},
// show:
//
// Animates the overview visible and grabs mouse and keyboard input
show: function() {
if (this.isDummy)
return;
if (this._shown)
return;
this._shown = true;
if (!this._syncGrab())
return;
Main.layoutManager.showOverview();
this._animateVisible();
},
focusSearch: function() {
this.show();
this._searchEntry.grab_key_focus();
@ -504,69 +485,6 @@ const Overview = new Lang.Class({
});
},
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
this._activationTime = Date.now() / 1000;
Meta.disable_unredirect_for_screen(global.screen);
this.viewSelector.show();
this._stack.opacity = 0;
Tweener.addTween(this._stack,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._showDone,
onCompleteScope: this
});
this._shadeBackgrounds();
this._coverPane.raise_top();
this._coverPane.show();
this.emit('showing');
},
// hide:
//
// Reverses the effect of show()
hide: function() {
if (this.isDummy)
return;
if (!this._shown)
return;
let event = Clutter.get_current_event();
if (event) {
let type = event.type();
let button = (type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE);
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0;
if (button && ctrl)
return;
}
this._animateNotVisible();
this._shown = false;
this._syncGrab();
},
toggle: function() {
if (this.isDummy)
return;
if (this.visible)
this.hide();
else
this.show();
},
// Checks if the Activities button is currently sensitive to
// clicks. The first call to this function within the
// OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being
@ -583,8 +501,6 @@ const Overview = new Lang.Class({
return false;
},
//// Private methods ////
_syncGrab: function() {
// We delay grab changes during animation so that when removing the
// overview we don't have a problem with the release of a press/release
@ -614,28 +530,49 @@ const Overview = new Lang.Class({
return true;
},
_animateNotVisible: function() {
if (!this.visible || this.animationInProgress)
// show:
//
// Animates the overview visible and grabs mouse and keyboard input
show: function() {
if (this.isDummy)
return;
if (this._shown)
return;
this._shown = true;
if (!this._syncGrab())
return;
Main.layoutManager.showOverview();
this._animateVisible();
},
_animateVisible: function() {
if (this.visible || this.animationInProgress)
return;
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = false;
this.visibleTarget = true;
this._activationTime = Date.now() / 1000;
this.viewSelector.zoomFromOverview();
Meta.disable_unredirect_for_screen(global.screen);
this.viewSelector.show();
// Make other elements fade out.
this._stack.opacity = 0;
Tweener.addTween(this._stack,
{ opacity: 0,
{ opacity: 255,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onComplete: this._showDone,
onCompleteScope: this
});
this._unshadeBackgrounds();
this._shadeBackgrounds();
this._coverPane.raise_top();
this._coverPane.show();
this.emit('hiding');
this.emit('showing');
},
_showDone: function() {
@ -652,6 +589,57 @@ const Overview = new Lang.Class({
global.sync_pointer();
},
// hide:
//
// Reverses the effect of show()
hide: function() {
if (this.isDummy)
return;
if (!this._shown)
return;
let event = Clutter.get_current_event();
if (event) {
let type = event.type();
let button = (type == Clutter.EventType.BUTTON_PRESS ||
type == Clutter.EventType.BUTTON_RELEASE);
let ctrl = (event.get_state() & Clutter.ModifierType.CONTROL_MASK) != 0;
if (button && ctrl)
return;
}
this._animateNotVisible();
this._shown = false;
this._syncGrab();
},
_animateNotVisible: function() {
if (!this.visible || this.animationInProgress)
return;
this.animationInProgress = true;
this.visibleTarget = false;
this.viewSelector.animateFromOverview();
// Make other elements fade out.
Tweener.addTween(this._stack,
{ opacity: 0,
transition: 'easeOutQuad',
time: ANIMATION_TIME,
onComplete: this._hideDone,
onCompleteScope: this
});
this._unshadeBackgrounds();
this._coverPane.raise_top();
this._coverPane.show();
this.emit('hiding');
},
_hideDone: function() {
// Re-enable unredirection
Meta.enable_unredirect_for_screen(global.screen);
@ -677,6 +665,16 @@ const Overview = new Lang.Class({
this._fakePointerEvent();
this._needsFakePointerEvent = false;
}
},
toggle: function() {
if (this.isDummy)
return;
if (this.visible)
this.hide();
else
this.show();
}
});
Signals.addSignalMethods(Overview.prototype);

View File

@ -118,7 +118,6 @@ const SlidingControl = new Lang.Class({
style_class: 'overview-controls',
clip_to_allocation: true });
Main.overview.connect('showing', Lang.bind(this, this._onOverviewShowing));
Main.overview.connect('hiding', Lang.bind(this, this._onOverviewHiding));
Main.overview.connect('item-drag-begin', Lang.bind(this, this._onDragBegin));
@ -177,14 +176,9 @@ const SlidingControl = new Lang.Class({
transition: 'easeOutQuad' });
},
_onOverviewShowing: function() {
this._visible = true;
this.layout.slideX = this._getSlide();
this.layout.translationX = this._getTranslation();
this.slideIn();
},
_onOverviewHiding: function() {
// We need to explicitily slideOut since showing pages
// doesn't implies to slide out, instead, hiding the overview does.
this.slideOut();
},

View File

@ -14,7 +14,6 @@ const St = imports.gi.St;
const Signals = imports.signals;
const Atk = imports.gi.Atk;
const Animation = imports.ui.animation;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab;
@ -572,7 +571,6 @@ const ActivitiesButton = new Lang.Class({
this.actor.label_actor = this._label;
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
Main.overview.connect('showing', Lang.bind(this, function() {
@ -601,16 +599,21 @@ const ActivitiesButton = new Lang.Class({
},
_onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
if (event.type() == Clutter.EventType.BUTTON_PRESS ||
event.type() == Clutter.EventType.TOUCH_BEGIN) {
if (!Main.overview.shouldToggleByCornerOrButton())
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
},
_onButtonRelease: function() {
Main.overview.toggle();
this.menu.close();
_onEvent: function(actor, event) {
this.parent(actor, event);
if (event.type() == Clutter.EventType.TOUCH_END ||
event.type() == Clutter.EventType.BUTTON_RELEASE)
Main.overview.toggle();
return Clutter.EVENT_PROPAGATE;
},

View File

@ -100,7 +100,7 @@ const Button = new Lang.Class({
accessible_name: nameText ? nameText : "",
accessible_role: Atk.Role.MENU });
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('event', Lang.bind(this, this._onEvent));
this.actor.connect('key-press-event', Lang.bind(this, this._onSourceKeyPress));
this.actor.connect('notify::visible', Lang.bind(this, this._onVisibilityChanged));
@ -131,11 +131,12 @@ const Button = new Lang.Class({
}
},
_onButtonPress: function(actor, event) {
if (!this.menu)
return Clutter.EVENT_PROPAGATE;
_onEvent: function(actor, event) {
if (this.menu &&
(event.type() == Clutter.EventType.TOUCH_BEGIN ||
event.type() == Clutter.EventType.BUTTON_PRESS))
this.menu.toggle();
this.menu.toggle();
return Clutter.EVENT_PROPAGATE;
},

View File

@ -1,9 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
@ -15,7 +13,6 @@ const GrabHelper = imports.ui.grabHelper;
const Main = imports.ui.main;
const Params = imports.misc.params;
const Separator = imports.ui.separator;
const Slider = imports.ui.slider;
const Tweener = imports.ui.tweener;
const Ornament = {
@ -24,17 +21,6 @@ const Ornament = {
CHECK: 2,
};
function _ensureStyle(actor) {
if (actor.get_children) {
let children = actor.get_children();
for (let i = 0; i < children.length; i++)
_ensureStyle(children[i]);
}
if (actor instanceof St.Widget)
actor.ensure_style();
}
function isPopupMenuItemVisible(child) {
if (child._delegate instanceof PopupMenuSection)
if (child._delegate.isEmpty())
@ -106,6 +92,7 @@ const PopupBaseMenuItem = new Lang.Class({
if (this._activatable) {
this.actor.connect('button-release-event', Lang.bind(this, this._onButtonReleaseEvent));
this.actor.connect('touch-event', Lang.bind(this, this._onTouchEvent));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPressEvent));
}
if (params.reactive && params.hover)
@ -132,6 +119,14 @@ const PopupBaseMenuItem = new Lang.Class({
return Clutter.EVENT_STOP;
},
_onTouchEvent: function (actor, event) {
if (event.type() == Clutter.EventType.TOUCH_END) {
this.activate(event);
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
},
_onKeyPressEvent: function (actor, event) {
let symbol = event.get_key_symbol();
@ -378,9 +373,9 @@ const PopupImageMenuItem = new Lang.Class({
this.parent(params);
this.label = new St.Label({ text: text });
this.addActor(this.label);
this.actor.add_child(this.label);
this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
this.addActor(this._icon, { align: St.Align.END });
this.actor.add_child(this._icon, { align: St.Align.END });
this.setIcon(iconName);
},

View File

@ -110,6 +110,13 @@ function loadRemoteSearchProviders(callback) {
else
remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath);
remoteProvider.defaultEnabled = true;
try {
remoteProvider.defaultEnabled = !keyfile.get_boolean(group, 'DefaultDisabled');
} catch(e) {
// ignore error
}
objectPaths[objectPath] = remoteProvider;
loadedProviders.push(remoteProvider);
} catch(e) {
@ -132,8 +139,14 @@ function loadRemoteSearchProviders(callback) {
loadedProviders = loadedProviders.filter(function(provider) {
let appId = provider.appInfo.get_id();
let disabled = searchSettings.get_strv('disabled');
return disabled.indexOf(appId) == -1;
if (provider.defaultEnabled) {
let disabled = searchSettings.get_strv('disabled');
return disabled.indexOf(appId) == -1;
} else {
let enabled = searchSettings.get_strv('enabled');
return enabled.indexOf(appId) != -1;
}
});
loadedProviders.sort(function(providerA, providerB) {

View File

@ -50,14 +50,10 @@ const RunDialog = new Lang.Class({
Main.createLookingGlass().open();
}),
'r': Lang.bind(this, function() {
global.reexec_self();
}),
'r': Lang.bind(this, this._restart),
// Developer brain backwards compatibility
'restart': Lang.bind(this, function() {
global.reexec_self();
}),
'restart': Lang.bind(this, this._restart),
'debugexit': Lang.bind(this, function() {
Meta.quit(Meta.ExitCode.ERROR);
@ -186,6 +182,10 @@ const RunDialog = new Lang.Class({
let results = someResults.reduce(function(a, b) {
return a.concat(b);
}, []);
if (!results.length)
return null;
let common = results.reduce(_getCommon, null);
return common.substr(text.length);
},
@ -271,6 +271,12 @@ const RunDialog = new Lang.Class({
}
},
_restart: function() {
this._shouldFadeOut = false;
this.close();
Meta.restart(_("Restarting…"));
},
open: function() {
this._history.lastItem();
this._errorBox.hide();

View File

@ -444,14 +444,12 @@ function clamp(value, min, max) {
}
/**
* To test screen shield, make sure to kill gnome-screensaver.
*
* If you are setting org.gnome.desktop.session.idle-delay directly in dconf,
* rather than through System Settings, you also need to set
* org.gnome.settings-daemon.plugins.power.sleep-display-ac and
* org.gnome.settings-daemon.plugins.power.sleep-display-battery to the same value.
* This will ensure that the screen blanks at the right time when it fades out.
* https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependance.
* https://bugzilla.gnome.org/show_bug.cgi?id=668703 explains the dependency.
*/
const ScreenShield = new Lang.Class({
Name: 'ScreenShield',
@ -902,17 +900,11 @@ const ScreenShield = new Lang.Class({
},
showDialog: function() {
// Ensure that the stage window is mapped, before taking a grab
// otherwise X errors out
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, Lang.bind(this, function() {
if (!this._becomeModal()) {
// In the login screen, this is a hard error. Fail-whale
log('Could not acquire modal grab for the login screen. Aborting login process.');
Meta.quit(Meta.ExitCode.ERROR);
}
return false;
}));
if (!this._becomeModal()) {
// In the login screen, this is a hard error. Fail-whale
log('Could not acquire modal grab for the login screen. Aborting login process.');
Meta.quit(Meta.ExitCode.ERROR);
}
this.actor.show();
this._isGreeter = Main.sessionMode.isGreeter;

View File

@ -7,6 +7,7 @@ const Meta = imports.gi.Meta;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
const Params = imports.misc.params;
// This module provides functionality for driving the shell user interface
// in an automated fashion. The primary current use case for this is
@ -78,6 +79,7 @@ const PerfHelperIface = '<node> \
<arg type="i" direction="in" /> \
<arg type="b" direction="in" /> \
<arg type="b" direction="in" /> \
<arg type="b" direction="in" /> \
</method> \
<method name="WaitWindows" /> \
<method name="DestroyWindows" /> \
@ -97,11 +99,36 @@ function _getPerfHelper() {
return _perfHelper;
}
function _callRemote(obj, method, ...args) {
let cb;
let errcb;
args.push(function(result, excp) {
if (excp) {
if (errcb)
errcb(excp);
} else {
if (cb)
cb();
}
});
method.apply(obj, args);
return function(callback, error_callback) {
cb = callback;
errcb = error_callback;
};
}
/**
* createTestWindow:
* @width: width of window, in pixels
* @height: height of window, in pixels
* @alpha: whether the window should be alpha transparent
* @params: options for window creation.
* width - width of window, in pixels (default 640)
* height - height of window, in pixels (default 480)
* alpha - whether the window should have an alpha channel (default false)
* maximized - whether the window should be created maximized (default false)
* redraws - whether the window should continually redraw itself (default false)
* @maximized: whethe the window should be created maximized
*
* Creates a window using gnome-shell-perf-helper for testing purposes.
@ -110,19 +137,17 @@ function _getPerfHelper() {
* because of the normal X asynchronous mapping process, to actually wait
* until the window has been mapped and exposed, use waitTestWindows().
*/
function createTestWindow(width, height, alpha, maximized) {
let cb;
function createTestWindow(width, height, params) {
params = Params.parse(params, { width: 640,
height: 480,
alpha: false,
maximized: false,
redraws: false });
let perfHelper = _getPerfHelper();
perfHelper.CreateWindowRemote(width, height, alpha, maximized,
function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
return _callRemote(perfHelper, perfHelper.CreateWindowRemote,
params.width, params.height,
params.alpha, params.maximized, params.redraws);
}
/**
@ -132,17 +157,8 @@ function createTestWindow(width, height, alpha, maximized) {
* created with createTestWindow have been mapped and exposed.
*/
function waitTestWindows() {
let cb;
let perfHelper = _getPerfHelper();
perfHelper.WaitWindowsRemote(function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
return _callRemote(perfHelper, perfHelper.WaitWindowsRemote);
}
/**
@ -155,17 +171,8 @@ function waitTestWindows() {
* process because of normal X asynchronicity.
*/
function destroyTestWindows() {
let cb;
let perfHelper = _getPerfHelper();
perfHelper.DestroyWindowsRemote(function(result, excp) {
if (cb)
cb();
});
return function(callback) {
cb = callback;
};
return _callRemote(perfHelper, perfHelper.DestroyWindowsRemote);
}
/**
@ -208,6 +215,10 @@ function _step(g, finish, onError) {
let waitFunction = g.next();
waitFunction(function() {
_step(g, finish, onError);
},
function(err) {
if (onError)
onError(err);
});
} catch (err if err instanceof StopIteration) {
if (finish)
@ -306,8 +317,8 @@ function _collect(scriptModule, outputFile) {
print ('------------------------------------------------------------');
for (let i = 0; i < metrics.length; i++) {
let metric = metrics[i];
print ('# ' + scriptModule.METRIC_DESCRIPTIONS[metric]);
print (metric + ': ' + scriptModule.METRICS[metric]);
print ('# ' + scriptModule.METRICS[metric].description);
print (metric + ': ' + scriptModule.METRICS[metric].value + scriptModule.METRICS[metric].units);
}
print ('------------------------------------------------------------');
}
@ -360,7 +371,12 @@ function runPerfScript(scriptModule, outputFile) {
_step(g,
function() {
_collect(scriptModule, outputFile);
try {
_collect(scriptModule, outputFile);
} catch (err) {
log("Script failed: " + err + "\n" + err.stack);
Meta.exit(Meta.ExitCode.ERROR);
}
Meta.exit(Meta.ExitCode.SUCCESS);
},
function(err) {

View File

@ -32,6 +32,7 @@ const SearchSystem = new Lang.Class({
this._registerProvider(new AppDisplay.AppSearchProvider());
this._searchSettings = new Gio.Settings({ schema_id: SEARCH_PROVIDERS_SCHEMA });
this._searchSettings.connect('changed::enabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disabled', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::disable-external', Lang.bind(this, this._reloadRemoteProviders));
this._searchSettings.connect('changed::sort-order', Lang.bind(this, this._reloadRemoteProviders));
@ -242,8 +243,8 @@ const GridSearchResult = new Lang.Class({
dragSource = icon.icon;
content = { actor: actor, icon: icon };
} else {
if (content._delegate && content._delegate.getDragActorSource)
dragSource = content._delegate.getDragActorSource();
if (content.getDragActorSource)
dragSource = content.getDragActorSource();
}
this.actor.set_child(content.actor);
@ -266,7 +267,7 @@ const GridSearchResult = new Lang.Class({
if (!dragSource)
// not exactly right, but alignment problems are hard to notice
dragSource = content;
dragSource = content.actor;
this._dragActorSource = dragSource;
},
@ -433,7 +434,7 @@ const ListSearchResults = new Lang.Class({
},
_setMoreIconVisible: function(visible) {
this.providerIcon.moreIcon.visible = true;
this.providerIcon.moreIcon.visible = visible;
},
_getMaxDisplayedResults: function() {
@ -465,8 +466,14 @@ const GridSearchResults = new Lang.Class({
Name: 'GridSearchResults',
Extends: SearchResultsBase,
_init: function(provider) {
_init: function(provider, parentContainer) {
this.parent(provider);
// We need to use the parent container to know how much results we can show.
// None of the actors in this class can be used for that, since the main actor
// goes hidden when no results are displayed, and then it lost its allocation.
// Then on the next use of _getMaxDisplayedResults allocation is 0, en therefore
// it doesn't show any result although we have some.
this._parentContainer = parentContainer;
this._grid = new IconGrid.IconGrid({ rowLimit: MAX_GRID_SEARCH_RESULTS_ROWS,
xAlign: St.Align.START });
@ -477,16 +484,9 @@ const GridSearchResults = new Lang.Class({
},
_getMaxDisplayedResults: function() {
return this._grid.columnsForWidth(this._bin.width) * this._grid.getRowLimit();
},
_renderResults: function(metas) {
for (let i = 0; i < metas.length; i++) {
let display = new GridSearchResult(this.provider, metas[i]);
display.connect('activate', Lang.bind(this, this._activateResult));
display.actor.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._grid.addItem(display);
}
let parentThemeNode = this._parentContainer.get_theme_node();
let availableWidth = parentThemeNode.adjust_for_width(this._parentContainer.width);
return this._grid.columnsForWidth(availableWidth) * this._grid.getRowLimit();
},
_clearResultDisplay: function () {
@ -577,7 +577,7 @@ const SearchResults = new Lang.Class({
if (provider.appInfo)
providerDisplay = new ListSearchResults(provider);
else
providerDisplay = new GridSearchResults(provider);
providerDisplay = new GridSearchResults(provider, this._content);
providerDisplay.connect('key-focus-in', Lang.bind(this, this._keyFocusIn));
this._content.add(providerDisplay.actor);

View File

@ -24,6 +24,7 @@ const Slider = new Lang.Class({
accessible_role: Atk.Role.SLIDER });
this.actor.connect('repaint', Lang.bind(this, this._sliderRepaint));
this.actor.connect('button-press-event', Lang.bind(this, this._startDragging));
this.actor.connect('touch-event', Lang.bind(this, this._touchDragging));
this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
this.actor.connect('key-press-event', Lang.bind(this, this.onKeyPressEvent));
@ -121,11 +122,21 @@ const Slider = new Lang.Class({
this._dragging = true;
let device = event.get_device();
device.grab(this.actor);
this._grabbedDevice = device;
let sequence = event.get_event_sequence();
if (sequence != null)
device.sequence_grab(sequence, this.actor);
else
device.grab(this.actor);
this._grabbedDevice = device;
this._grabbedSequence = sequence;
if (sequence == null) {
this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging));
this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent));
}
this._releaseId = this.actor.connect('button-release-event', Lang.bind(this, this._endDragging));
this._motionId = this.actor.connect('motion-event', Lang.bind(this, this._motionEvent));
let absX, absY;
[absX, absY] = event.get_coords();
this._moveHandle(absX, absY);
@ -134,10 +145,17 @@ const Slider = new Lang.Class({
_endDragging: function() {
if (this._dragging) {
this.actor.disconnect(this._releaseId);
this.actor.disconnect(this._motionId);
if (this._releaseId)
this.actor.disconnect(this._releaseId);
if (this._motionId)
this.actor.disconnect(this._motionId);
this._grabbedDevice.ungrab();
if (this._grabbedSequence != null)
this._grabbedDevice.sequence_ungrab(this._grabbedSequence);
else
this._grabbedDevice.ungrab();
this._grabbedSequence = null;
this._grabbedDevice = null;
this._dragging = false;
@ -146,6 +164,24 @@ const Slider = new Lang.Class({
return Clutter.EVENT_STOP;
},
_touchDragging: function(actor, event) {
let device = event.get_device();
let sequence = event.get_event_sequence();
if (!this._dragging &&
event.type() == Clutter.EventType.TOUCH_BEGIN) {
this.startDragging(event);
return Clutter.EVENT_STOP;
} else if (device.sequence_get_grabbed_actor(sequence) == actor) {
if (event.type() == Clutter.EventType.TOUCH_UPDATE)
return this._motionEvent(actor, event);
else if (event.type() == Clutter.EventType.TOUCH_END)
return this._endDragging();
}
return Clutter.EVENT_PROPAGATE;
},
scroll: function(event) {
let direction = event.get_scroll_direction();
let delta;

View File

@ -283,11 +283,11 @@ const InputSourcePopup = new Lang.Class({
this._select(this._selectedIndex);
},
_keyPressHandler: function(keysym, backwards, action) {
_keyPressHandler: function(keysym, action) {
if (action == this._action)
this._select(backwards ? this._previous() : this._next());
this._select(this._next());
else if (action == this._actionBackward)
this._select(backwards ? this._next() : this._previous());
this._select(this._previous());
else if (keysym == Clutter.Left)
this._select(this._previous());
else if (keysym == Clutter.Right)
@ -366,13 +366,12 @@ const InputSourceIndicator = new Lang.Class({
this._keybindingAction =
Main.wm.addKeybinding('switch-input-source',
new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES,
Meta.KeyBindingFlags.NONE,
Shell.KeyBindingMode.ALL,
Lang.bind(this, this._switchInputSource));
this._keybindingActionBackward =
Main.wm.addKeybinding('switch-input-source-backward',
new Gio.Settings({ schema_id: "org.gnome.desktop.wm.keybindings" }),
Meta.KeyBindingFlags.REVERSES |
Meta.KeyBindingFlags.IS_REVERSED,
Shell.KeyBindingMode.ALL,
Lang.bind(this, this._switchInputSource));
@ -473,8 +472,7 @@ const InputSourceIndicator = new Lang.Class({
let popup = new InputSourcePopup(this._mruSources, this._keybindingAction, this._keybindingActionBackward);
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!popup.show(backwards, binding.get_name(), binding.get_mask()))
if (!popup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
popup.destroy();
},

View File

@ -9,8 +9,9 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Shell = imports.gi.Shell;
const LOCATION_SCHEMA = 'org.gnome.shell.location';
const LOCATION_SCHEMA = 'org.gnome.system.location';
const MAX_ACCURACY_LEVEL = 'max-accuracy-level';
const ENABLED = 'enabled';
var GeoclueIface = '<node> \
<interface name="org.freedesktop.GeoClue2.Manager"> \
@ -44,6 +45,8 @@ const Indicator = new Lang.Class({
this.parent();
this._settings = new Gio.Settings({ schema_id: LOCATION_SCHEMA });
this._settings.connect('changed::' + ENABLED,
Lang.bind(this, this._onMaxAccuracyLevelChanged));
this._settings.connect('changed::' + MAX_ACCURACY_LEVEL,
Lang.bind(this, this._onMaxAccuracyLevelChanged));
@ -93,10 +96,12 @@ const Indicator = new Lang.Class({
_syncIndicator: function() {
if (this._proxy == null) {
this._indicator.visible = false;
this._item.actor.visible = false;
return;
}
this._indicator.visible = this._proxy.InUse;
this._item.actor.visible = this._indicator.visible;
this._updateMenuLabels();
},
@ -123,7 +128,6 @@ const Indicator = new Lang.Class({
this._propertiesChangedId = this._proxy.connect('g-properties-changed',
Lang.bind(this, this._onGeocluePropsChanged));
this._availableAccuracyLevel = this._proxy.AvailableAccuracyLevel;
this._syncIndicator();
this._proxy.AddAgentRemote('gnome-shell', Lang.bind(this, this._onAgentRegistered));
@ -148,10 +152,8 @@ const Indicator = new Lang.Class({
},
_onOnOffAction: function() {
if (this._getMaxAccuracyLevel() == 0)
this._settings.set_enum(MAX_ACCURACY_LEVEL, this._availableAccuracyLevel);
else
this._settings.set_enum(MAX_ACCURACY_LEVEL, 0);
let enabled = this._settings.get_boolean(ENABLED);
this._settings.set_boolean(ENABLED, !enabled);
},
_onSessionUpdated: function() {
@ -160,12 +162,12 @@ const Indicator = new Lang.Class({
},
_updateMenuLabels: function() {
if (this._getMaxAccuracyLevel() == 0) {
this._item.status.text = _("Disabled");
this._onOffAction.label.text = _("Enable");
} else {
if (this._settings.get_boolean(ENABLED)) {
this._item.status.text = this._indicator.visible ? _("In Use") : _("Enabled");
this._onOffAction.label.text = _("Disable");
} else {
this._item.status.text = _("Disabled");
this._onOffAction.label.text = _("Enable");
}
},
@ -179,7 +181,10 @@ const Indicator = new Lang.Class({
},
_getMaxAccuracyLevel: function() {
return this._settings.get_enum(MAX_ACCURACY_LEVEL);
if (this._settings.get_boolean(ENABLED))
return this._settings.get_enum(MAX_ACCURACY_LEVEL);
else
return 0;
},
_notifyMaxAccuracyLevel: function() {
@ -191,12 +196,6 @@ const Indicator = new Lang.Class({
let unpacked = properties.deep_unpack();
if ("InUse" in unpacked)
this._syncIndicator();
if ("AvailableAccuracyLevel" in unpacked) {
this._availableAccuracyLevel = this._proxy.AvailableAccuracyLevel;
if (this._getMaxAccuracyLevel() != 0)
this._settings.set_enum(MAX_ACCURACY_LEVEL, this._availableAccuracyLevel);
}
}
});

View File

@ -151,11 +151,11 @@ const Indicator = new Lang.Class({
Gio.DBus.session.watch_name('org.gnome.SettingsDaemon.Orientation',
Gio.BusNameWatcherFlags.NONE,
Lang.bind(this, function() {
this._orentationExists = true;
this._orientationExists = true;
this._updateOrientationLock();
}),
Lang.bind(this, function() {
this._orentationExists = false;
this._orientationExists = false;
this._updateOrientationLock();
}));
this._updateOrientationLock();

View File

@ -178,19 +178,17 @@ const SwitcherPopup = new Lang.Class({
return mod(this._selectedIndex - 1, this._items.length);
},
_keyPressHandler: function(keysym, backwards, action) {
_keyPressHandler: function(keysym, action) {
throw new Error('Not implemented');
},
_keyPressEvent: function(actor, event) {
let keysym = event.get_key_symbol();
let event_state = event.get_state();
let backwards = event_state & Clutter.ModifierType.SHIFT_MASK;
let action = global.display.get_keybinding_action(event.get_key_code(), event_state);
let action = global.display.get_keybinding_action(event.get_key_code(), event.get_state());
this._disableHover();
if (this._keyPressHandler(keysym, backwards, action) != Clutter.EVENT_PROPAGATE)
if (this._keyPressHandler(keysym, action) != Clutter.EVENT_PROPAGATE)
return Clutter.EVENT_STOP;
if (keysym == Clutter.Escape)

View File

@ -53,8 +53,10 @@ function _wrapTweening(target, tweeningParameters) {
}
}
if (!Gtk.Settings.get_default().gtk_enable_animations)
if (!Gtk.Settings.get_default().gtk_enable_animations) {
tweeningParameters['time'] = 0.000001;
tweeningParameters['delay'] = 0.000001;
}
_addHandler(target, tweeningParameters, 'onComplete', _tweenCompleted);
}

View File

@ -49,13 +49,145 @@ function getTermsForSearchString(searchString) {
return terms;
}
const EDGE_THRESHOLD = 20;
const DRAG_DISTANCE = 80;
const EdgeDragAction = new Lang.Class({
Name: 'EdgeDragAction',
Extends: Clutter.GestureAction,
_init : function(side) {
this.parent();
this._side = side;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
_getMonitorRect : function (x, y) {
let rect = new Meta.Rectangle({ x: x - 1, y: y - 1, width: 1, height: 1 });
let monitorIndex = global.screen.get_monitor_index_for_rect(rect);
return global.screen.get_monitor_geometry(monitorIndex);
},
vfunc_gesture_prepare : function(action, actor) {
if (this.get_n_current_points() == 0)
return false;
let [x, y] = this.get_press_coords(0);
let monitorRect = this._getMonitorRect(x, y);
return ((this._side == St.Side.LEFT && x < monitorRect.x + EDGE_THRESHOLD) ||
(this._side == St.Side.RIGHT && x > monitorRect.x + monitorRect.width - EDGE_THRESHOLD) ||
(this._side == St.Side.TOP && y < monitorRect.y + EDGE_THRESHOLD) ||
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
},
vfunc_gesture_progress : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
let offsetY = Math.abs (y - startY);
if (offsetX < EDGE_THRESHOLD && offsetY < EDGE_THRESHOLD)
return true;
if ((offsetX > offsetY &&
(this._side == St.Side.TOP || this._side == St.Side.BOTTOM)) ||
(offsetY > offsetX &&
(this._side == St.Side.LEFT || this._side == St.Side.RIGHT))) {
this.cancel();
return false;
}
return true;
},
vfunc_gesture_end : function (action, actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);
if ((this._side == St.Side.TOP && y > monitorRect.y + DRAG_DISTANCE) ||
(this._side == St.Side.BOTTOM && y < monitorRect.y + monitorRect.height - DRAG_DISTANCE) ||
(this._side == St.Side.LEFT && x > monitorRect.x + DRAG_DISTANCE) ||
(this._side == St.Side.RIGHT && x < monitorRect.x + monitorRect.width - DRAG_DISTANCE))
this.emit('activated');
}
});
Signals.addSignalMethods(EdgeDragAction.prototype);
const ShowOverviewAction = new Lang.Class({
Name: 'ShowOverviewAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(3);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
return this.get_n_current_points() == this.get_n_touch_points();
},
_getBoundingRect : function(motion) {
let minX, minY, maxX, maxY;
for (let i = 0; i < this.get_n_current_points(); i++) {
let x, y;
if (motion == true) {
[x, y] = this.get_motion_coords(i);
} else {
[x, y] = this.get_press_coords(i);
}
if (i == 0) {
minX = maxX = x;
minY = maxY = y;
} else {
minX = Math.min(minX, x);
minY = Math.min(minY, y);
maxX = Math.max(maxX, x);
maxY = Math.max(maxY, y);
}
}
return new Meta.Rectangle({ x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY });
},
vfunc_gesture_begin : function(action, actor) {
this._initialRect = this._getBoundingRect(false);
return true;
},
vfunc_gesture_end : function(action, actor) {
let rect = this._getBoundingRect(true);
let oldArea = this._initialRect.width * this._initialRect.height;
let newArea = rect.width * rect.height;
let areaDiff = newArea / oldArea;
this.emit('activated', areaDiff);
}
});
Signals.addSignalMethods(ShowOverviewAction.prototype);
const ViewSelector = new Lang.Class({
Name: 'ViewSelector',
_init : function(searchEntry, showAppsButton) {
this.actor = new Shell.Stack({ name: 'viewSelector' });
this._showAppsBlocked = false;
this._showAppsButton = showAppsButton;
this._showAppsButton.connect('notify::checked', Lang.bind(this, this._onShowAppsButtonToggled));
@ -118,18 +250,26 @@ const ViewSelector = new Lang.Class({
this._stageKeyPressId = 0;
Main.overview.connect('showing', Lang.bind(this,
function () {
this._resetShowAppsButton();
this._stageKeyPressId = global.stage.connect('key-press-event',
Lang.bind(this, this._onStageKeyPress));
}));
Main.overview.connect('hiding', Lang.bind(this,
function () {
this._resetShowAppsButton();
if (this._stageKeyPressId != 0) {
global.stage.disconnect(this._stageKeyPressId);
this._stageKeyPressId = 0;
}
}));
Main.overview.connect('shown', Lang.bind(this,
function() {
// If we were animating from the desktop view to the
// apps page the workspace page was visible, allowing
// the windows to animate, but now we no longer want to
// show it given that we are now on the apps page or
// search page.
if (this._activePage != this._workspacesPage)
this._workspacesPage.opacity = 0;
}));
Main.wm.addKeybinding('toggle-application-view',
new Gio.Settings({ schema_id: SHELL_KEYBINDINGS_SCHEMA }),
@ -145,31 +285,56 @@ const ViewSelector = new Lang.Class({
Shell.KeyBindingMode.OVERVIEW,
Lang.bind(Main.overview, Main.overview.toggle));
let gesture;
gesture = new EdgeDragAction(St.Side.LEFT);
gesture.connect('activated', Lang.bind(this, function() {
if (Main.overview.visible)
Main.overview.hide();
else
this.showApps();
}));
global.stage.add_action(gesture);
gesture = new ShowOverviewAction();
gesture.connect('activated', Lang.bind(this, function(action, areaDiff) {
if (areaDiff < 0.7)
Main.overview.show();
}));
global.stage.add_action(gesture);
},
_toggleAppsPage: function() {
Main.overview.show();
this._showAppsButton.checked = !this._showAppsButton.checked;
Main.overview.show();
},
showApps: function() {
Main.overview.show();
this._showAppsButton.checked = true;
Main.overview.show();
},
show: function() {
this.reset();
this._workspacesDisplay.show();
this._workspacesDisplay.show(this._showAppsButton.checked);
this._activePage = null;
this._showPage(this._workspacesPage);
if (this._showAppsButton.checked)
this._showPage(this._appsPage);
else
this._showPage(this._workspacesPage);
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeOutDesktop();
},
zoomFromOverview: function() {
this._workspacesDisplay.zoomFromOverview();
animateFromOverview: function() {
// Make sure workspace page is fully visible to allow
// workspace.js do the animation of the windows
this._workspacesPage.opacity = 255;
this._workspacesDisplay.animateFromOverview(this._activePage != this._workspacesPage);
this._showAppsButton.checked = false;
if (!this._workspacesDisplay.activeWorkspaceHasMaximizedWindows())
Main.overview.fadeInDesktop();
@ -220,7 +385,10 @@ const ViewSelector = new Lang.Class({
});
},
_showPage: function(page, noFade) {
_showPage: function(page) {
if (!Main.overview.visible)
return;
if (page == this._activePage)
return;
@ -228,7 +396,7 @@ const ViewSelector = new Lang.Class({
this._activePage = page;
this.emit('page-changed');
if (oldPage && !noFade)
if (oldPage)
Tweener.addTween(oldPage,
{ opacity: 0,
time: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
@ -239,7 +407,7 @@ const ViewSelector = new Lang.Class({
})
});
else
this._fadePageIn(oldPage);
this._fadePageIn();
},
_a11yFocusPage: function(page) {
@ -248,21 +416,10 @@ const ViewSelector = new Lang.Class({
},
_onShowAppsButtonToggled: function() {
if (this._showAppsBlocked)
return;
this._showPage(this._showAppsButton.checked ?
this._appsPage : this._workspacesPage);
},
_resetShowAppsButton: function() {
this._showAppsBlocked = true;
this._showAppsButton.checked = false;
this._showAppsBlocked = false;
this._showPage(this._workspacesPage, true);
},
_onStageKeyPress: function(actor, event) {
// Ignore events while anything but the overview has
// pushed a modal (system modals, looking glass, ...)
@ -358,7 +515,10 @@ const ViewSelector = new Lang.Class({
startSearch: function(event) {
global.stage.set_key_focus(this._text);
this._text.event(event, true);
let synthEvent = event.copy();
synthEvent.set_source(this._text);
this._text.event(synthEvent, true);
},
// the entry does not show the hint

View File

@ -9,6 +9,7 @@ const Meta = imports.gi.Meta;
const Pango = imports.gi.Pango;
const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const AltTab = imports.ui.altTab;
const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
@ -18,6 +19,13 @@ const Tweener = imports.ui.tweener;
const WindowMenu = imports.ui.windowMenu;
const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
const MAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
const UNMAXIMIZE_WINDOW_ANIMATION_TIME = 0.15;
const MINIMIZE_WINDOW_ANIMATION_TIME = 0.2;
const SHOW_WINDOW_ANIMATION_TIME = 0.15;
const DIALOG_SHOW_WINDOW_ANIMATION_TIME = 0.1;
const DESTROY_WINDOW_ANIMATION_TIME = 0.15;
const DIALOG_DESTROY_WINDOW_ANIMATION_TIME = 0.1;
const WINDOW_ANIMATION_TIME = 0.25;
const DIM_BRIGHTNESS = -0.3;
const DIM_TIME = 0.500;
@ -456,6 +464,115 @@ const TilePreview = new Lang.Class({
}
});
const WorkspaceSwitchAction = new Lang.Class({
Name: 'WorkspaceSwitchAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(4);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
return this.get_n_current_points() == this.get_n_touch_points();
},
vfunc_gesture_end : function(action, actor) {
const MOTION_THRESHOLD = 50;
// Just check one touchpoint here
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = x - startX;
let offsetY = y - startY;
let direction;
if (Math.abs(offsetX) < MOTION_THRESHOLD &&
Math.abs(offsetY) < MOTION_THRESHOLD)
return;
if (Math.abs(offsetY) > Math.abs(offsetX)) {
if (offsetY > 0)
direction = Meta.MotionDirection.UP;
else
direction = Meta.MotionDirection.DOWN;
} else {
if (offsetX > 0)
direction = Meta.MotionDirection.LEFT;
else
direction = Meta.MotionDirection.RIGHT;
}
this.emit('activated', direction);
}
});
Signals.addSignalMethods(WorkspaceSwitchAction.prototype);
const AppSwitchAction = new Lang.Class({
Name: 'AppSwitchAction',
Extends: Clutter.GestureAction,
_init : function() {
this.parent();
this.set_n_touch_points(3);
global.display.connect('grab-op-begin', Lang.bind(this, function() {
this.cancel();
}));
},
vfunc_gesture_prepare : function(action, actor) {
return this.get_n_current_points() <= 4;
},
vfunc_gesture_begin : function(action, actor) {
// in milliseconds
const LONG_PRESS_TIMEOUT = 250;
let nPoints = this.get_n_current_points();
let event = this.get_last_event (nPoints - 1);
if (nPoints == 3)
this._longPressStartTime = event.get_time();
else if (nPoints == 4) {
// Check whether the 4th finger press happens after a 3-finger long press,
// this only needs to be checked on the first 4th finger press
if (this._longPressStartTime != null &&
event.get_time() < this._longPressStartTime + LONG_PRESS_TIMEOUT)
this.cancel();
else {
this._longPressStartTime = null;
this.emit('activated');
}
}
return this.get_n_current_points() <= 4;
},
vfunc_gesture_progress : function(action, actor) {
const MOTION_THRESHOLD = 30;
if (this.get_n_current_points() == 3) {
for (let i = 0; i < this.get_n_current_points(); i++) {
[startX, startY] = this.get_press_coords(i);
[x, y] = this.get_motion_coords(i);
if (Math.abs(x - startX) > MOTION_THRESHOLD ||
Math.abs(y - startY) > MOTION_THRESHOLD)
return false;
}
}
return true;
}
});
Signals.addSignalMethods(AppSwitchAction.prototype);
const WindowManager = new Lang.Class({
Name: 'WindowManager',
@ -683,6 +800,53 @@ const WindowManager = new Lang.Class({
global.screen.override_workspace_layout(Meta.ScreenCorner.TOPLEFT,
false, -1, 1);
let gesture = new WorkspaceSwitchAction();
gesture.connect('activated', Lang.bind(this, function(action, direction) {
let newWs = global.screen.get_active_workspace().get_neighbor(direction);
this.actionMoveWorkspace(newWs);
}));
global.stage.add_action(gesture);
gesture = new AppSwitchAction();
gesture.connect('activated', Lang.bind(this, this._switchApp));
global.stage.add_action(gesture);
},
_lookupIndex: function (windows, metaWindow) {
for (let i = 0; i < windows.length; i++) {
if (windows[i].metaWindow == metaWindow) {
return i;
}
}
return -1;
},
_switchApp : function () {
let windows = global.get_window_actors().filter(Lang.bind(this, function(actor) {
let win = actor.metaWindow;
return (!win.is_override_redirect() &&
win.located_on_workspace(global.screen.get_active_workspace()));
}));
if (windows.length == 0)
return;
let focusWindow = global.display.focus_window;
let nextWindow;
if (focusWindow == null)
nextWindow = windows[0].metaWindow;
else {
let index = this._lookupIndex (windows, focusWindow) + 1;
if (index >= windows.length)
index = 0;
nextWindow = windows[index].metaWindow;
}
Main.activateWindow(nextWindow);
},
keepWorkspaceAlive: function(workspace, duration) {
@ -717,12 +881,12 @@ const WindowManager = new Lang.Class({
return !Main.overview.visible;
},
_shouldAnimateActor: function(actor) {
_shouldAnimateActor: function(actor, types) {
if (!this._shouldAnimate())
return false;
let windowType = actor.meta_window.get_window_type();
return windowType == Meta.WindowType.NORMAL ||
windowType == Meta.WindowType.MODAL_DIALOG;
let type = actor.meta_window.get_window_type();
return types.indexOf(type) >= 0;
},
_removeEffect : function(list, actor) {
@ -735,7 +899,10 @@ const WindowManager = new Lang.Class({
},
_minimizeWindow : function(shellwm, actor) {
if (!this._shouldAnimateActor(actor)) {
let types = [Meta.WindowType.NORMAL,
Meta.WindowType.MODAL_DIALOG,
Meta.WindowType.DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_minimize(actor);
return;
}
@ -747,7 +914,7 @@ const WindowManager = new Lang.Class({
if (actor.meta_window.is_monitor_sized()) {
Tweener.addTween(actor,
{ opacity: 0,
time: WINDOW_ANIMATION_TIME,
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
@ -779,8 +946,8 @@ const WindowManager = new Lang.Class({
scale_y: yScale,
x: xDest,
y: yDest,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
time: MINIMIZE_WINDOW_ANIMATION_TIME,
transition: 'easeInExpo',
onComplete: this._minimizeWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
@ -796,7 +963,7 @@ const WindowManager = new Lang.Class({
Tweener.removeTweens(actor);
actor.set_scale(1.0, 1.0);
actor.set_opacity(255);
actor.move_anchor_point_from_gravity(Clutter.Gravity.NORTH_WEST);
actor.set_pivot_point(0, 0);
shellwm.completed_minimize(actor);
}
@ -894,7 +1061,10 @@ const WindowManager = new Lang.Class({
actor._windowType = type;
}));
if (!this._shouldAnimateActor(actor)) {
let types = [Meta.WindowType.NORMAL,
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_map(actor);
return;
}
@ -902,15 +1072,23 @@ const WindowManager = new Lang.Class({
if (actor.meta_window.is_attached_dialog()) {
/* Scale the window from the center of the parent */
this._checkDimming(actor.get_meta_window().get_transient_for());
actor.set_scale(1.0, 0.0);
actor.set_pivot_point(0.5, 0.5);
}
switch (actor._windowType) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 1.0);
actor.scale_x = 0.01;
actor.scale_y = 0.05;
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ scale_y: 1,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
{ opacity: 255,
scale_x: 1,
scale_y: 1,
time: SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutExpo',
onComplete: this._mapWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
@ -918,15 +1096,20 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
} else {
/* Fade window in */
break;
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.set_pivot_point(0.5, 0.5);
actor.scale_y = 0;
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
Tweener.addTween(actor,
{ opacity: 255,
time: WINDOW_ANIMATION_TIME,
scale_x: 1,
scale_y: 1,
time: DIALOG_SHOW_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._mapWindowDone,
onCompleteScope: this,
@ -935,6 +1118,10 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
break;
default:
shellwm.completed_map(actor);
return;
}
},
@ -942,7 +1129,11 @@ const WindowManager = new Lang.Class({
if (this._removeEffect(this._mapping, actor)) {
Tweener.removeTweens(actor);
actor.opacity = 255;
actor.set_pivot_point(0, 0);
actor.scale_y = 1;
actor.scale_x = 1;
actor.translation_y = 0;
actor.translation_x = 0;
shellwm.completed_map(actor);
}
},
@ -965,30 +1156,25 @@ const WindowManager = new Lang.Class({
});
}
if (!this._shouldAnimateActor(actor)) {
let types = [Meta.WindowType.NORMAL,
Meta.WindowType.DIALOG,
Meta.WindowType.MODAL_DIALOG];
if (!this._shouldAnimateActor(actor, types)) {
shellwm.completed_destroy(actor);
return;
}
this._destroying.push(actor);
if (window.is_attached_dialog()) {
let parent = window.get_transient_for();
this._checkDimming(parent, window);
actor.set_scale(1.0, 1.0);
switch (actor._windowType) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 0.5);
actor.show();
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor);
this._destroyWindowDone(shellwm, actor);
}));
this._destroying.push(actor);
Tweener.addTween(actor,
{ scale_y: 0,
time: WINDOW_ANIMATION_TIME,
transition: "easeOutQuad",
{ opacity: 0,
scale_x: 0.8,
scale_y: 0.8,
time: DESTROY_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
@ -996,9 +1182,37 @@ const WindowManager = new Lang.Class({
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
break;
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
if (window.is_attached_dialog()) {
let parent = window.get_transient_for();
this._checkDimming(parent, window);
actor._parentDestroyId = parent.connect('unmanaged', Lang.bind(this, function () {
Tweener.removeTweens(actor);
this._destroyWindowDone(shellwm, actor);
}));
}
Tweener.addTween(actor,
{ scale_y: 0,
time: DIALOG_DESTROY_WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._destroyWindowDone,
onCompleteScope: this,
onCompleteParams: [shellwm, actor],
onOverwrite: this._destroyWindowDone,
onOverwriteScope: this,
onOverwriteParams: [shellwm, actor]
});
break;
default:
shellwm.completed_destroy(actor);
return;
}
shellwm.completed_destroy(actor);
},
_destroyWindowDone : function(shellwm, actor) {
@ -1171,9 +1385,7 @@ const WindowManager = new Lang.Class({
let tabPopup = new AltTab.AppSwitcherPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
@ -1184,16 +1396,12 @@ const WindowManager = new Lang.Class({
let tabPopup = new AltTab.WindowSwitcherPopup();
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
if (!tabPopup.show(backwards, binding.get_name(), binding.get_mask()))
if (!tabPopup.show(binding.is_reversed(), binding.get_name(), binding.get_mask()))
tabPopup.destroy();
},
_startA11ySwitcher : function(display, screen, window, binding) {
let modifiers = binding.get_modifiers();
let backwards = modifiers & Meta.VirtualModifier.SHIFT_MASK;
Main.ctrlAltTabManager.popup(backwards, binding.get_name(), binding.get_mask());
Main.ctrlAltTabManager.popup(binding.is_reversed(), binding.get_name(), binding.get_mask());
},
_toggleAppMenu : function(display, screen, window, event, binding) {

View File

@ -34,6 +34,8 @@ const DRAGGING_WINDOW_OPACITY = 100;
const LAYOUT_SCALE_WEIGHT = 1;
const LAYOUT_SPACE_WEIGHT = 0.1;
const WINDOW_ANIMATION_MAX_NUMBER_BLENDING = 3;
function _interpolate(start, end, step) {
return start + (end - start) * step;
}
@ -87,7 +89,7 @@ const WindowCloneLayout = new Lang.Class({
},
vfunc_allocate: function(container, box, flags) {
let clone = container.get_children().forEach(function (child) {
container.get_children().forEach(Lang.bind(this, function (child) {
let realWindow;
if (child == container._delegate._windowClone)
realWindow = container._delegate.realWindow;
@ -96,8 +98,8 @@ const WindowCloneLayout = new Lang.Class({
child.allocate(this._makeBoxForWindow(realWindow.meta_window),
flags);
}, this);
},
}));
}
});
const WindowClone = new Lang.Class({
@ -517,6 +519,7 @@ const WindowOverlay = new Lang.Class({
Tweener.removeTweens(button);
Tweener.removeTweens(border);
Tweener.removeTweens(title);
let [cloneX, cloneY, cloneWidth, cloneHeight] = this._windowClone.slot;
@ -1258,6 +1261,13 @@ const Workspace = new Lang.Class({
return;
}
// We will reposition windows anyway when enter again overview or when ending the windows
// animations whith fade animation.
// In this way we avoid unwanted animations of windows repositioning while
// animating overview.
if (this.leavingOverview || this._animatingWindowsFade)
return;
let initialPositioning = flags & WindowPositionFlags.INITIAL;
let animate = flags & WindowPositionFlags.ANIMATE;
@ -1320,7 +1330,7 @@ const Workspace = new Lang.Class({
});
}
this._animateClone(clone, overlay, x, y, scale, initialPositioning);
this._animateClone(clone, overlay, x, y, scale);
} else {
// cancel any active tweens (otherwise they might override our changes)
Tweener.removeTweens(clone.actor);
@ -1349,7 +1359,7 @@ const Workspace = new Lang.Class({
}
},
_animateClone: function(clone, overlay, x, y, scale, initialPositioning) {
_animateClone: function(clone, overlay, x, y, scale) {
Tweener.addTween(clone.actor,
{ x: x,
y: y,
@ -1556,14 +1566,141 @@ const Workspace = new Lang.Class({
return false;
},
// Animate the full-screen to Overview transition.
zoomToOverview : function() {
fadeToOverview: function() {
// We don't want to reposition windows while animating in this way.
this._animatingWindowsFade = true;
this._overviewShownId = Main.overview.connect('shown', Lang.bind(this,
this._doneShowingOverview));
if (this._windows.length == 0)
return;
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
return;
// Special case maximized windows, since it doesn't make sense
// to animate windows below in the stack
let topMaximizedWindow;
// It is ok to treat the case where there is no maximized
// window as if the bottom-most window was maximized given that
// it won't affect the result of the animation
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
break;
}
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
let topIndex = this._windows.length - 1;
for (let i = 0; i < this._windows.length; i++) {
if (i < topMaximizedWindow) {
// below top-most maximized window, don't animate
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
this._windows[i].actor.opacity = 0;
} else {
let fromTop = topIndex - i;
let time;
if (fromTop < nTimeSlots) // animate top-most windows gradually
time = windowBaseTime * (nTimeSlots - fromTop);
else
time = windowBaseTime;
this._windows[i].actor.opacity = 255;
this._fadeWindow(i, time, 0);
}
}
},
fadeFromOverview: function() {
this.leavingOverview = true;
this._overviewHiddenId = Main.overview.connect('hidden', Lang.bind(this,
this._doneLeavingOverview));
if (this._windows.length == 0)
return;
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
Tweener.removeTweens(clone.actor);
}
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
if (this.metaWorkspace != null && this.metaWorkspace != global.screen.get_active_workspace())
return;
// Special case maximized windows, since it doesn't make sense
// to animate windows below in the stack
let topMaximizedWindow;
// It is ok to treat the case where there is no maximized
// window as if the bottom-most window was maximized given that
// it won't affect the result of the animation
for (topMaximizedWindow = this._windows.length - 1; topMaximizedWindow > 0; topMaximizedWindow--) {
let metaWindow = this._windows[topMaximizedWindow].metaWindow;
if (metaWindow.maximized_horizontally && metaWindow.maximized_vertically)
break;
}
let nTimeSlots = Math.min(WINDOW_ANIMATION_MAX_NUMBER_BLENDING + 1, this._windows.length - topMaximizedWindow);
let windowBaseTime = Overview.ANIMATION_TIME / nTimeSlots;
let topIndex = this._windows.length - 1;
for (let i = 0; i < this._windows.length; i++) {
if (i < topMaximizedWindow) {
// below top-most maximized window, don't animate
let overlay = this._windowOverlays[i];
if (overlay)
overlay.hide();
this._windows[i].actor.opacity = 0;
} else {
let fromTop = topIndex - i;
let time;
if (fromTop < nTimeSlots) // animate top-most windows gradually
time = windowBaseTime * (fromTop + 1);
else
time = windowBaseTime * nTimeSlots;
this._windows[i].actor.opacity = 0;
this._fadeWindow(i, time, 255);
}
}
},
_fadeWindow: function(index, time, opacity) {
let clone = this._windows[index];
let overlay = this._windowOverlays[index];
if (overlay)
overlay.hide();
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
clone.actor.scale_x = 1;
clone.actor.scale_y = 1;
clone.actor.x = origX;
clone.actor.y = origY;
Tweener.addTween(clone.actor,
{ time: time,
opacity: opacity,
transition: 'easeOutQuad'
});
} else {
// The window is hidden
clone.actor.opacity = 0;
}
},
zoomToOverview: function() {
// Position and scale the windows.
this._recalculateWindowPositions(WindowPositionFlags.ANIMATE | WindowPositionFlags.INITIAL);
},
// Animates the return from Overview mode
zoomFromOverview : function() {
zoomFromOverview: function() {
let currentWorkspace = global.screen.get_active_workspace();
this.leavingOverview = true;
@ -1584,35 +1721,37 @@ const Workspace = new Lang.Class({
return;
// Position and scale the windows.
for (let i = 0; i < this._windows.length; i++) {
let clone = this._windows[i];
let overlay = this._windowOverlays[i];
for (let i = 0; i < this._windows.length; i++)
this._zoomWindowFromOverview(i);
},
if (overlay)
overlay.hide();
_zoomWindowFromOverview: function(index) {
let clone = this._windows[index];
let overlay = this._windowOverlays[index];
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
if (overlay)
overlay.hide();
Tweener.addTween(clone.actor,
{ x: origX,
y: origY,
scale_x: 1.0,
scale_y: 1.0,
time: Overview.ANIMATION_TIME,
opacity: 255,
transition: 'easeOutQuad'
});
} else {
// The window is hidden, make it shrink and fade it out
Tweener.addTween(clone.actor,
{ scale_x: 0,
scale_y: 0,
opacity: 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
if (clone.metaWindow.showing_on_its_workspace()) {
let [origX, origY] = clone.getOriginalPosition();
Tweener.addTween(clone.actor,
{ x: origX,
y: origY,
scale_x: 1.0,
scale_y: 1.0,
time: Overview.ANIMATION_TIME,
opacity: 255,
transition: 'easeOutQuad'
});
} else {
// The window is hidden, make it shrink and fade it out
Tweener.addTween(clone.actor,
{ scale_x: 0,
scale_y: 0,
opacity: 0,
time: Overview.ANIMATION_TIME,
transition: 'easeOutQuad'
});
}
},
@ -1651,6 +1790,11 @@ const Workspace = new Lang.Class({
this.leavingOverview = false;
},
_doneShowingOverview: function() {
this._animatingWindowsFade = false;
this._recalculateWindowPositions(WindowPositionFlags.INITIAL);
},
// Tests if @actor belongs to this workspaces and monitor
_isMyWindow : function (actor) {
let win = actor.meta_window;

View File

@ -306,7 +306,7 @@ const WorkspaceThumbnail = new Lang.Class({
_createBackground: function() {
this._bgManager = new Background.BackgroundManager({ monitorIndex: Main.layoutManager.primaryIndex,
container: this._contents,
effects: Meta.BackgroundEffects.NONE });
vignette: false });
},
setPorthole: function(x, y, width, height) {
@ -878,9 +878,6 @@ const ThumbnailsBox = new Lang.Class({
for (let key in ThumbnailState)
this._stateCounts[ThumbnailState[key]] = 0;
// The "porthole" is the portion of the screen that we show in the workspaces
this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
this.addThumbnails(0, global.screen.n_workspaces);
this._updateSwitcherVisibility();
@ -904,6 +901,7 @@ const ThumbnailsBox = new Lang.Class({
for (let w = 0; w < this._thumbnails.length; w++)
this._thumbnails[w].destroy();
this._thumbnails = [];
this._porthole = null;
},
_workspacesChanged: function() {
@ -934,6 +932,7 @@ const ThumbnailsBox = new Lang.Class({
},
addThumbnails: function(start, count) {
this._ensurePorthole();
for (let k = start; k < start + count; k++) {
let metaWorkspace = global.screen.get_workspace_by_index(k);
let thumbnail = new WorkspaceThumbnail(metaWorkspace);
@ -1121,9 +1120,7 @@ const ThumbnailsBox = new Lang.Class({
// the size request to our children because we know how big they are and know
// that the actors aren't depending on the virtual functions being called.
if (this._thumbnails.length == 0)
return;
this._ensurePorthole();
let themeNode = this.actor.get_theme_node();
let spacing = themeNode.get_length('spacing');
@ -1135,8 +1132,7 @@ const ThumbnailsBox = new Lang.Class({
},
_getPreferredWidth: function(actor, forHeight, alloc) {
if (this._thumbnails.length == 0)
return;
this._ensurePorthole();
let themeNode = this.actor.get_theme_node();
@ -1154,6 +1150,13 @@ const ThumbnailsBox = new Lang.Class({
alloc.natural_size = width;
},
// The "porthole" is the portion of the screen that we show in the
// workspaces
_ensurePorthole: function() {
if (!this._porthole)
this._porthole = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
},
_allocate: function(actor, box, flags) {
let rtl = (Clutter.get_default_text_direction () == Clutter.TextDirection.RTL);

View File

@ -21,6 +21,11 @@ const WORKSPACE_SWITCH_TIME = 0.25;
// Note that mutter has a compile-time limit of 36
const MAX_WORKSPACES = 16;
const AnimationType = {
ZOOM: 0,
FADE: 1
};
const OVERRIDE_SCHEMA = 'org.gnome.shell.overrides';
const WorkspacesViewBase = new Lang.Class({
@ -142,17 +147,25 @@ const WorkspacesView = new Lang.Class({
return this._workspaces[active];
},
zoomToOverview: function() {
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomToOverview();
animateToOverview: function(animationType) {
for (let w = 0; w < this._workspaces.length; w++) {
if (animationType == AnimationType.ZOOM)
this._workspaces[w].zoomToOverview();
else
this._workspaces[w].fadeToOverview();
}
this._updateWorkspaceActors(false);
},
zoomFromOverview: function() {
animateFromOverview: function(animationType) {
this.actor.remove_clip();
for (let w = 0; w < this._workspaces.length; w++)
this._workspaces[w].zoomFromOverview();
for (let w = 0; w < this._workspaces.length; w++) {
if (animationType == AnimationType.ZOOM)
this._workspaces[w].zoomFromOverview();
else
this._workspaces[w].fadeFromOverview();
}
},
syncStacking: function(stackIndices) {
@ -365,12 +378,18 @@ const ExtraWorkspaceView = new Lang.Class({
this._workspace.setActualGeometry(this._actualGeometry);
},
zoomToOverview: function() {
this._workspace.zoomToOverview();
animateToOverview: function(animationType) {
if (animationType == AnimationType.ZOOM)
this._workspace.zoomToOverview();
else
this._workspace.fadeToOverview();
},
zoomFromOverview: function() {
this._workspace.zoomFromOverview();
animateFromOverview: function(animationType) {
if (animationType == AnimationType.ZOOM)
this._workspace.zoomFromOverview();
else
this._workspace.fadeFromOverview();
},
syncStacking: function(stackIndices) {
@ -462,10 +481,16 @@ const WorkspacesDisplay = new Lang.Class({
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
},
show: function() {
show: function(fadeOnPrimary) {
this._updateWorkspacesViews();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomToOverview();
for (let i = 0; i < this._workspacesViews.length; i++) {
let animationType;
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateToOverview(animationType);
}
this._restackedNotifyId =
Main.overview.connect('windows-restacked',
@ -474,9 +499,15 @@ const WorkspacesDisplay = new Lang.Class({
this._scrollEventId = Main.overview.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
},
zoomFromOverview: function() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].zoomFromOverview();
animateFromOverview: function(fadeOnPrimary) {
for (let i = 0; i < this._workspacesViews.length; i++) {
let animationType;
if (fadeOnPrimary && i == this._primaryIndex)
animationType = AnimationType.FADE;
else
animationType = AnimationType.ZOOM;
this._workspacesViews[i].animateFromOverview(animationType);
}
},
hide: function() {

1093
po/as.po

File diff suppressed because it is too large Load Diff

653
po/de.po

File diff suppressed because it is too large Load Diff

783
po/el.po

File diff suppressed because it is too large Load Diff

211
po/es.po
View File

@ -10,8 +10,8 @@ msgstr ""
"Project-Id-Version: gnome-shell.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2014-06-17 07:28+0000\n"
"PO-Revision-Date: 2014-06-17 18:41+0200\n"
"POT-Creation-Date: 2014-07-22 07:35+0000\n"
"PO-Revision-Date: 2014-07-22 11:27+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
"Language: es\n"
@ -324,19 +324,23 @@ msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr ""
"Retardo al cambiar el foco del ratón hasta que el puntero deja de moverse"
#: ../js/extensionPrefs/main.js:125
#: ../data/org.gnome.Shell.PortalHelper.desktop.in.h:1
msgid "Captive Portal"
msgstr "Portal captivo"
#: ../js/extensionPrefs/main.js:127
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Hubo un error al lanzar el diálogo de preferencias para %s:"
#: ../js/extensionPrefs/main.js:157
#: ../js/extensionPrefs/main.js:159
msgid "GNOME Shell Extensions"
msgstr "Extensiones de GNOME Shell"
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:136
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:142
#: ../js/ui/components/polkitAgent.js:166 ../js/ui/endSessionDialog.js:429
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/network.js:878
#: ../js/ui/status/network.js:915
msgid "Cancel"
msgstr "Cancelar"
@ -367,8 +371,8 @@ msgstr "¿No está en la lista?"
msgid "(e.g., user or %s)"
msgstr "(ej., usuario o %s)"
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:262
#: ../js/ui/components/networkAgent.js:280
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:286
msgid "Username: "
msgstr "Nombre de usuario:"
@ -397,6 +401,10 @@ msgstr "No se pudo analizar el comando:"
msgid "Execution of “%s” failed:"
msgstr "Falló la ejecución de «%s»:"
#: ../js/portalHelper/main.js:84
msgid "Web Authentication Redirect"
msgstr "Redirección para autenticación web"
#: ../js/ui/appDisplay.js:641
msgid "Frequently used applications will appear here"
msgstr "Las aplicaciones usadas frecuentemente aparecerán aquí"
@ -409,19 +417,19 @@ msgstr "Frecuentes"
msgid "All"
msgstr "Todas"
#: ../js/ui/appDisplay.js:1569
#: ../js/ui/appDisplay.js:1613
msgid "New Window"
msgstr "Ventana nueva"
#: ../js/ui/appDisplay.js:1591 ../js/ui/dash.js:285
#: ../js/ui/appDisplay.js:1635 ../js/ui/dash.js:285
msgid "Remove from Favorites"
msgstr "Quitar de los favoritos"
#: ../js/ui/appDisplay.js:1597
#: ../js/ui/appDisplay.js:1641
msgid "Add to Favorites"
msgstr "Añadir a los favoritos"
#: ../js/ui/appDisplay.js:1606
#: ../js/ui/appDisplay.js:1650
msgid "Show Details"
msgstr "Mostrar detalles"
@ -435,7 +443,7 @@ msgstr "Se ha añadido %s a sus favoritos."
msgid "%s has been removed from your favorites."
msgstr "Se ha quitado %s de sus favoritos."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:810
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:809
#: ../js/ui/status/system.js:337
msgid "Settings"
msgstr "Configuración"
@ -569,35 +577,35 @@ msgid "Next month"
msgstr "Siguiente mes"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:775
#: ../js/ui/calendar.js:785
msgid "Nothing Scheduled"
msgstr "Nada programado"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:793
#: ../js/ui/calendar.js:803
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %d de %B"
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:796
#: ../js/ui/calendar.js:806
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %d de %B de %Y"
#: ../js/ui/calendar.js:807
#: ../js/ui/calendar.js:817
msgid "Today"
msgstr "Hoy"
#: ../js/ui/calendar.js:811
#: ../js/ui/calendar.js:821
msgid "Tomorrow"
msgstr "Mañana"
#: ../js/ui/calendar.js:822
#: ../js/ui/calendar.js:832
msgid "This week"
msgstr "Esta semana"
#: ../js/ui/calendar.js:830
#: ../js/ui/calendar.js:840
msgid "Next week"
msgstr "La semana que viene"
@ -630,40 +638,40 @@ msgstr "Contraseña:"
msgid "Type again:"
msgstr "Escriba de nuevo:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:240
#: ../js/ui/status/network.js:322 ../js/ui/status/network.js:881
#: ../js/ui/components/networkAgent.js:137 ../js/ui/status/network.js:277
#: ../js/ui/status/network.js:359 ../js/ui/status/network.js:918
msgid "Connect"
msgstr "Conectar"
#: ../js/ui/components/networkAgent.js:224
#: ../js/ui/components/networkAgent.js:236
#: ../js/ui/components/networkAgent.js:264
#: ../js/ui/components/networkAgent.js:284
#: ../js/ui/components/networkAgent.js:294
#: ../js/ui/components/networkAgent.js:230
#: ../js/ui/components/networkAgent.js:242
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:290
#: ../js/ui/components/networkAgent.js:300
msgid "Password: "
msgstr "Contraseña: "
#: ../js/ui/components/networkAgent.js:229
#: ../js/ui/components/networkAgent.js:235
msgid "Key: "
msgstr "Clave:"
#: ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:274
msgid "Identity: "
msgstr "Identidad:"
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:276
msgid "Private key password: "
msgstr "Contraseña de la clave privada:"
#: ../js/ui/components/networkAgent.js:282
#: ../js/ui/components/networkAgent.js:288
msgid "Service: "
msgstr "Servicio:"
#: ../js/ui/components/networkAgent.js:311
#: ../js/ui/components/networkAgent.js:317
msgid "Authentication required by wireless network"
msgstr "La red inalámbrica requiere autenticación"
#: ../js/ui/components/networkAgent.js:312
#: ../js/ui/components/networkAgent.js:318
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -672,35 +680,35 @@ msgstr ""
"Se necesitan contraseñas o claves de cifrado para acceder a la red "
"inalámbrica «%s»."
#: ../js/ui/components/networkAgent.js:316
#: ../js/ui/components/networkAgent.js:322
msgid "Wired 802.1X authentication"
msgstr "Autenticación 802.1X cableada"
#: ../js/ui/components/networkAgent.js:318
#: ../js/ui/components/networkAgent.js:324
msgid "Network name: "
msgstr "Nombre de la red"
#: ../js/ui/components/networkAgent.js:323
#: ../js/ui/components/networkAgent.js:329
msgid "DSL authentication"
msgstr "Autenticación DSL"
#: ../js/ui/components/networkAgent.js:330
#: ../js/ui/components/networkAgent.js:336
msgid "PIN code required"
msgstr "Código PIN requerido"
#: ../js/ui/components/networkAgent.js:331
#: ../js/ui/components/networkAgent.js:337
msgid "PIN code is needed for the mobile broadband device"
msgstr "Se necesita un código PIN para el dispositivo de banda ancha móvil"
#: ../js/ui/components/networkAgent.js:332
#: ../js/ui/components/networkAgent.js:338
msgid "PIN: "
msgstr "PIN: "
#: ../js/ui/components/networkAgent.js:338
#: ../js/ui/components/networkAgent.js:344
msgid "Mobile broadband network password"
msgstr "Contraseña de la red de banda ancha móvil"
#: ../js/ui/components/networkAgent.js:339
#: ../js/ui/components/networkAgent.js:345
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "Se requiere una contraseña para conectarse a «%s»."
@ -1001,7 +1009,7 @@ msgstr "Ver cuenta"
msgid "Unknown reason"
msgstr "Razón desconocida"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:229
msgid "Windows"
msgstr "Ventanas"
@ -1204,7 +1212,7 @@ msgstr "Activado"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:719 ../js/ui/status/location.js:164
#: ../js/ui/status/network.js:555 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/status/network.js:592 ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Desactivado"
@ -1264,7 +1272,7 @@ msgstr "Bandeja de mensajes"
msgid "System Information"
msgstr "Información del sistema"
#: ../js/ui/notificationDaemon.js:516 ../src/shell-app.c:425
#: ../js/ui/notificationDaemon.js:513 ../src/shell-app.c:425
msgctxt "program"
msgid "Unknown"
msgstr "Desconocido"
@ -1292,32 +1300,37 @@ msgstr "Vista general"
msgid "Type to search…"
msgstr "Escribir para buscar…"
#: ../js/ui/panel.js:516
#: ../js/ui/panel.js:515
msgid "Quit"
msgstr "Salir"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". */
#: ../js/ui/panel.js:568
#: ../js/ui/panel.js:567
msgid "Activities"
msgstr "Actividades"
#: ../js/ui/panel.js:915
#: ../js/ui/panel.js:914
msgid "Top Bar"
msgstr "Barra superior"
#: ../js/ui/popupMenu.js:279
#: ../js/ui/popupMenu.js:274
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:74
#: ../js/ui/runDialog.js:70
msgid "Enter a Command"
msgstr "Introducir un comando"
#: ../js/ui/runDialog.js:114 ../js/ui/windowMenu.js:120
#: ../js/ui/runDialog.js:110 ../js/ui/windowMenu.js:120
msgid "Close"
msgstr "Cerrar"
#: ../js/ui/runDialog.js:273
#| msgid "Estimating…"
msgid "Restarting…"
msgstr "Reiniciando…"
#. Translators: This is a time format for a date in
#. long format */
#: ../js/ui/screenShield.js:88
@ -1347,11 +1360,11 @@ msgstr "No se pudo bloquear"
msgid "Lock was blocked by an application"
msgstr "Una aplicación impidió el bloqueo"
#: ../js/ui/search.js:606
#: ../js/ui/search.js:614
msgid "Searching…"
msgstr "Buscando…"
#: ../js/ui/search.js:652
#: ../js/ui/search.js:660
msgid "No results."
msgstr "No se encontraron resultados."
@ -1427,9 +1440,9 @@ msgstr "Texto grande"
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:151
#: ../js/ui/status/network.js:323 ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1345 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:178
#: ../js/ui/status/network.js:360 ../js/ui/status/network.js:1281
#: ../js/ui/status/network.js:1392 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/rfkill.js:114
msgid "Turn Off"
msgstr "Apagar"
@ -1445,7 +1458,7 @@ msgid_plural "%d Connected Devices"
msgstr[0] "%d dispositivo conectado"
msgstr[1] "%d dispositivos conectados"
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1262
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1309
msgid "Not Connected"
msgstr "No conectado"
@ -1473,156 +1486,156 @@ msgstr "Activar"
msgid "In Use"
msgstr "En uso"
#: ../js/ui/status/network.js:74
#: ../js/ui/status/network.js:101
msgid "<unknown>"
msgstr "<desconocido>"
#: ../js/ui/status/network.js:420 ../js/ui/status/network.js:1260
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:457 ../js/ui/status/network.js:1307
#: ../js/ui/status/network.js:1511
msgid "Off"
msgstr "Desconectado"
#: ../js/ui/status/network.js:422
#: ../js/ui/status/network.js:459
msgid "Connected"
msgstr "Conectada"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu) */
#: ../js/ui/status/network.js:426
#: ../js/ui/status/network.js:463
msgid "Unmanaged"
msgstr "Sin gestionar"
#: ../js/ui/status/network.js:428
#: ../js/ui/status/network.js:465
msgid "Disconnecting"
msgstr "Desconectando"
#: ../js/ui/status/network.js:434 ../js/ui/status/network.js:1254
#: ../js/ui/status/network.js:471 ../js/ui/status/network.js:1301
msgid "Connecting"
msgstr "Conectando"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:437
#: ../js/ui/status/network.js:474
msgid "Authentication required"
msgstr "Autenticación requerida"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */
#: ../js/ui/status/network.js:445
#: ../js/ui/status/network.js:482
msgid "Firmware missing"
msgstr "Falta el «firmware»"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage */
#: ../js/ui/status/network.js:449
#: ../js/ui/status/network.js:486
msgid "Unavailable"
msgstr "No disponible"
#: ../js/ui/status/network.js:451 ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:488 ../js/ui/status/network.js:1695
msgid "Connection failed"
msgstr "Falló la conexión"
#: ../js/ui/status/network.js:467
#: ../js/ui/status/network.js:504
msgid "Wired Settings"
msgstr "Configuración de Wi-Fi"
#: ../js/ui/status/network.js:509 ../js/ui/status/network.js:587
#: ../js/ui/status/network.js:546 ../js/ui/status/network.js:624
msgid "Mobile Broadband Settings"
msgstr "Configuración de banda ancha móvil"
#: ../js/ui/status/network.js:551 ../js/ui/status/network.js:1258
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1305
msgid "Hardware Disabled"
msgstr "Hardware desactivado"
#: ../js/ui/status/network.js:595
#: ../js/ui/status/network.js:632
msgid "Use as Internet connection"
msgstr "Usar como conexión a Internet"
#: ../js/ui/status/network.js:776
#: ../js/ui/status/network.js:813
msgid "Airplane Mode is On"
msgstr "El modo avión está activado"
#: ../js/ui/status/network.js:777
#: ../js/ui/status/network.js:814
msgid "Wi-Fi is disabled when airplane mode is on."
msgstr "La Wi-Fi se desactiva cuando se activa el modo avión."
#: ../js/ui/status/network.js:778
#: ../js/ui/status/network.js:815
msgid "Turn Off Airplane Mode"
msgstr "Apagar el modo avión"
#: ../js/ui/status/network.js:787
#: ../js/ui/status/network.js:824
msgid "Wi-Fi is Off"
msgstr "La Wi-Fi está desactivada"
#: ../js/ui/status/network.js:788
#: ../js/ui/status/network.js:825
msgid "Wi-Fi needs to be turned on in order to connect to a network."
msgstr "Se debe activar la Wi-Fi para poder conectarse a la red."
#: ../js/ui/status/network.js:789
#: ../js/ui/status/network.js:826
msgid "Turn On Wi-Fi"
msgstr "Activar la Wi-Fi"
#: ../js/ui/status/network.js:814
#: ../js/ui/status/network.js:851
msgid "Wi-Fi Networks"
msgstr "Redes Wi-Fi"
#: ../js/ui/status/network.js:816
#: ../js/ui/status/network.js:853
msgid "Select a network"
msgstr "Seleccionar una red"
#: ../js/ui/status/network.js:845
#: ../js/ui/status/network.js:882
msgid "No Networks"
msgstr "No hay redes"
#: ../js/ui/status/network.js:866 ../js/ui/status/rfkill.js:112
#: ../js/ui/status/network.js:903 ../js/ui/status/rfkill.js:112
msgid "Use hardware switch to turn off"
msgstr "Usar el interruptor hardware para apagar"
#: ../js/ui/status/network.js:1136
#: ../js/ui/status/network.js:1173
msgid "Select Network"
msgstr "Seleccionar red"
#: ../js/ui/status/network.js:1142
#: ../js/ui/status/network.js:1179
msgid "Wi-Fi Settings"
msgstr "Configuración de Wi-Fi"
#: ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1281
msgid "Turn On"
msgstr "Enceder"
#: ../js/ui/status/network.js:1251
#: ../js/ui/status/network.js:1298
msgid "Hotspot Active"
msgstr "Punto de acceso activo"
#: ../js/ui/status/network.js:1362
#: ../js/ui/status/network.js:1409
msgid "connecting..."
msgstr "conectando…"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:1365
#: ../js/ui/status/network.js:1412
msgid "authentication required"
msgstr "se necesita autenticación"
#: ../js/ui/status/network.js:1367
#: ../js/ui/status/network.js:1414
msgid "connection failed"
msgstr "falló la conexión"
#: ../js/ui/status/network.js:1433 ../js/ui/status/rfkill.js:89
#: ../js/ui/status/network.js:1480 ../js/ui/status/rfkill.js:89
msgid "Network Settings"
msgstr "Configuración de la red"
#: ../js/ui/status/network.js:1435
#: ../js/ui/status/network.js:1482
msgid "VPN Settings"
msgstr "Configuración de VPN"
#: ../js/ui/status/network.js:1454
#: ../js/ui/status/network.js:1501
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1607
#: ../js/ui/status/network.js:1656
msgid "Network Manager"
msgstr "Gestor de la red"
#: ../js/ui/status/network.js:1647
#: ../js/ui/status/network.js:1696
msgid "Activation of network connection failed"
msgstr "Falló la activación de la conexión de red"
@ -1704,11 +1717,11 @@ msgstr "Iniciar sesión como otro usuario"
msgid "Unlock Window"
msgstr "Desbloquear ventana"
#: ../js/ui/viewSelector.js:100
#: ../js/ui/viewSelector.js:233
msgid "Applications"
msgstr "Aplicaciones"
#: ../js/ui/viewSelector.js:104
#: ../js/ui/viewSelector.js:237
msgid "Search"
msgstr "Buscar"
@ -1717,22 +1730,22 @@ msgstr "Buscar"
msgid "“%s” is ready"
msgstr "«%s» está preparado"
#: ../js/ui/windowManager.js:57
#: ../js/ui/windowManager.js:58
msgid "Do you want to keep these display settings?"
msgstr "¿Quiere mantener esta configuración de la pantalla?"
#. Translators: this and the following message should be limited in lenght,
#. to avoid ellipsizing the labels.
#. */
#: ../js/ui/windowManager.js:76
#: ../js/ui/windowManager.js:77
msgid "Revert Settings"
msgstr "Revertir configuración"
#: ../js/ui/windowManager.js:80
#: ../js/ui/windowManager.js:81
msgid "Keep Changes"
msgstr "Mantener cambios"
#: ../js/ui/windowManager.js:99
#: ../js/ui/windowManager.js:100
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"

796
po/eu.po

File diff suppressed because it is too large Load Diff

871
po/fr.po

File diff suppressed because it is too large Load Diff

882
po/fur.po

File diff suppressed because it is too large Load Diff

618
po/gl.po

File diff suppressed because it is too large Load Diff

2254
po/gu.po

File diff suppressed because it is too large Load Diff

375
po/he.po

File diff suppressed because it is too large Load Diff

218
po/lt.po
View File

@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2014-06-22 07:30+0000\n"
"PO-Revision-Date: 2014-06-22 15:56+0300\n"
"POT-Creation-Date: 2014-07-25 19:35+0000\n"
"PO-Revision-Date: 2014-07-25 22:53+0300\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
@ -316,19 +316,23 @@ msgstr "Darbalaukiai tik pagrindiniame monitoriuje"
msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr "Atidėti fokuso pakeitimus pelei iki žymiklis nustos judėti"
#: ../js/extensionPrefs/main.js:125
#: ../data/org.gnome.Shell.PortalHelper.desktop.in.h:1
msgid "Captive Portal"
msgstr "Pagavimo portalas"
#: ../js/extensionPrefs/main.js:127
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Kilo klaida įkeliant %s nustatymų dialogą:"
#: ../js/extensionPrefs/main.js:157
#: ../js/extensionPrefs/main.js:159
msgid "GNOME Shell Extensions"
msgstr "GNOME Shell plėtiniai"
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:136
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:142
#: ../js/ui/components/polkitAgent.js:166 ../js/ui/endSessionDialog.js:429
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/network.js:878
#: ../js/ui/status/network.js:915
msgid "Cancel"
msgstr "Atsisakyti"
@ -359,8 +363,8 @@ msgstr "Nėra sąraše?"
msgid "(e.g., user or %s)"
msgstr "(pvz., naudotojas arba %s)"
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:262
#: ../js/ui/components/networkAgent.js:280
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:286
msgid "Username: "
msgstr "Naudotojo vardas: "
@ -389,6 +393,11 @@ msgstr "Nepavyko perskaityti komandos:"
msgid "Execution of “%s” failed:"
msgstr "Nepavyko įvykdyti „%s“:"
#: ../js/portalHelper/main.js:84
#| msgid "Authentication Required"
msgid "Web Authentication Redirect"
msgstr "Reikia patvirtinti tapatybę internete"
#: ../js/ui/appDisplay.js:641
msgid "Frequently used applications will appear here"
msgstr "Čia bus matomos dažnai naudojamos programos"
@ -401,33 +410,33 @@ msgstr "Dažnai naudojamos"
msgid "All"
msgstr "Visos"
#: ../js/ui/appDisplay.js:1569
#: ../js/ui/appDisplay.js:1631
msgid "New Window"
msgstr "Naujas langas"
#: ../js/ui/appDisplay.js:1591 ../js/ui/dash.js:285
#: ../js/ui/appDisplay.js:1653 ../js/ui/dash.js:285
msgid "Remove from Favorites"
msgstr "Pašalinti iš mėgstamų"
#: ../js/ui/appDisplay.js:1597
#: ../js/ui/appDisplay.js:1659
msgid "Add to Favorites"
msgstr "Pridėti prie mėgstamų"
#: ../js/ui/appDisplay.js:1606
#: ../js/ui/appDisplay.js:1668
msgid "Show Details"
msgstr "Rodyti detalią informaciją"
#: ../js/ui/appFavorites.js:87
#: ../js/ui/appFavorites.js:122
#, javascript-format
msgid "%s has been added to your favorites."
msgstr "%s pridėta prie jūsų mėgstamų."
#: ../js/ui/appFavorites.js:121
#: ../js/ui/appFavorites.js:156
#, javascript-format
msgid "%s has been removed from your favorites."
msgstr "%s pašalinta iš jūsų mėgstamų."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:810
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:814
#: ../js/ui/status/system.js:337
msgid "Settings"
msgstr "Nustatymai"
@ -561,35 +570,35 @@ msgid "Next month"
msgstr "Kitas mėnuo"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:775
#: ../js/ui/calendar.js:785
msgid "Nothing Scheduled"
msgstr "Nieko nesuplanuota"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:793
#: ../js/ui/calendar.js:803
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %B %d d."
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:796
#: ../js/ui/calendar.js:806
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %Y m. %B %d d."
#: ../js/ui/calendar.js:807
#: ../js/ui/calendar.js:817
msgid "Today"
msgstr "Šiandien"
#: ../js/ui/calendar.js:811
#: ../js/ui/calendar.js:821
msgid "Tomorrow"
msgstr "Rytoj"
#: ../js/ui/calendar.js:822
#: ../js/ui/calendar.js:832
msgid "This week"
msgstr "Šią savaitę"
#: ../js/ui/calendar.js:830
#: ../js/ui/calendar.js:840
msgid "Next week"
msgstr "Kitą savaitę"
@ -622,40 +631,40 @@ msgstr "Slaptažodis:"
msgid "Type again:"
msgstr "Įveskite dar kartą:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:240
#: ../js/ui/status/network.js:322 ../js/ui/status/network.js:881
#: ../js/ui/components/networkAgent.js:137 ../js/ui/status/network.js:277
#: ../js/ui/status/network.js:359 ../js/ui/status/network.js:918
msgid "Connect"
msgstr "Prisijungti"
#: ../js/ui/components/networkAgent.js:224
#: ../js/ui/components/networkAgent.js:236
#: ../js/ui/components/networkAgent.js:264
#: ../js/ui/components/networkAgent.js:284
#: ../js/ui/components/networkAgent.js:294
#: ../js/ui/components/networkAgent.js:230
#: ../js/ui/components/networkAgent.js:242
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:290
#: ../js/ui/components/networkAgent.js:300
msgid "Password: "
msgstr "Slaptažodis: "
#: ../js/ui/components/networkAgent.js:229
#: ../js/ui/components/networkAgent.js:235
msgid "Key: "
msgstr "Raktas: "
#: ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:274
msgid "Identity: "
msgstr "Tapatybė: "
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:276
msgid "Private key password: "
msgstr "Privataus rakto slaptažodis: "
#: ../js/ui/components/networkAgent.js:282
#: ../js/ui/components/networkAgent.js:288
msgid "Service: "
msgstr "Tarnyba: "
#: ../js/ui/components/networkAgent.js:311
#: ../js/ui/components/networkAgent.js:317
msgid "Authentication required by wireless network"
msgstr "Belaidžiam tinklui reikia patvirtinti tapatybę"
#: ../js/ui/components/networkAgent.js:312
#: ../js/ui/components/networkAgent.js:318
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -664,35 +673,35 @@ msgstr ""
"Slaptažodžiai arba šifravimo raktai yra būtini priėjimui prie belaidžio "
"tinklo „%s“."
#: ../js/ui/components/networkAgent.js:316
#: ../js/ui/components/networkAgent.js:322
msgid "Wired 802.1X authentication"
msgstr "Laidinis 802.1X tapatybės patvirtinimas"
#: ../js/ui/components/networkAgent.js:318
#: ../js/ui/components/networkAgent.js:324
msgid "Network name: "
msgstr "Tinklo vardas: "
#: ../js/ui/components/networkAgent.js:323
#: ../js/ui/components/networkAgent.js:329
msgid "DSL authentication"
msgstr "DSL tapatybės patvirtinimas"
#: ../js/ui/components/networkAgent.js:330
#: ../js/ui/components/networkAgent.js:336
msgid "PIN code required"
msgstr "Reikalingas PIN kodas"
#: ../js/ui/components/networkAgent.js:331
#: ../js/ui/components/networkAgent.js:337
msgid "PIN code is needed for the mobile broadband device"
msgstr "Reikalingas PIN kodas mobiliajam plačiajuosčiam įrenginiui"
#: ../js/ui/components/networkAgent.js:332
#: ../js/ui/components/networkAgent.js:338
msgid "PIN: "
msgstr "PIN: "
#: ../js/ui/components/networkAgent.js:338
#: ../js/ui/components/networkAgent.js:344
msgid "Mobile broadband network password"
msgstr "Mobiliojo plačiajuosčio tinklo slaptažodis"
#: ../js/ui/components/networkAgent.js:339
#: ../js/ui/components/networkAgent.js:345
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "Būtinas slaptažodis norint prisijungti prie „%s“."
@ -990,7 +999,7 @@ msgstr "Rodyti paskyrą"
msgid "Unknown reason"
msgstr "Nežinoma priežastis"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:229
msgid "Windows"
msgstr "Langai"
@ -1166,7 +1175,7 @@ msgstr "Įdiegti"
msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Parsiųsti ir įdiegti „%s“ iš extensions.gnome.org?"
#: ../js/ui/keyboard.js:645 ../js/ui/status/keyboard.js:339
#: ../js/ui/keyboard.js:653 ../js/ui/status/keyboard.js:339
msgid "Keyboard"
msgstr "Klaviatūra"
@ -1198,7 +1207,7 @@ msgstr "Įjungta"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:719 ../js/ui/status/location.js:164
#: ../js/ui/status/network.js:555 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/status/network.js:592 ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Išjungta"
@ -1258,7 +1267,7 @@ msgstr "Pranešimų juosta"
msgid "System Information"
msgstr "Sistemos informacija"
#: ../js/ui/notificationDaemon.js:516 ../src/shell-app.c:425
#: ../js/ui/notificationDaemon.js:513 ../src/shell-app.c:425
msgctxt "program"
msgid "Unknown"
msgstr "Nežinoma"
@ -1287,32 +1296,37 @@ msgstr "Apžvalga"
msgid "Type to search…"
msgstr "Rašykite, ko ieškote…"
#: ../js/ui/panel.js:516
#: ../js/ui/panel.js:515
msgid "Quit"
msgstr "Užverti"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". */
#: ../js/ui/panel.js:568
#: ../js/ui/panel.js:567
msgid "Activities"
msgstr "Apžvalga"
#: ../js/ui/panel.js:915
#: ../js/ui/panel.js:919
msgid "Top Bar"
msgstr "Viršutinė juosta"
#: ../js/ui/popupMenu.js:279
#: ../js/ui/popupMenu.js:283
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:74
#: ../js/ui/runDialog.js:70
msgid "Enter a Command"
msgstr "Įveskite komandą"
#: ../js/ui/runDialog.js:114 ../js/ui/windowMenu.js:120
#: ../js/ui/runDialog.js:110 ../js/ui/windowMenu.js:120
msgid "Close"
msgstr "Užverti"
#: ../js/ui/runDialog.js:273
#| msgid "Estimating…"
msgid "Restarting…"
msgstr "Perleidžiama…"
#. Translators: This is a time format for a date in
#. long format */
#: ../js/ui/screenShield.js:88
@ -1343,11 +1357,11 @@ msgstr "Nepavyksta užrakinti"
msgid "Lock was blocked by an application"
msgstr "Programa užblokavo užrakinimą"
#: ../js/ui/search.js:606
#: ../js/ui/search.js:614
msgid "Searching…"
msgstr "Ieškoma…"
#: ../js/ui/search.js:652
#: ../js/ui/search.js:660
msgid "No results."
msgstr "Nerasta atitikmenų."
@ -1423,9 +1437,9 @@ msgstr "Didelis tekstas"
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:151
#: ../js/ui/status/network.js:323 ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1345 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:178
#: ../js/ui/status/network.js:360 ../js/ui/status/network.js:1281
#: ../js/ui/status/network.js:1392 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/rfkill.js:114
msgid "Turn Off"
msgstr "Išjungti"
@ -1442,7 +1456,7 @@ msgstr[0] "%d prijungtas įrenginys"
msgstr[1] "%d prijungti įrenginiai"
msgstr[2] "%d prijungtų įrenginių"
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1262
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1309
msgid "Not Connected"
msgstr "Atsijungta"
@ -1470,156 +1484,156 @@ msgstr "Įjungti"
msgid "In Use"
msgstr "Naudojama"
#: ../js/ui/status/network.js:74
#: ../js/ui/status/network.js:101
msgid "<unknown>"
msgstr "<nežinoma>"
#: ../js/ui/status/network.js:420 ../js/ui/status/network.js:1260
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:457 ../js/ui/status/network.js:1307
#: ../js/ui/status/network.js:1511
msgid "Off"
msgstr "Išjungta"
#: ../js/ui/status/network.js:422
#: ../js/ui/status/network.js:459
msgid "Connected"
msgstr "Prisijungta"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu) */
#: ../js/ui/status/network.js:426
#: ../js/ui/status/network.js:463
msgid "Unmanaged"
msgstr "Nevaldomas"
#: ../js/ui/status/network.js:428
#: ../js/ui/status/network.js:465
msgid "Disconnecting"
msgstr "Atsijungiama"
#: ../js/ui/status/network.js:434 ../js/ui/status/network.js:1254
#: ../js/ui/status/network.js:471 ../js/ui/status/network.js:1301
msgid "Connecting"
msgstr "Jungiamasi"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:437
#: ../js/ui/status/network.js:474
msgid "Authentication required"
msgstr "Reikia patvirtinti tapatybę"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */
#: ../js/ui/status/network.js:445
#: ../js/ui/status/network.js:482
msgid "Firmware missing"
msgstr "Trūksta integruotos programinės įrangos (firmware)"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage */
#: ../js/ui/status/network.js:449
#: ../js/ui/status/network.js:486
msgid "Unavailable"
msgstr "Nepasiekiamas"
#: ../js/ui/status/network.js:451 ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:488 ../js/ui/status/network.js:1695
msgid "Connection failed"
msgstr "Nepavyko prisijungti"
#: ../js/ui/status/network.js:467
#: ../js/ui/status/network.js:504
msgid "Wired Settings"
msgstr "Laidinio ryšio nustatymai"
#: ../js/ui/status/network.js:509 ../js/ui/status/network.js:587
#: ../js/ui/status/network.js:546 ../js/ui/status/network.js:624
msgid "Mobile Broadband Settings"
msgstr "Mobiliojo plačiajuosčio tinklo nustatymai"
#: ../js/ui/status/network.js:551 ../js/ui/status/network.js:1258
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1305
msgid "Hardware Disabled"
msgstr "Aparatinė įranga išjungta"
#: ../js/ui/status/network.js:595
#: ../js/ui/status/network.js:632
msgid "Use as Internet connection"
msgstr "Naudoti kaip interneto ryšį"
#: ../js/ui/status/network.js:776
#: ../js/ui/status/network.js:813
msgid "Airplane Mode is On"
msgstr "Skrydžio veiksena įjungta"
#: ../js/ui/status/network.js:777
#: ../js/ui/status/network.js:814
msgid "Wi-Fi is disabled when airplane mode is on."
msgstr "Belaidis ryšys yra išjungta skrydžio veiksenoje."
#: ../js/ui/status/network.js:778
#: ../js/ui/status/network.js:815
msgid "Turn Off Airplane Mode"
msgstr "Išjungti skrydžio veikseną"
#: ../js/ui/status/network.js:787
#: ../js/ui/status/network.js:824
msgid "Wi-Fi is Off"
msgstr "Belaidžio ryšys išjungtas"
#: ../js/ui/status/network.js:788
#: ../js/ui/status/network.js:825
msgid "Wi-Fi needs to be turned on in order to connect to a network."
msgstr "Norint prisijungti prie tinklo reikia įjungti belaidį ryšį."
#: ../js/ui/status/network.js:789
#: ../js/ui/status/network.js:826
msgid "Turn On Wi-Fi"
msgstr "Įjungti belaidį ryšį"
#: ../js/ui/status/network.js:814
#: ../js/ui/status/network.js:851
msgid "Wi-Fi Networks"
msgstr "Wi-Fi tinklai"
#: ../js/ui/status/network.js:816
#: ../js/ui/status/network.js:853
msgid "Select a network"
msgstr "Pasirinkite tinklą"
#: ../js/ui/status/network.js:845
#: ../js/ui/status/network.js:882
msgid "No Networks"
msgstr "Nėra tinklų"
#: ../js/ui/status/network.js:866 ../js/ui/status/rfkill.js:112
#: ../js/ui/status/network.js:903 ../js/ui/status/rfkill.js:112
msgid "Use hardware switch to turn off"
msgstr "Išjungimui naudoti aparatinį jungiklį"
#: ../js/ui/status/network.js:1136
#: ../js/ui/status/network.js:1173
msgid "Select Network"
msgstr "Pasirinkite tinklą"
#: ../js/ui/status/network.js:1142
#: ../js/ui/status/network.js:1179
msgid "Wi-Fi Settings"
msgstr "Belaidžio ryšio nustatymai"
#: ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1281
msgid "Turn On"
msgstr "Įjungti"
#: ../js/ui/status/network.js:1251
#: ../js/ui/status/network.js:1298
msgid "Hotspot Active"
msgstr "Prieigos taškas aktyvus"
#: ../js/ui/status/network.js:1362
#: ../js/ui/status/network.js:1409
msgid "connecting..."
msgstr "jungiamasi..."
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:1365
#: ../js/ui/status/network.js:1412
msgid "authentication required"
msgstr "reikia patvirtinti tapatybę"
#: ../js/ui/status/network.js:1367
#: ../js/ui/status/network.js:1414
msgid "connection failed"
msgstr "nepavyko prisijungti"
#: ../js/ui/status/network.js:1433 ../js/ui/status/rfkill.js:89
#: ../js/ui/status/network.js:1480 ../js/ui/status/rfkill.js:89
msgid "Network Settings"
msgstr "Tinklo nustatymai"
#: ../js/ui/status/network.js:1435
#: ../js/ui/status/network.js:1482
msgid "VPN Settings"
msgstr "VPN nustatymai"
#: ../js/ui/status/network.js:1454
#: ../js/ui/status/network.js:1501
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1607
#: ../js/ui/status/network.js:1656
msgid "Network Manager"
msgstr "Tinklo valdymas"
#: ../js/ui/status/network.js:1647
#: ../js/ui/status/network.js:1696
msgid "Activation of network connection failed"
msgstr "Tinklo ryšio nepavyko aktyvuoti"
@ -1701,11 +1715,11 @@ msgstr "Prisijungti kitu naudotoju"
msgid "Unlock Window"
msgstr "Atrakinimo langas"
#: ../js/ui/viewSelector.js:100
#: ../js/ui/viewSelector.js:233
msgid "Applications"
msgstr "Programos"
#: ../js/ui/viewSelector.js:104
#: ../js/ui/viewSelector.js:237
msgid "Search"
msgstr "Ieškoti"
@ -1714,22 +1728,22 @@ msgstr "Ieškoti"
msgid "“%s” is ready"
msgstr "„%s“ yra pasirengusi"
#: ../js/ui/windowManager.js:57
#: ../js/ui/windowManager.js:58
msgid "Do you want to keep these display settings?"
msgstr "Ar nori įrašyti šiuos vaizduoklio nustatymus?"
#. Translators: this and the following message should be limited in lenght,
#. to avoid ellipsizing the labels.
#. */
#: ../js/ui/windowManager.js:76
#: ../js/ui/windowManager.js:77
msgid "Revert Settings"
msgstr "Grąžinti nustatymus"
#: ../js/ui/windowManager.js:80
#: ../js/ui/windowManager.js:81
msgid "Keep Changes"
msgstr "Įrašyti pakeitimus"
#: ../js/ui/windowManager.js:99
#: ../js/ui/windowManager.js:100
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"

540
po/nb.po

File diff suppressed because it is too large Load Diff

1018
po/nl.po

File diff suppressed because it is too large Load Diff

2324
po/or.po

File diff suppressed because it is too large Load Diff

840
po/pa.po

File diff suppressed because it is too large Load Diff

View File

@ -21,8 +21,8 @@ msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2014-06-03 07:28+0000\n"
"PO-Revision-Date: 2014-06-03 10:26-0300\n"
"POT-Creation-Date: 2014-07-18 07:33+0000\n"
"PO-Revision-Date: 2014-07-18 13:24-0300\n"
"Last-Translator: Enrico Nicoletto <liverig@gmail.com>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
@ -139,18 +139,27 @@ msgstr ""
"área de favoritos."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:9
msgid "App Picker View"
msgstr "Visualização do seletor de aplicativos"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:10
msgid "Index of the currently selected view in the application picker."
msgstr ""
"Índice da visualização atualmente selecionada no seletor de aplicativos."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:11
msgid "History for command (Alt-F2) dialog"
msgstr "Histórico do diálogo de comandos (Alt-F2)"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:10
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
msgid "History for the looking glass dialog"
msgstr "Histórico do diálogo do shell looking glass"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:11
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
msgid "Always show the 'Log out' menu item in the user menu."
msgstr "Sempre mostrar o item de menu \"Encerrar sessão\" no menu de usuário."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:12
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
msgid ""
"This key overrides the automatic hiding of the 'Log out' menu item in single-"
"user, single-session situations."
@ -159,14 +168,14 @@ msgstr ""
"sessão\" quando houver somente um usuário, em situações de somente uma "
"sessão."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:13
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
msgid ""
"Whether to remember password for mounting encrypted or remote filesystems"
msgstr ""
"Se lembra ou não as senhas para montar sistemas de arquivos criptografados "
"ou remotos"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:14
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
msgid ""
"The shell will request a password when an encrypted device or a remote "
"filesystem is mounted. If the password can be saved for future use a "
@ -178,70 +187,78 @@ msgstr ""
"posterior, a caixa de seleção 'Lembrar senha' estará presente. Esta chave "
"ajusta o estado padrão da caixa de seleção."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:15
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
msgid "Show the week date in the calendar"
msgstr "Mostrar o número da semana na agenda"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:16
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
msgid "If true, display the ISO week date in the calendar."
msgstr "Se verdadeiro, exibe o número da semana na agenda."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:17
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
msgid "Keybinding to open the application menu"
msgstr "Atalho de teclado para abrir um menu de aplicativo"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:18
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
msgid "Keybinding to open the application menu."
msgstr "Atalho de teclado para abrir um menu de aplicativo."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:19
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
msgid "Keybinding to open the \"Show Applications\" view"
msgstr "Atalho de teclado para abrir a visualização \"Mostrar aplicativos\""
#: ../data/org.gnome.shell.gschema.xml.in.in.h:20
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
msgid ""
"Keybinding to open the \"Show Applications\" view of the Activities Overview."
msgstr ""
"Atalho de teclado para abrir a visualização \"Mostrar aplicativos\" do "
"panorama de atividades."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:21
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
msgid "Keybinding to open the overview"
msgstr "Atalho de teclado para abrir o panorama"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:22
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
msgid "Keybinding to open the Activities Overview."
msgstr "Atalho de teclado para abrir o panorama de atividades."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:23
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
msgid "Keybinding to toggle the visibility of the message tray"
msgstr "Atalho de teclado para alternar a visibilidade da área de notificação"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:24
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
msgid "Keybinding to toggle the visibility of the message tray."
msgstr "Atalho de teclado para alternar a visibilidade da área de notificação."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:25
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
msgid "Keybinding to focus the active notification"
msgstr "Atalho de teclado para ativar a notificação ativa"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:26
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
msgid "Keybinding to focus the active notification."
msgstr "Atalho de teclado para ativar a notificação ativa."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:27
# Tween pode significar uma contração de Between ou se referir a um termo "in-between" usado em animação gráfica. -- Enrico
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
msgid ""
"Keybinding that pauses and resumes all running tweens, for debugging purposes"
msgstr ""
"Atalho de teclado que pausa e continua todos os intermediários em execução, "
"a fim de depuração"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
msgid "Which keyboard to use"
msgstr "Qual teclado usar"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:28
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
msgid "The type of keyboard to use."
msgstr "O tipo do teclado para usar."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
msgid "The maximum accuracy level of location."
msgstr "O nível máximo de precisão de local."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
msgid ""
"Configures the maximum level of location accuracy applications are allowed "
"to see. Valid options are 'off' (disable location tracking), 'country', "
@ -259,11 +276,24 @@ msgstr ""
"recursos de rede (apesar de na melhor hipótese usarem precisão à nível de "
"rua)."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:31
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
msgid "Limit switcher to current workspace."
msgstr "Limitar o alternador ao espaço de trabalho atual."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
msgid ""
"If true, only applications that have windows on the current workspace are "
"shown in the switcher. Otherwise, all applications are included."
msgstr ""
"Se verdadeiro, o alternador mostrará somente os aplicativos que possuem "
"janelas no espaço de trabalho atual. Caso contrário, todos os aplicativos "
"serão incluídos."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
msgid "The application icon mode."
msgstr "O modo ícone do aplicativo."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:32
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
msgid ""
"Configures how the windows are shown in the switcher. Valid possibilities "
"are 'thumbnail-only' (shows a thumbnail of the window), 'app-icon-"
@ -273,48 +303,59 @@ msgstr ""
"válidas são 'thumbnail-only' (mostra uma miniatura da janela), 'app-icon-"
"only' (mostra apenas o ícone do aplicativo) ou 'both'."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:33
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
msgid ""
"If true, only windows from the current workspace are shown in the switcher. "
"Otherwise, all windows are included."
msgstr ""
"Se verdadeiro, o alternador mostrará somente as janelas do espaço de "
"trabalho atual. Caso contrário, todos as janelas serão incluídas."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:39
msgid "Attach modal dialog to the parent window"
msgstr "Anexar diálogo modal à janela pai"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:34
#: ../data/org.gnome.shell.gschema.xml.in.in.h:40
msgid ""
"This key overrides the key in org.gnome.mutter when running GNOME Shell."
msgstr ""
"Esta chave sobrescreve a chave em org.gnome.mutter ao executar o Shell do "
"GNOME."
#: ../data/org.gnome.shell.gschema.xml.in.in.h:35
#: ../data/org.gnome.shell.gschema.xml.in.in.h:41
msgid "Enable edge tiling when dropping windows on screen edges"
msgstr ""
"Habilitar contorno ladrilhado ao arrastar janelas sobre as bordas da tela"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:36
#: ../data/org.gnome.shell.gschema.xml.in.in.h:42
msgid "Workspaces are managed dynamically"
msgstr "Espaços de trabalho são gerenciados dinamicamente"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:37
#: ../data/org.gnome.shell.gschema.xml.in.in.h:43
msgid "Workspaces only on primary monitor"
msgstr "Espaços de trabalho apenas no monitor primário"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:38
#: ../data/org.gnome.shell.gschema.xml.in.in.h:44
msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr "Atrasar foco altera o modo do mouse até o ponteiro parar de mover"
#: ../data/org.gnome.Shell.PortalHelper.desktop.in.h:1
msgid "Captive Portal"
msgstr "Portal cativo"
#: ../js/extensionPrefs/main.js:125
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Ocorreu um erro ao carregar o dialogo de preferências para %s:"
#: ../js/extensionPrefs/main.js:157
#| msgid "Configure GNOME Shell Extensions"
msgid "GNOME Shell Extensions"
msgstr "Extensões do Shell do GNOME"
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:136
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:142
#: ../js/ui/components/polkitAgent.js:166 ../js/ui/endSessionDialog.js:429
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/network.js:878
#: ../js/ui/status/network.js:915
msgid "Cancel"
msgstr "Cancelar"
@ -345,8 +386,8 @@ msgstr "Não está listado?"
msgid "(e.g., user or %s)"
msgstr "(ex.: usuário ou %s)"
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:262
#: ../js/ui/components/networkAgent.js:280
#: ../js/gdm/loginDialog.js:619 ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:286
msgid "Username: "
msgstr "Nome de usuário: "
@ -375,31 +416,35 @@ msgstr "Não foi possível analisar comando:"
msgid "Execution of “%s” failed:"
msgstr "A execução de \"%s\" falhou:"
#: ../js/ui/appDisplay.js:640
#: ../js/portalHelper/main.js:84
msgid "Web Authentication Redirect"
msgstr "Redirecionamento para autenticação web"
#: ../js/ui/appDisplay.js:641
msgid "Frequently used applications will appear here"
msgstr "Aplicativos usados frequentemente vão aparecer aqui"
#: ../js/ui/appDisplay.js:751
#: ../js/ui/appDisplay.js:752
msgid "Frequent"
msgstr "Frequente"
#: ../js/ui/appDisplay.js:758
#: ../js/ui/appDisplay.js:759
msgid "All"
msgstr "Todos"
#: ../js/ui/appDisplay.js:1571
#: ../js/ui/appDisplay.js:1613
msgid "New Window"
msgstr "Nova janela"
#: ../js/ui/appDisplay.js:1593 ../js/ui/dash.js:285
#: ../js/ui/appDisplay.js:1635 ../js/ui/dash.js:285
msgid "Remove from Favorites"
msgstr "Remover dos favoritos"
#: ../js/ui/appDisplay.js:1599
#: ../js/ui/appDisplay.js:1641
msgid "Add to Favorites"
msgstr "Adicionar aos favoritos"
#: ../js/ui/appDisplay.js:1608
#: ../js/ui/appDisplay.js:1650
msgid "Show Details"
msgstr "Mostrar detalhes"
@ -413,7 +458,7 @@ msgstr "%s foi adicionado aos seus favoritos."
msgid "%s has been removed from your favorites."
msgstr "%s foi removido dos seus favoritos."
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:810
#: ../js/ui/backgroundMenu.js:19 ../js/ui/panel.js:809
#: ../js/ui/status/system.js:337
msgid "Settings"
msgstr "Configurações"
@ -547,35 +592,35 @@ msgid "Next month"
msgstr "Próximo mês"
#. Translators: Text to show if there are no events */
#: ../js/ui/calendar.js:775
#: ../js/ui/calendar.js:785
msgid "Nothing Scheduled"
msgstr "Nada agendado"
#. Translators: Shown on calendar heading when selected day occurs on current year */
#: ../js/ui/calendar.js:793
#: ../js/ui/calendar.js:803
msgctxt "calendar heading"
msgid "%A, %B %d"
msgstr "%A, %d de %B"
#. Translators: Shown on calendar heading when selected day occurs on different year */
#: ../js/ui/calendar.js:796
#: ../js/ui/calendar.js:806
msgctxt "calendar heading"
msgid "%A, %B %d, %Y"
msgstr "%A, %d de %B de %Y"
#: ../js/ui/calendar.js:807
#: ../js/ui/calendar.js:817
msgid "Today"
msgstr "Hoje"
#: ../js/ui/calendar.js:811
#: ../js/ui/calendar.js:821
msgid "Tomorrow"
msgstr "Amanhã"
#: ../js/ui/calendar.js:822
#: ../js/ui/calendar.js:832
msgid "This week"
msgstr "Esta semana"
#: ../js/ui/calendar.js:830
#: ../js/ui/calendar.js:840
msgid "Next week"
msgstr "Próxima semana"
@ -608,40 +653,40 @@ msgstr "Senha:"
msgid "Type again:"
msgstr "Digite novamente:"
#: ../js/ui/components/networkAgent.js:131 ../js/ui/status/network.js:240
#: ../js/ui/status/network.js:322 ../js/ui/status/network.js:881
#: ../js/ui/components/networkAgent.js:137 ../js/ui/status/network.js:277
#: ../js/ui/status/network.js:359 ../js/ui/status/network.js:918
msgid "Connect"
msgstr "Conectar"
#: ../js/ui/components/networkAgent.js:224
#: ../js/ui/components/networkAgent.js:236
#: ../js/ui/components/networkAgent.js:264
#: ../js/ui/components/networkAgent.js:284
#: ../js/ui/components/networkAgent.js:294
#: ../js/ui/components/networkAgent.js:230
#: ../js/ui/components/networkAgent.js:242
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:290
#: ../js/ui/components/networkAgent.js:300
msgid "Password: "
msgstr "Senha: "
#: ../js/ui/components/networkAgent.js:229
#: ../js/ui/components/networkAgent.js:235
msgid "Key: "
msgstr "Chave: "
#: ../js/ui/components/networkAgent.js:268
#: ../js/ui/components/networkAgent.js:274
msgid "Identity: "
msgstr "Identidade: "
#: ../js/ui/components/networkAgent.js:270
#: ../js/ui/components/networkAgent.js:276
msgid "Private key password: "
msgstr "Senha da chave privada: "
#: ../js/ui/components/networkAgent.js:282
#: ../js/ui/components/networkAgent.js:288
msgid "Service: "
msgstr "Serviço: "
#: ../js/ui/components/networkAgent.js:311
#: ../js/ui/components/networkAgent.js:317
msgid "Authentication required by wireless network"
msgstr "Autenticação requisitada pela rede sem fio"
#: ../js/ui/components/networkAgent.js:312
#: ../js/ui/components/networkAgent.js:318
#, javascript-format
msgid ""
"Passwords or encryption keys are required to access the wireless network "
@ -650,35 +695,35 @@ msgstr ""
"Senhas ou chaves criptografadas são necessárias para acessar a rede sem fio "
"\"%s\"."
#: ../js/ui/components/networkAgent.js:316
#: ../js/ui/components/networkAgent.js:322
msgid "Wired 802.1X authentication"
msgstr "Autenticação 802.1X cabeada"
#: ../js/ui/components/networkAgent.js:318
#: ../js/ui/components/networkAgent.js:324
msgid "Network name: "
msgstr "Nome da rede: "
#: ../js/ui/components/networkAgent.js:323
#: ../js/ui/components/networkAgent.js:329
msgid "DSL authentication"
msgstr "Autenticação DSL"
#: ../js/ui/components/networkAgent.js:330
#: ../js/ui/components/networkAgent.js:336
msgid "PIN code required"
msgstr "Código PIN requisitado"
#: ../js/ui/components/networkAgent.js:331
#: ../js/ui/components/networkAgent.js:337
msgid "PIN code is needed for the mobile broadband device"
msgstr "O código PIN é necessário para o dispositivo móvel de banda larga"
#: ../js/ui/components/networkAgent.js:332
#: ../js/ui/components/networkAgent.js:338
msgid "PIN: "
msgstr "PIN: "
#: ../js/ui/components/networkAgent.js:338
#: ../js/ui/components/networkAgent.js:344
msgid "Mobile broadband network password"
msgstr "Senha da rede de banda larga móvel"
#: ../js/ui/components/networkAgent.js:339
#: ../js/ui/components/networkAgent.js:345
#, javascript-format
msgid "A password is required to connect to “%s”."
msgstr "Uma senha é necessária para se conectar a \"%s\""
@ -976,7 +1021,7 @@ msgstr "Visualizar conta"
msgid "Unknown reason"
msgstr "Razão desconhecida"
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:96
#: ../js/ui/ctrlAltTab.js:29 ../js/ui/viewSelector.js:229
msgid "Windows"
msgstr "Janelas"
@ -988,23 +1033,23 @@ msgstr "Mostrar aplicativos"
msgid "Dash"
msgstr "Dash"
#: ../js/ui/dateMenu.js:97
#: ../js/ui/dateMenu.js:96
msgid "Open Calendar"
msgstr "Abrir agenda"
#: ../js/ui/dateMenu.js:101
#: ../js/ui/dateMenu.js:100
msgid "Open Clocks"
msgstr "Abrir relógios"
# O "&" foi inserido como "e" para versão 3.8.0 no gnome-control-center
#: ../js/ui/dateMenu.js:108
#: ../js/ui/dateMenu.js:107
msgid "Date & Time Settings"
msgstr "Configurações de data & hora"
#. Translators: This is the date format to use when the calendar popup is
#. * shown - it is shown just below the time in the shell (e.g. "Tue 9:29 AM").
#. */
#: ../js/ui/dateMenu.js:205
#: ../js/ui/dateMenu.js:204
msgid "%A %B %e, %Y"
msgstr "%A, %e de %B de %Y"
@ -1085,7 +1130,7 @@ msgstr[1] "O sistema irá reiniciar automaticamente em %d segundos."
#: ../js/ui/endSessionDialog.js:121
msgctxt "title"
msgid "Restart & Install Updates"
msgstr "Reiniciar & Instalar atualizações"
msgstr "Reiniciar & instalar atualizações"
#: ../js/ui/endSessionDialog.js:123
#, javascript-format
@ -1181,7 +1226,7 @@ msgstr "Habilitado"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:719 ../js/ui/status/location.js:164
#: ../js/ui/status/network.js:555 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/status/network.js:592 ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Desabilitado"
@ -1205,43 +1250,43 @@ msgstr "Ver fonte"
msgid "Web Page"
msgstr "Página web"
#: ../js/ui/messageTray.js:1326
#: ../js/ui/messageTray.js:1325
msgid "Open"
msgstr "Abrir"
#: ../js/ui/messageTray.js:1333
#: ../js/ui/messageTray.js:1332
msgid "Remove"
msgstr "Remover"
#: ../js/ui/messageTray.js:1630
#: ../js/ui/messageTray.js:1629
msgid "Notifications"
msgstr "Notificações"
#: ../js/ui/messageTray.js:1637
#: ../js/ui/messageTray.js:1636
msgid "Clear Messages"
msgstr "Sem mensagens"
#: ../js/ui/messageTray.js:1656
#: ../js/ui/messageTray.js:1655
msgid "Notification Settings"
msgstr "Configurações de notificação"
#: ../js/ui/messageTray.js:1709
#: ../js/ui/messageTray.js:1708
msgid "Tray Menu"
msgstr "Menu de notificação"
#: ../js/ui/messageTray.js:1926
#: ../js/ui/messageTray.js:1925
msgid "No Messages"
msgstr "Sem mensagens"
#: ../js/ui/messageTray.js:1964
#: ../js/ui/messageTray.js:1963
msgid "Message Tray"
msgstr "Área de notificação"
#: ../js/ui/messageTray.js:2967
#: ../js/ui/messageTray.js:2966
msgid "System Information"
msgstr "Informações do sistema"
#: ../js/ui/notificationDaemon.js:516 ../src/shell-app.c:425
#: ../js/ui/notificationDaemon.js:513 ../src/shell-app.c:425
msgctxt "program"
msgid "Unknown"
msgstr "Desconhecido"
@ -1269,32 +1314,37 @@ msgstr "Panorama"
msgid "Type to search…"
msgstr "Digite para pesquisar…"
#: ../js/ui/panel.js:516
#: ../js/ui/panel.js:515
msgid "Quit"
msgstr "Sair"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". */
#: ../js/ui/panel.js:568
#: ../js/ui/panel.js:567
msgid "Activities"
msgstr "Atividades"
#: ../js/ui/panel.js:915
#: ../js/ui/panel.js:914
msgid "Top Bar"
msgstr "Barra superior"
#: ../js/ui/popupMenu.js:279
#: ../js/ui/popupMenu.js:274
msgid "toggle-switch-us"
msgstr "toggle-switch-intl"
#: ../js/ui/runDialog.js:74
#: ../js/ui/runDialog.js:70
msgid "Enter a Command"
msgstr "Digite um comando"
#: ../js/ui/runDialog.js:114 ../js/ui/windowMenu.js:120
#: ../js/ui/runDialog.js:110 ../js/ui/windowMenu.js:120
msgid "Close"
msgstr "Fechar"
#: ../js/ui/runDialog.js:273
#| msgid "Estimating…"
msgid "Restarting…"
msgstr "Reiniciando…"
#. Translators: This is a time format for a date in
#. long format */
#: ../js/ui/screenShield.js:88
@ -1404,9 +1454,9 @@ msgstr "Texto grande"
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:151
#: ../js/ui/status/network.js:323 ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1345 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:178
#: ../js/ui/status/network.js:360 ../js/ui/status/network.js:1281
#: ../js/ui/status/network.js:1392 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/rfkill.js:114
msgid "Turn Off"
msgstr "Desligar"
@ -1422,7 +1472,7 @@ msgid_plural "%d Connected Devices"
msgstr[0] "%d dispositivo conectado"
msgstr[1] "%d dispositivos conectados"
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1262
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1309
msgid "Not Connected"
msgstr "Não conectado"
@ -1450,157 +1500,157 @@ msgstr "Habilitar"
msgid "In Use"
msgstr "Em uso"
#: ../js/ui/status/network.js:74
#: ../js/ui/status/network.js:101
msgid "<unknown>"
msgstr "<desconhecido>"
#: ../js/ui/status/network.js:420 ../js/ui/status/network.js:1260
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:457 ../js/ui/status/network.js:1307
#: ../js/ui/status/network.js:1511
msgid "Off"
msgstr "Off"
#: ../js/ui/status/network.js:422
#: ../js/ui/status/network.js:459
msgid "Connected"
msgstr "Conectado"
# Não gerenciável para transmitir a idéia que o Networkmanager não consegue gerenciar o dispositivo --Enrico
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu) */
#: ../js/ui/status/network.js:426
#: ../js/ui/status/network.js:463
msgid "Unmanaged"
msgstr "Não gerenciável"
#: ../js/ui/status/network.js:428
#: ../js/ui/status/network.js:465
msgid "Disconnecting"
msgstr "Desconectando"
#: ../js/ui/status/network.js:434 ../js/ui/status/network.js:1254
#: ../js/ui/status/network.js:471 ../js/ui/status/network.js:1301
msgid "Connecting"
msgstr "Conectando"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:437
#: ../js/ui/status/network.js:474
msgid "Authentication required"
msgstr "Autenticação necessária"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */
#: ../js/ui/status/network.js:445
#: ../js/ui/status/network.js:482
msgid "Firmware missing"
msgstr "Firmware em falta"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage */
#: ../js/ui/status/network.js:449
#: ../js/ui/status/network.js:486
msgid "Unavailable"
msgstr "Indisponível"
#: ../js/ui/status/network.js:451 ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:488 ../js/ui/status/network.js:1695
msgid "Connection failed"
msgstr "Falha de conexão"
#: ../js/ui/status/network.js:467
#: ../js/ui/status/network.js:504
msgid "Wired Settings"
msgstr "Configurações da rede cabeada"
#: ../js/ui/status/network.js:509 ../js/ui/status/network.js:587
#: ../js/ui/status/network.js:546 ../js/ui/status/network.js:624
msgid "Mobile Broadband Settings"
msgstr "Configurações de banda larga móvel"
#: ../js/ui/status/network.js:551 ../js/ui/status/network.js:1258
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1305
msgid "Hardware Disabled"
msgstr "Hardware desabilitado"
#: ../js/ui/status/network.js:595
#: ../js/ui/status/network.js:632
msgid "Use as Internet connection"
msgstr "Usar como conexão de Internet"
#: ../js/ui/status/network.js:776
#: ../js/ui/status/network.js:813
msgid "Airplane Mode is On"
msgstr "Modo avião ligado"
#: ../js/ui/status/network.js:777
#: ../js/ui/status/network.js:814
msgid "Wi-Fi is disabled when airplane mode is on."
msgstr "O Wi-Fi é desabilitado quando o modo avião está ligado."
#: ../js/ui/status/network.js:778
#: ../js/ui/status/network.js:815
msgid "Turn Off Airplane Mode"
msgstr "Desligar modo avião"
#: ../js/ui/status/network.js:787
#: ../js/ui/status/network.js:824
msgid "Wi-Fi is Off"
msgstr "Wi-Fi desligado"
#: ../js/ui/status/network.js:788
#: ../js/ui/status/network.js:825
msgid "Wi-Fi needs to be turned on in order to connect to a network."
msgstr "O Wi-Fi precisa ser ligado a fim de conectar-se a uma rede."
#: ../js/ui/status/network.js:789
#: ../js/ui/status/network.js:826
msgid "Turn On Wi-Fi"
msgstr "Ligar Wi-Fi"
#: ../js/ui/status/network.js:814
#: ../js/ui/status/network.js:851
msgid "Wi-Fi Networks"
msgstr "Redes Wi-Fi"
#: ../js/ui/status/network.js:816
#: ../js/ui/status/network.js:853
msgid "Select a network"
msgstr "Selecione uma rede"
#: ../js/ui/status/network.js:845
#: ../js/ui/status/network.js:882
msgid "No Networks"
msgstr "Nenhuma rede"
#: ../js/ui/status/network.js:866 ../js/ui/status/rfkill.js:112
#: ../js/ui/status/network.js:903 ../js/ui/status/rfkill.js:112
msgid "Use hardware switch to turn off"
msgstr "Usar alternador de hardware para desligar"
#: ../js/ui/status/network.js:1136
#: ../js/ui/status/network.js:1173
msgid "Select Network"
msgstr "Selecione a rede"
#: ../js/ui/status/network.js:1142
#: ../js/ui/status/network.js:1179
msgid "Wi-Fi Settings"
msgstr "Configurações de Wi-Fi"
#: ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1281
msgid "Turn On"
msgstr "Ligar"
#: ../js/ui/status/network.js:1251
#: ../js/ui/status/network.js:1298
msgid "Hotspot Active"
msgstr "Ponto de acesso ativo"
#: ../js/ui/status/network.js:1362
#: ../js/ui/status/network.js:1409
msgid "connecting..."
msgstr "conectando..."
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:1365
#: ../js/ui/status/network.js:1412
msgid "authentication required"
msgstr "autenticação necessária"
#: ../js/ui/status/network.js:1367
#: ../js/ui/status/network.js:1414
msgid "connection failed"
msgstr "conexão falhou"
#: ../js/ui/status/network.js:1433 ../js/ui/status/rfkill.js:89
#: ../js/ui/status/network.js:1480 ../js/ui/status/rfkill.js:89
msgid "Network Settings"
msgstr "Configurações de rede"
#: ../js/ui/status/network.js:1435
#: ../js/ui/status/network.js:1482
msgid "VPN Settings"
msgstr "Configurações de VPN"
#: ../js/ui/status/network.js:1454
#: ../js/ui/status/network.js:1501
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1607
#: ../js/ui/status/network.js:1656
msgid "Network Manager"
msgstr "Gerenciador de rede"
#: ../js/ui/status/network.js:1647
#: ../js/ui/status/network.js:1696
msgid "Activation of network connection failed"
msgstr "Falha ao ativar a conexão da rede"
@ -1684,11 +1734,11 @@ msgstr "Iniciar sessão como outro usuário"
msgid "Unlock Window"
msgstr "Desbloquear janela"
#: ../js/ui/viewSelector.js:100
#: ../js/ui/viewSelector.js:233
msgid "Applications"
msgstr "Aplicativos"
#: ../js/ui/viewSelector.js:104
#: ../js/ui/viewSelector.js:237
msgid "Search"
msgstr "Pesquisar"
@ -1697,22 +1747,22 @@ msgstr "Pesquisar"
msgid "“%s” is ready"
msgstr "\"%s\" está pronto"
#: ../js/ui/windowManager.js:57
#: ../js/ui/windowManager.js:58
msgid "Do you want to keep these display settings?"
msgstr "Você deseja manter essas configurações de exibição?"
#. Translators: this and the following message should be limited in lenght,
#. to avoid ellipsizing the labels.
#. */
#: ../js/ui/windowManager.js:76
#: ../js/ui/windowManager.js:77
msgid "Revert Settings"
msgstr "Reverter configurações"
#: ../js/ui/windowManager.js:80
#: ../js/ui/windowManager.js:81
msgid "Keep Changes"
msgstr "Manter alterações"
#: ../js/ui/windowManager.js:99
#: ../js/ui/windowManager.js:100
#, javascript-format
msgid "Settings changes will revert in %d second"
msgid_plural "Settings changes will revert in %d seconds"
@ -1785,19 +1835,19 @@ msgstr[1] "%u entradas"
msgid "System Sounds"
msgstr "Sons do sistema"
#: ../src/main.c:349
#: ../src/main.c:371
msgid "Print version"
msgstr "Versão de impressão"
#: ../src/main.c:355
#: ../src/main.c:377
msgid "Mode used by GDM for login screen"
msgstr "Modo usado pelo GDM para a tela de início de sessão"
#: ../src/main.c:361
#: ../src/main.c:383
msgid "Use a specific mode, e.g. \"gdm\" for login screen"
msgstr "Utilizar um modo específico, ex.: \"gdm\" para a tela de login"
#: ../src/main.c:367
#: ../src/main.c:389
msgid "List possible modes"
msgstr "Listar modos possíveis"

122
po/ru.po
View File

@ -18,17 +18,17 @@ msgstr ""
"Project-Id-Version: gnome-shell\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-"
"shell&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2014-06-25 07:31+0000\n"
"PO-Revision-Date: 2014-06-25 22:59+0400\n"
"Last-Translator: Yuri Myasoedov <ymyasoedov@yandex.ru>\n"
"POT-Creation-Date: 2014-07-08 07:32+0000\n"
"PO-Revision-Date: 2014-07-08 17:18+0300\n"
"Last-Translator: Yuri Myasoedov <omerta13@yandex.ru>\n"
"Language-Team: русский <gnome-cyr@gnome.org>\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"X-Generator: Gtranslator 2.91.6\n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Poedit 1.5.4\n"
#: ../data/50-gnome-shell-system.xml.in.h:1
msgid "System"
@ -226,10 +226,14 @@ msgstr "Комбинация клавиш для перевода фокуса
msgid "Keybinding to focus the active notification."
msgstr "Комбинация клавиш для перевода фокуса на текущее уведомление."
# tweens? пока непонятно, что это
#: ../data/org.gnome.shell.gschema.xml.in.in.h:29
#, fuzzy
msgid ""
"Keybinding that pauses and resumes all running tweens, for debugging purposes"
msgstr ""
"Комбинация клавиш, которая приостанавливает и возобновляет все запущенные "
"tweens (для отладки)"
#: ../data/org.gnome.shell.gschema.xml.in.in.h:30
msgid "Which keyboard to use"
@ -323,20 +327,23 @@ msgstr "Рабочие места только на основном монит
msgid "Delay focus changes in mouse mode until the pointer stops moving"
msgstr "Задержка изменения фокуса в режиме мыши после остановки указателя"
#: ../data/org.gnome.Shell.PortalHelper.desktop.in.h:1
msgid "Captive Portal"
msgstr "Captive-портал"
#: ../js/extensionPrefs/main.js:125
#, javascript-format
msgid "There was an error loading the preferences dialog for %s:"
msgstr "Возникла ошибка загрузки диалогового окна параметров для %s:"
#: ../js/extensionPrefs/main.js:157
#| msgid "Configure GNOME Shell Extensions"
msgid "GNOME Shell Extensions"
msgstr "Расширения GNOME Shell"
#: ../js/gdm/authPrompt.js:147 ../js/ui/components/networkAgent.js:142
#: ../js/ui/components/polkitAgent.js:166 ../js/ui/endSessionDialog.js:429
#: ../js/ui/extensionDownloader.js:195 ../js/ui/shellMountOperation.js:399
#: ../js/ui/status/network.js:878
#: ../js/ui/status/network.js:915
msgid "Cancel"
msgstr "Отмена"
@ -397,6 +404,11 @@ msgstr "Не удалось разобрать команду:"
msgid "Execution of “%s” failed:"
msgstr "Не удалось выполнить «%s»:"
#: ../js/portalHelper/main.js:84
#| msgid "Authentication Required"
msgid "Web Authentication Redirect"
msgstr "Перенаправление для проверки подлинности"
#: ../js/ui/appDisplay.js:641
msgid "Frequently used applications will appear here"
msgstr "Здесь появляются часто используемые приложения"
@ -422,7 +434,6 @@ msgid "Add to Favorites"
msgstr "Добавить в избранное"
#: ../js/ui/appDisplay.js:1607
#| msgid "Show Text"
msgid "Show Details"
msgstr "Показать подробности"
@ -633,8 +644,8 @@ msgstr "Пароль:"
msgid "Type again:"
msgstr "Введите ещё раз:"
#: ../js/ui/components/networkAgent.js:137 ../js/ui/status/network.js:240
#: ../js/ui/status/network.js:322 ../js/ui/status/network.js:881
#: ../js/ui/components/networkAgent.js:137 ../js/ui/status/network.js:277
#: ../js/ui/status/network.js:359 ../js/ui/status/network.js:918
msgid "Connect"
msgstr "Соединиться"
@ -1217,7 +1228,7 @@ msgstr "Включено"
#. translators:
#. * The device has been disabled
#: ../js/ui/lookingGlass.js:719 ../js/ui/status/location.js:164
#: ../js/ui/status/network.js:555 ../src/gvc/gvc-mixer-control.c:1830
#: ../js/ui/status/network.js:592 ../src/gvc/gvc-mixer-control.c:1830
msgid "Disabled"
msgstr "Выключено"
@ -1443,9 +1454,9 @@ msgstr "Крупный текст"
msgid "Bluetooth"
msgstr "Bluetooth"
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:151
#: ../js/ui/status/network.js:323 ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1345 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/bluetooth.js:51 ../js/ui/status/network.js:178
#: ../js/ui/status/network.js:360 ../js/ui/status/network.js:1281
#: ../js/ui/status/network.js:1392 ../js/ui/status/rfkill.js:86
#: ../js/ui/status/rfkill.js:114
msgid "Turn Off"
msgstr "Выключить"
@ -1462,7 +1473,7 @@ msgstr[0] "Подключено %d устройство"
msgstr[1] "Подключено %d устройства"
msgstr[2] "Подключено %d устройств"
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1262
#: ../js/ui/status/bluetooth.js:106 ../js/ui/status/network.js:1309
msgid "Not Connected"
msgstr "Не подключено"
@ -1490,161 +1501,156 @@ msgstr "Включить"
msgid "In Use"
msgstr "Используется"
#: ../js/ui/status/network.js:74
#: ../js/ui/status/network.js:101
msgid "<unknown>"
msgstr "<неизвестно>"
#: ../js/ui/status/network.js:420 ../js/ui/status/network.js:1260
#: ../js/ui/status/network.js:1464
#: ../js/ui/status/network.js:457 ../js/ui/status/network.js:1307
#: ../js/ui/status/network.js:1511
msgid "Off"
msgstr "Выключено"
#: ../js/ui/status/network.js:422
#: ../js/ui/status/network.js:459
msgid "Connected"
msgstr "Подключено"
#. Translators: this is for network devices that are physically present but are not
#. under NetworkManager's control (and thus cannot be used in the menu) */
#: ../js/ui/status/network.js:426
#| msgid "unmanaged"
#: ../js/ui/status/network.js:463
msgid "Unmanaged"
msgstr "Не управляется"
#: ../js/ui/status/network.js:428
#| msgid "disconnecting..."
#: ../js/ui/status/network.js:465
msgid "Disconnecting"
msgstr "Отключение"
#: ../js/ui/status/network.js:434 ../js/ui/status/network.js:1254
#: ../js/ui/status/network.js:471 ../js/ui/status/network.js:1301
msgid "Connecting"
msgstr "Подключение"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:437
#| msgid "authentication required"
#: ../js/ui/status/network.js:474
msgid "Authentication required"
msgstr "Требуется подтверждение подлинности"
#. Translators: this is for devices that require some kind of firmware or kernel
#. module, which is missing */
#: ../js/ui/status/network.js:445
#| msgid "firmware missing"
#: ../js/ui/status/network.js:482
msgid "Firmware missing"
msgstr "Отсутствует прошивка"
#. Translators: this is for a network device that cannot be activated (for example it
#. is disabled by rfkill, or it has no coverage */
#: ../js/ui/status/network.js:449
#| msgid "unavailable"
#: ../js/ui/status/network.js:486
msgid "Unavailable"
msgstr "Недоступно"
#: ../js/ui/status/network.js:451 ../js/ui/status/network.js:1646
#: ../js/ui/status/network.js:488 ../js/ui/status/network.js:1695
msgid "Connection failed"
msgstr "Сбой подключения"
#: ../js/ui/status/network.js:467
#: ../js/ui/status/network.js:504
msgid "Wired Settings"
msgstr "Параметры проводных соединений"
#: ../js/ui/status/network.js:509 ../js/ui/status/network.js:587
#: ../js/ui/status/network.js:546 ../js/ui/status/network.js:624
msgid "Mobile Broadband Settings"
msgstr "Параметры широкополосной мобильной связи"
#: ../js/ui/status/network.js:551 ../js/ui/status/network.js:1258
#: ../js/ui/status/network.js:588 ../js/ui/status/network.js:1305
msgid "Hardware Disabled"
msgstr "Оборудование выключено"
#: ../js/ui/status/network.js:595
#: ../js/ui/status/network.js:632
msgid "Use as Internet connection"
msgstr "Использовать как Интернет-соединение"
#: ../js/ui/status/network.js:776
#: ../js/ui/status/network.js:813
msgid "Airplane Mode is On"
msgstr "Включён режим авиаперелёта"
#: ../js/ui/status/network.js:777
#: ../js/ui/status/network.js:814
msgid "Wi-Fi is disabled when airplane mode is on."
msgstr "Когда включён режим авиаперелёта, адаптер Wi-Fi выключен."
#: ../js/ui/status/network.js:778
#: ../js/ui/status/network.js:815
msgid "Turn Off Airplane Mode"
msgstr "Выключить режим авиаперелёта"
#: ../js/ui/status/network.js:787
#: ../js/ui/status/network.js:824
msgid "Wi-Fi is Off"
msgstr "Wi-Fi выключен"
#: ../js/ui/status/network.js:788
#: ../js/ui/status/network.js:825
msgid "Wi-Fi needs to be turned on in order to connect to a network."
msgstr "Для подключения к сети, адаптер Wi-Fi должен быть включён."
#: ../js/ui/status/network.js:789
#: ../js/ui/status/network.js:826
msgid "Turn On Wi-Fi"
msgstr "Включить Wi-Fi"
#: ../js/ui/status/network.js:814
#: ../js/ui/status/network.js:851
msgid "Wi-Fi Networks"
msgstr "Сети Wi-Fi"
#: ../js/ui/status/network.js:816
#: ../js/ui/status/network.js:853
msgid "Select a network"
msgstr "Выберите сеть"
#: ../js/ui/status/network.js:845
#: ../js/ui/status/network.js:882
msgid "No Networks"
msgstr "Сети отсутствуют"
#: ../js/ui/status/network.js:866 ../js/ui/status/rfkill.js:112
#: ../js/ui/status/network.js:903 ../js/ui/status/rfkill.js:112
msgid "Use hardware switch to turn off"
msgstr "Используйте механический переключатель, чтобы выключить"
#: ../js/ui/status/network.js:1136
#: ../js/ui/status/network.js:1173
msgid "Select Network"
msgstr "Выбрать сеть"
#: ../js/ui/status/network.js:1142
#: ../js/ui/status/network.js:1179
msgid "Wi-Fi Settings"
msgstr "Параметры Wi-Fi"
#: ../js/ui/status/network.js:1234
#: ../js/ui/status/network.js:1281
msgid "Turn On"
msgstr "Включить"
#: ../js/ui/status/network.js:1251
#: ../js/ui/status/network.js:1298
msgid "Hotspot Active"
msgstr "Точка доступа включена"
#: ../js/ui/status/network.js:1362
#: ../js/ui/status/network.js:1409
msgid "connecting..."
msgstr "подключение…"
#. Translators: this is for network connections that require some kind of key or password */
#: ../js/ui/status/network.js:1365
#: ../js/ui/status/network.js:1412
msgid "authentication required"
msgstr "требуется подтверждение подлинности"
#: ../js/ui/status/network.js:1367
#: ../js/ui/status/network.js:1414
msgid "connection failed"
msgstr "сбой подключения"
#: ../js/ui/status/network.js:1433 ../js/ui/status/rfkill.js:89
#: ../js/ui/status/network.js:1480 ../js/ui/status/rfkill.js:89
msgid "Network Settings"
msgstr "Настроить сеть"
#: ../js/ui/status/network.js:1435
#: ../js/ui/status/network.js:1482
msgid "VPN Settings"
msgstr "Параметры VPN"
#: ../js/ui/status/network.js:1454
#: ../js/ui/status/network.js:1501
msgid "VPN"
msgstr "VPN"
#: ../js/ui/status/network.js:1607
#: ../js/ui/status/network.js:1656
msgid "Network Manager"
msgstr "Диспетчер сети"
#: ../js/ui/status/network.js:1647
#: ../js/ui/status/network.js:1696
msgid "Activation of network connection failed"
msgstr "Не удалось активировать сетевое подключение"
@ -1785,7 +1791,7 @@ msgstr "Изменить размер"
#: ../js/ui/windowMenu.js:65
msgid "Move Titlebar Onscreen"
msgstr ""
msgstr "Переместить панель заголовка на экран"
#: ../js/ui/windowMenu.js:70
msgid "Always on Top"

854
po/te.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,6 +4,8 @@ st_cflags = \
-DLIBDIR=\""$(libdir)"\" \
-DG_LOG_DOMAIN=\"St\" \
-DST_COMPILATION \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DPACKAGE_DATA_DIR=\"$(pkgdatadir)\" \
$(ST_CFLAGS) \
$(NULL)

View File

@ -61,6 +61,8 @@ include Makefile-hotplug-sniffer.am
gnome_shell_cflags = \
$(GNOME_SHELL_CFLAGS) \
-I$(srcdir)/tray \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DVERSION=\"$(VERSION)\" \
-DLOCALEDIR=\"$(datadir)/locale\" \
-DDATADIR=\"$(datadir)\" \
@ -257,7 +259,7 @@ libexec_PROGRAMS += gnome-shell-perf-helper
gnome_shell_perf_helper_SOURCES = shell-perf-helper.c
gnome_shell_perf_helper_CPPFLAGS = $(SHELL_PERF_HELPER_CFLAGS)
gnome_shell_perf_helper_LDADD = $(SHELL_PERF_HELPER_LIBS)
gnome_shell_perf_helper_LDADD = $(SHELL_PERF_HELPER_LIBS) -lm
########################################

View File

@ -42,8 +42,8 @@ function _showHello() {
let monitor = Main.layoutManager.primaryMonitor;
text.set_position(Math.floor(monitor.width / 2 - text.width / 2),
Math.floor(monitor.height / 2 - text.height / 2));
text.set_position(monitor.x + Math.floor(monitor.width / 2 - text.width / 2),
monitor.y + Math.floor(monitor.height / 2 - text.height / 2));
Tweener.addTween(text,
{ opacity: 0,

View File

@ -75,11 +75,16 @@ def start_shell(perf_output=None):
# Set up environment
env = dict(os.environ)
env['SHELL_PERF_MODULE'] = options.perf
env['MUTTER_WM_CLASS_FILTER'] = 'Gnome-shell-perf-helper'
filters = ['Gnome-shell-perf-helper'] + options.extra_filter
env['MUTTER_WM_CLASS_FILTER'] = ','.join(filters)
if perf_output is not None:
env['SHELL_PERF_OUTPUT'] = perf_output
# A fixed background image
env['SHELL_BACKGROUND_IMAGE'] = '@pkgdatadir@/perf-background.xml'
self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
args = []
args.append(os.path.join(self_dir, 'gnome-shell'))
@ -102,8 +107,6 @@ def run_shell(perf_output=None):
def restore_shell():
pid = os.fork()
if (pid == 0):
if "MUTTER_WM_CLASS_FILTER" in os.environ:
del os.environ["MUTTER_WM_CLASS_FILTER"]
os.execlp("gnome-shell", "gnome-shell", "--replace")
else:
sys.exit(0)
@ -189,6 +192,11 @@ def upload_performance_report(report_text):
print "Performance report upload failed with status %d" % response.status
print response.read()
def gnome_hwtest_log(*args):
command = ['gnome-hwtest-log', '-t', 'gnome-shell-perf-tool']
command.extend(args)
subprocess.check_call(command)
def run_performance_test():
iters = options.perf_iters
if options.perf_warmup:
@ -289,6 +297,13 @@ def run_performance_test():
if options.perf_upload:
upload_performance_report(json.dumps(report))
elif options.hwtest:
# Log to systemd journal
for metric in sorted(metric_summaries.keys()):
summary = metric_summaries[metric]
gnome_hwtest_log('--metric=' + metric + '=' + str(summary['values'][0]) + summary['units'],
'--metric-description=' + summary['description'])
gnome_hwtest_log('--finished')
else:
# Write a human readable summary
print '------------------------------------------------------------';
@ -304,8 +319,7 @@ def run_performance_test():
parser = optparse.OptionParser()
parser.add_option("", "--perf", metavar="PERF_MODULE",
help="Specify the name of a performance module to run",
default="core")
help="Specify the name of a performance module to run")
parser.add_option("", "--perf-iters", type="int", metavar="ITERS",
help="Numbers of iterations of performance module to run",
default=1)
@ -315,6 +329,10 @@ parser.add_option("", "--perf-output", metavar="OUTPUT_FILE",
help="Output file to write performance report")
parser.add_option("", "--perf-upload", action="store_true",
help="Upload performance report to server")
parser.add_option("", "--extra-filter", action="append",
help="add an extra window class that should be allowed")
parser.add_option("", "--hwtest", action="store_true",
help="Log results appropriately for GNOME Hardware Testing")
parser.add_option("", "--version", action="callback", callback=show_version,
help="Display version and exit")
@ -323,12 +341,25 @@ parser.add_option("-r", "--replace", action="store_true",
options, args = parser.parse_args()
if options.perf == None:
if options.hwtest:
options.perf = 'hwtest'
else:
options.perf = 'core'
if options.extra_filter is None:
if options.hwtest:
options.extra_filter = ['Gedit']
else:
options.extra_filter = []
if args:
parser.print_usage()
sys.exit(1)
normal_exit = run_performance_test()
if normal_exit:
restore_shell()
if not options.hwtest:
restore_shell()
else:
sys.exit(1)

View File

@ -26,8 +26,6 @@
#include <stdlib.h>
#include <string.h>
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#define COGL_ENABLE_EXPERIMENTAL_API
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include <gjs/gjs.h>
@ -174,7 +172,6 @@ gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
const char * (* query_extensions_string) (Display *dpy, int screen);
Bool (* query_extension) (Display *dpy, int *error, int *event);
MetaScreen *screen;
MetaDisplay *display;
Display *xdisplay;
const char *glx_extensions;
@ -183,9 +180,8 @@ gnome_shell_plugin_has_swap_event (GnomeShellPlugin *shell_plugin)
return FALSE;
screen = meta_plugin_get_screen (plugin);
display = meta_screen_get_display (screen);
xdisplay = meta_display_get_xdisplay (display);
xdisplay = clutter_x11_get_default_display ();
query_extensions_string =
(void *) cogl_get_proc_address ("glXQueryExtensionsString");
@ -389,9 +385,17 @@ gnome_shell_plugin_xevent_filter (MetaPlugin *plugin,
* can send this with a ust of 0. Simplify life for consumers
* by ignoring such events */
if (swap_complete_event->ust != 0)
shell_perf_log_event_x (shell_perf_log_get_default (),
"glx.swapComplete",
swap_complete_event->ust);
{
gboolean frame_timestamps;
g_object_get (shell_plugin->global,
"frame-timestamps", &frame_timestamps,
NULL);
if (frame_timestamps)
shell_perf_log_event_x (shell_perf_log_get_default (),
"glx.swapComplete",
swap_complete_event->ust);
}
}
#endif

View File

@ -242,6 +242,8 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
void *datap,
GError **error)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
CreateFadedIconData *data = datap;
ShellApp *app;
GdkPixbuf *pixbuf;
@ -333,13 +335,11 @@ shell_app_create_faded_icon_cpu (StTextureCache *cache,
}
}
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NONE,
have_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
rowstride,
pixels);
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
have_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
rowstride,
pixels,
NULL));
g_free (pixels);
g_object_unref (pixbuf);
@ -705,6 +705,72 @@ shell_app_open_new_window (ShellApp *app,
shell_app_launch (app, 0, workspace, NULL);
}
/**
* shell_app_can_open_new_window:
* @app: a #ShellApp
*
* Returns %TRUE if the app supports opening a new window through
* shell_app_open_new_window() (ie, if calling that function will
* result in actually opening a new window and not something else,
* like presenting the most recently active one)
*/
gboolean
shell_app_can_open_new_window (ShellApp *app)
{
ShellAppRunningState *state;
/* Apps that are not running can always open new windows, because
activating them would open the first one */
if (!app->running_state)
return TRUE;
state = app->running_state;
/* If the app has an explicit new-window action, then it can
(or it should be able to - we don't actually call the action
because we need to trigger startup notification, so it still
depends on what the app decides to do for Activate vs ActivateAction)
*/
if (g_action_group_has_action (G_ACTION_GROUP (state->muxer), "app.new-window"))
return TRUE;
/* If the app doesn't have a desktop file, then nothing is possible */
if (!app->info)
return FALSE;
/* If the app is explicitly telling us, then we know for sure */
if (g_desktop_app_info_has_key (G_DESKTOP_APP_INFO (app->info),
"X-GNOME-SingleWindow"))
return !g_desktop_app_info_get_boolean (G_DESKTOP_APP_INFO (app->info),
"X-GNOME-SingleWindow");
/* If this is a unique GtkApplication, and we don't have a new-window, then
probably we can't
We don't consider non-unique GtkApplications here to handle cases like
evince, which don't export a new-window action because each window is in
a different process. In any case, in a non-unique GtkApplication each
Activate() knows nothing about the other instances, so it will show a
new window.
*/
if (state->remote_menu)
{
const char *application_id;
application_id = meta_window_get_gtk_application_id (state->windows->data);
if (application_id != NULL)
return FALSE;
else
return TRUE;
}
/* In all other cases, we don't have a reliable source of information
or a decent heuristic, so we err on the compatibility side and say
yes.
*/
return TRUE;
}
/**
* shell_app_get_state:
* @app: a #ShellApp

View File

@ -56,6 +56,7 @@ void shell_app_activate_full (ShellApp *app,
void shell_app_open_new_window (ShellApp *app,
int workspace);
gboolean shell_app_can_open_new_window (ShellApp *app);
ShellAppState shell_app_get_state (ShellApp *app);

View File

@ -46,8 +46,6 @@
static ShellGlobal *the_object = NULL;
static void grab_notify (GtkWidget *widget, gboolean is_grab, gpointer user_data);
struct _ShellGlobal {
GObject parent;
@ -63,15 +61,6 @@ struct _ShellGlobal {
char *session_mode;
/* We use this window to get a notification from GTK+ when
* a widget in our process does a GTK+ grab. See
* http://bugzilla.gnome.org/show_bug.cgi?id=570641
*
* This window is never mapped or shown.
*/
GtkWindow *grab_notifier;
gboolean gtk_grab_active;
XserverRegion input_region;
GjsContext *js_context;
@ -96,6 +85,8 @@ struct _ShellGlobal {
guint32 xdnd_timestamp;
gboolean has_modal;
gboolean frame_timestamps;
gboolean frame_finish_timestamp;
};
enum {
@ -116,6 +107,8 @@ enum {
PROP_IMAGEDIR,
PROP_USERDATADIR,
PROP_FOCUS_MANAGER,
PROP_FRAME_TIMESTAMPS,
PROP_FRAME_FINISH_TIMESTAMP,
};
/* Signals */
@ -146,6 +139,12 @@ shell_global_set_property(GObject *object,
g_clear_pointer (&global->session_mode, g_free);
global->session_mode = g_ascii_strdown (g_value_get_string (value), -1);
break;
case PROP_FRAME_TIMESTAMPS:
global->frame_timestamps = g_value_get_boolean (value);
break;
case PROP_FRAME_FINISH_TIMESTAMP:
global->frame_finish_timestamp = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -217,6 +216,12 @@ shell_global_get_property(GObject *object,
case PROP_FOCUS_MANAGER:
g_value_set_object (value, global->focus_manager);
break;
case PROP_FRAME_TIMESTAMPS:
g_value_set_boolean (value, global->frame_timestamps);
break;
case PROP_FRAME_FINISH_TIMESTAMP:
g_value_set_boolean (value, global->frame_finish_timestamp);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -269,10 +274,6 @@ shell_global_init (ShellGlobal *global)
global->runtime_state_path = g_file_new_for_path (path);
global->settings = g_settings_new ("org.gnome.shell");
global->grab_notifier = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
g_signal_connect (global->grab_notifier, "grab-notify", G_CALLBACK (grab_notify), global);
global->gtk_grab_active = FALSE;
global->sound_context = ca_gtk_context_get ();
ca_context_change_props (global->sound_context,
@ -332,7 +333,6 @@ shell_global_finalize (GObject *object)
ShellGlobal *global = SHELL_GLOBAL (object);
g_object_unref (global->js_context);
gtk_widget_destroy (GTK_WIDGET (global->grab_notifier));
g_object_unref (global->settings);
the_object = NULL;
@ -500,6 +500,20 @@ shell_global_class_init (ShellGlobalClass *klass)
"The shell's StFocusManager",
ST_TYPE_FOCUS_MANAGER,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_FRAME_TIMESTAMPS,
g_param_spec_boolean ("frame-timestamps",
"Frame Timestamps",
"Whether to log frame timestamps in the performance log",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_FRAME_FINISH_TIMESTAMP,
g_param_spec_boolean ("frame-finish-timestamp",
"Frame Finish Timestamps",
"Whether at the end of a frame to call glFinish and log paintCompletedTimestamp",
FALSE,
G_PARAM_READWRITE));
}
/*
@ -624,9 +638,7 @@ sync_input_region (ShellGlobal *global)
{
MetaScreen *screen = global->meta_screen;
if (global->gtk_grab_active)
meta_empty_stage_input_region (screen);
else if (global->has_modal)
if (global->has_modal)
meta_set_stage_input_region (screen, None);
else
meta_set_stage_input_region (screen, global->input_region);
@ -756,17 +768,72 @@ global_stage_notify_height (GObject *gobject,
static gboolean
global_stage_before_paint (gpointer data)
{
shell_perf_log_event (shell_perf_log_get_default (),
"clutter.stagePaintStart");
ShellGlobal *global = SHELL_GLOBAL (data);
if (global->frame_timestamps)
shell_perf_log_event (shell_perf_log_get_default (),
"clutter.stagePaintStart");
return TRUE;
}
static gboolean
global_stage_after_paint (gpointer data)
load_gl_symbol (const char *name,
void **func)
{
shell_perf_log_event (shell_perf_log_get_default (),
"clutter.stagePaintDone");
*func = cogl_get_proc_address (name);
if (!*func)
{
g_warning ("failed to resolve required GL symbol \"%s\"\n", name);
return FALSE;
}
return TRUE;
}
static void
global_stage_after_paint (ClutterStage *stage,
ShellGlobal *global)
{
/* At this point, we've finished all layout and painting, but haven't
* actually flushed or swapped */
if (global->frame_timestamps && global->frame_finish_timestamp)
{
/* It's interesting to find out when the paint actually finishes
* on the GPU. We could wait for this asynchronously with
* ARB_timer_query (see https://bugzilla.gnome.org/show_bug.cgi?id=732350
* for an implementation of this), but what we actually would
* find out then is the latency for drawing a frame, not how much
* GPU work was needed, since frames can overlap. Calling glFinish()
* is a fairly reliable way to separate out adjacent frames
* and measure the amount of GPU work. This is turned on with a
* separate property from ::frame-timestamps, since it should not
* be turned on if we're trying to actual measure latency or frame
* rate.
*/
static void (*finish) (void);
if (!finish)
load_gl_symbol ("glFinish", (void **)&finish);
cogl_flush ();
finish ();
shell_perf_log_event (shell_perf_log_get_default (),
"clutter.paintCompletedTimestamp");
}
}
static gboolean
global_stage_after_swap (gpointer data)
{
/* Everything is done, we're ready for a new frame */
ShellGlobal *global = SHELL_GLOBAL (data);
if (global->frame_timestamps)
shell_perf_log_event (shell_perf_log_get_default (),
"clutter.stagePaintDone");
return TRUE;
}
@ -784,7 +851,11 @@ update_scale_factor (GtkSettings *settings,
g_value_init (&value, G_TYPE_INT);
if (gdk_screen_get_setting (global->gdk_screen, "gdk-window-scaling-factor", &value))
g_object_set (context, "scale-factor", g_value_get_int (&value), NULL);
{
g_object_set (context, "scale-factor", g_value_get_int (&value), NULL);
if (meta_is_wayland_compositor ())
g_object_set (clutter_settings_get_default (), "font-dpi", 96 * 1024 * g_value_get_int (&value), NULL);
}
/* Make sure clutter and gdk scaling stays disabled */
g_object_set (clutter_settings_get_default (), "window-scaling-factor", 1, NULL);
@ -947,19 +1018,26 @@ _shell_global_set_plugin (ShellGlobal *global,
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
global_stage_before_paint,
NULL, NULL);
global, NULL);
g_signal_connect (global->stage, "after-paint",
G_CALLBACK (global_stage_after_paint), global);
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
global_stage_after_paint,
NULL, NULL);
global_stage_after_swap,
global, NULL);
shell_perf_log_define_event (shell_perf_log_get_default(),
"clutter.stagePaintStart",
"Start of stage page repaint",
"");
shell_perf_log_define_event (shell_perf_log_get_default(),
"clutter.paintCompletedTimestamp",
"Paint completion on GPU",
"");
shell_perf_log_define_event (shell_perf_log_get_default(),
"clutter.stagePaintDone",
"End of stage page repaint",
"End of frame, possibly including swap time",
"");
g_signal_connect (global->stage, "notify::key-focus",
@ -1240,17 +1318,6 @@ shell_global_notify_error (ShellGlobal *global,
g_signal_emit_by_name (global, "notify-error", msg, details);
}
static void
grab_notify (GtkWidget *widget, gboolean was_grabbed, gpointer user_data)
{
ShellGlobal *global = SHELL_GLOBAL (user_data);
global->gtk_grab_active = !was_grabbed;
/* Update for the new setting of gtk_grab_active */
sync_input_region (global);
}
/**
* shell_global_init_xdnd:
* @global: the #ShellGlobal

View File

@ -13,9 +13,6 @@
#include "config.h"
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#define COGL_ENABLE_EXPERIMENTAL_API
#include <cogl/cogl.h>
#include "shell-glsl-quad.h"

View File

@ -35,8 +35,6 @@
#define SHELL_IS_INVERT_EFFECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_INVERT_LIGHTNESS_EFFECT))
#define SHELL_INVERT_LIGHTNESS_EFFECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_INVERT_LIGHTNESS_EFFEC, ShellInvertLightnessEffectClass))
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include "shell-invert-lightness-effect.h"
#include <cogl/cogl.h>

View File

@ -21,7 +21,6 @@
#ifndef __SHELL_INVERT_LIGHTNESS_EFFECT_H__
#define __SHELL_INVERT_LIGHTNESS_EFFECT_H__
#define COGL_ENABLE_EXPERIMENTAL_API
#include <clutter/clutter.h>
G_BEGIN_DECLS

View File

@ -9,6 +9,8 @@
#include "config.h"
#include <math.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@ -27,6 +29,7 @@ static const gchar introspection_xml[] =
" <arg type='i' name='height' direction='in'/>"
" <arg type='b' name='alpha' direction='in'/>"
" <arg type='b' name='maximized' direction='in'/>"
" <arg type='b' name='redraws' direction='in'/>"
" </method>"
" <method name='WaitWindows'/>"
" <method name='DestroyWindows'/>"
@ -40,9 +43,13 @@ typedef struct {
guint alpha : 1;
guint maximized : 1;
guint redraws : 1;
guint mapped : 1;
guint exposed : 1;
guint pending : 1;
gint64 start_time;
gint64 time;
} WindowInfo;
static int opt_idle_timeout = 30;
@ -119,6 +126,7 @@ on_window_draw (GtkWidget *window,
{
cairo_rectangle_int_t allocation;
gtk_widget_get_allocation (window, &allocation);
double x_offset, y_offset;
/* We draw an arbitrary pattern of red lines near the border of the
* window to make it more clear than empty windows if something
@ -136,16 +144,27 @@ on_window_draw (GtkWidget *window,
cairo_paint (cr);
cairo_restore (cr);
if (info->redraws)
{
double position = (info->time - info->start_time) / 1000000.;
x_offset = 20 * cos (2 * M_PI * position);
y_offset = 20 * sin (2 * M_PI * position);
}
else
{
x_offset = y_offset = 0;
}
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_set_line_width (cr, 10);
cairo_move_to (cr, 0, 40);
cairo_line_to (cr, allocation.width, 40);
cairo_move_to (cr, 0, allocation.height - 40);
cairo_line_to (cr, allocation.width, allocation.height - 40);
cairo_move_to (cr, 40, 0);
cairo_line_to (cr, 40, allocation.height);
cairo_move_to (cr, allocation.width - 40, 0);
cairo_line_to (cr, allocation.width - 40, allocation.height);
cairo_move_to (cr, 0, 40 + y_offset);
cairo_line_to (cr, allocation.width, 40 + y_offset);
cairo_move_to (cr, 0, allocation.height - 40 + y_offset);
cairo_line_to (cr, allocation.width, allocation.height - 40 + y_offset);
cairo_move_to (cr, 40 + x_offset, 0);
cairo_line_to (cr, 40 + x_offset, allocation.height);
cairo_move_to (cr, allocation.width - 40 + x_offset, 0);
cairo_line_to (cr, allocation.width - 40 + x_offset, allocation.height);
cairo_stroke (cr);
info->exposed = TRUE;
@ -159,11 +178,29 @@ on_window_draw (GtkWidget *window,
return FALSE;
}
static gboolean
tick_callback (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
WindowInfo *info = user_data;
if (info->start_time < 0)
info->start_time = info->time = gdk_frame_clock_get_frame_time (frame_clock);
else
info->time = gdk_frame_clock_get_frame_time (frame_clock);
gtk_widget_queue_draw (widget);
return TRUE;
}
static void
create_window (int width,
int height,
gboolean alpha,
gboolean maximized)
gboolean maximized,
gboolean redraws)
{
WindowInfo *info;
@ -172,12 +209,14 @@ create_window (int width,
info->height = height;
info->alpha = alpha;
info->maximized = maximized;
info->redraws = redraws;
info->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
if (alpha)
gtk_widget_set_visual (info->window, gdk_screen_get_rgba_visual (gdk_screen_get_default ()));
if (maximized)
gtk_window_maximize (GTK_WINDOW (info->window));
info->pending = TRUE;
info->start_time = -1;
gtk_widget_set_size_request (info->window, width, height);
gtk_widget_set_app_paintable (info->window, TRUE);
@ -185,6 +224,10 @@ create_window (int width,
g_signal_connect (info->window, "draw", G_CALLBACK (on_window_draw), info);
gtk_widget_show (info->window);
if (info->redraws)
gtk_widget_add_tick_callback (info->window, tick_callback,
info, NULL);
our_windows = g_list_prepend (our_windows, info);
}
@ -242,11 +285,11 @@ handle_method_call (GDBusConnection *connection,
else if (g_strcmp0 (method_name, "CreateWindow") == 0)
{
int width, height;
gboolean alpha, maximized;
gboolean alpha, maximized, redraws;
g_variant_get (parameters, "(iibb)", &width, &height, &alpha, &maximized);
g_variant_get (parameters, "(iibbb)", &width, &height, &alpha, &maximized, &redraws);
create_window (width, height, alpha, maximized);
create_window (width, height, alpha, maximized, redraws);
g_dbus_method_invocation_return_value (invocation, NULL);
}
else if (g_strcmp0 (method_name, "WaitWindows") == 0)

View File

@ -126,11 +126,7 @@ G_DEFINE_TYPE(ShellPerfLog, shell_perf_log, G_TYPE_OBJECT);
static gint64
get_time (void)
{
GTimeVal timeval;
g_get_current_time (&timeval);
return timeval.tv_sec * G_GINT64_CONSTANT(1000000) + timeval.tv_usec;
return g_get_monotonic_time ();
}
static void

View File

@ -21,13 +21,6 @@
#include "shell-recorder-src.h"
#include "shell-recorder.h"
#include <clutter/x11/clutter-x11.h>
#include <X11/extensions/XInput.h>
#include <X11/extensions/XInput2.h>
/* This is also hard-coded in mutter and GDK */
#define VIRTUAL_CORE_POINTER_ID 2
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
@ -63,7 +56,6 @@ struct _ShellRecorder {
GdkScreen *gdk_screen;
gboolean have_pointer;
int pointer_x;
int pointer_y;
@ -559,156 +551,18 @@ on_cursor_changed (MetaCursorTracker *tracker,
recorder_queue_redraw (recorder);
}
/* We use an event filter on the stage to get the XFixesCursorNotifyEvent
* and also to track cursor position (when the cursor is over the stage's
* input area); tracking cursor position here rather than with ClutterEvent
* allows us to avoid worrying about event propagation and competing
* signal handlers.
*/
static ClutterX11FilterReturn
recorder_event_filter (XEvent *xev,
ClutterEvent *cev,
gpointer data)
{
ShellRecorder *recorder = data;
XIEvent *input_event = NULL;
if (xev->xany.window != clutter_x11_get_stage_window (recorder->stage))
return CLUTTER_X11_FILTER_CONTINUE;
if (xev->xany.type == GenericEvent &&
xev->xcookie.extension == recorder->xinput_opcode)
input_event = (XIEvent *) xev->xcookie.data;
if (input_event != NULL &&
input_event->evtype == XI_Motion)
{
XIDeviceEvent *device_event = (XIDeviceEvent *) input_event;
if (device_event->deviceid == VIRTUAL_CORE_POINTER_ID)
{
recorder->pointer_x = device_event->event_x;
recorder->pointer_y = device_event->event_y;
recorder_queue_redraw (recorder);
}
}
/* We want to track whether the pointer is over the stage
* window itself, and not in a child window. A "virtual"
* crossing is one that goes directly from ancestor to child.
*/
else if (input_event != NULL &&
input_event->evtype == XI_Enter)
{
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
if (enter_event->deviceid == VIRTUAL_CORE_POINTER_ID &&
(enter_event->detail != XINotifyVirtual &&
enter_event->detail != XINotifyNonlinearVirtual))
{
recorder->have_pointer = TRUE;
recorder->pointer_x = enter_event->event_x;
recorder->pointer_y = enter_event->event_y;
recorder_queue_redraw (recorder);
}
}
else if (input_event != NULL &&
input_event->evtype == XI_Leave)
{
XILeaveEvent *leave_event = (XILeaveEvent *) input_event;
if (leave_event->deviceid == VIRTUAL_CORE_POINTER_ID &&
(leave_event->detail != XINotifyVirtual &&
leave_event->detail != XINotifyNonlinearVirtual))
{
recorder->have_pointer = FALSE;
recorder->pointer_x = leave_event->event_x;
recorder->pointer_y = leave_event->event_y;
recorder_queue_redraw (recorder);
}
}
return CLUTTER_X11_FILTER_CONTINUE;
}
/* We optimize out querying the server for the pointer position if the
* pointer is in the input area of the ClutterStage. We track changes to
* that with Enter/Leave events, but we need to 100% accurate about the
* initial condition, which is a little involved.
*/
static void
recorder_get_initial_cursor_position (ShellRecorder *recorder)
{
Display *xdisplay = clutter_x11_get_default_display ();
Window xwindow = clutter_x11_get_stage_window (recorder->stage);
XWindowAttributes xwa;
Window root, child, parent;
Window *children;
guint n_children;
int root_x,root_y;
int window_x, window_y;
guint mask;
XGrabServer(xdisplay);
XGetWindowAttributes (xdisplay, xwindow, &xwa);
XQueryTree (xdisplay, xwindow, &root, &parent, &children, &n_children);
XFree (children);
if (xwa.map_state == IsViewable &&
XQueryPointer (xdisplay, parent,
&root, &child, &root_x, &root_y, &window_x, &window_y, &mask) &&
child == xwindow)
{
/* The point of this call is not actually to translate the coordinates -
* we could do that ourselves using xwa.{x,y} - but rather to see if
* the pointer is in a child of the window, which we count as "not in
* window", because we aren't guaranteed to get pointer events.
*/
XTranslateCoordinates(xdisplay, parent, xwindow,
window_x, window_y,
&window_x, &window_y, &child);
if (child == None)
{
recorder->have_pointer = TRUE;
recorder->pointer_x = window_x;
recorder->pointer_y = window_y;
}
}
else
recorder->have_pointer = FALSE;
XUngrabServer(xdisplay);
XFlush(xdisplay);
}
/* When the cursor is not over the stage's input area, we query for the
* pointer position in a timeout.
*/
static void
recorder_update_pointer (ShellRecorder *recorder)
{
Display *xdisplay = clutter_x11_get_default_display ();
Window xwindow = clutter_x11_get_stage_window (recorder->stage);
Window root, child;
int root_x,root_y;
int window_x, window_y;
guint mask;
int pointer_x, pointer_y;
if (recorder->have_pointer)
return;
meta_cursor_tracker_get_pointer (recorder->cursor_tracker, &pointer_x, &pointer_y, NULL);
if (XQueryPointer (xdisplay, xwindow,
&root, &child, &root_x, &root_y, &window_x, &window_y, &mask))
if (pointer_x != recorder->pointer_x || pointer_y != recorder->pointer_y)
{
if (window_x != recorder->pointer_x || window_y != recorder->pointer_y)
{
recorder->pointer_x = window_x;
recorder->pointer_y = window_y;
recorder_queue_redraw (recorder);
}
recorder->pointer_x = pointer_x;
recorder->pointer_y = pointer_y;
recorder_queue_redraw (recorder);
}
}
@ -751,10 +605,8 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
G_CALLBACK (recorder_on_stage_paint), recorder);
g_signal_connect (recorder->stage, "notify::width",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
g_signal_connect (recorder->stage, "notify::width",
g_signal_connect (recorder->stage, "notify::height",
G_CALLBACK (recorder_on_stage_notify_size), recorder);
clutter_x11_add_filter (recorder_event_filter, recorder);
}
static void
@ -770,8 +622,6 @@ recorder_disconnect_stage_callbacks (ShellRecorder *recorder)
(void *)recorder_on_stage_notify_size,
recorder);
clutter_x11_remove_filter (recorder_event_filter, recorder);
/* We don't don't deselect for cursor changes in case someone else just
* happened to be selecting for cursor events on the same window; sending
* us the events is close to free in any case.
@ -800,40 +650,7 @@ recorder_set_stage (ShellRecorder *recorder,
recorder->stage = stage;
if (recorder->stage)
{
int error_base, event_base;
int major = 2, minor = 3;
recorder->stage = stage;
recorder_update_size (recorder);
if (XQueryExtension (clutter_x11_get_default_display (),
"XInputExtension",
&recorder->xinput_opcode,
&error_base,
&event_base))
{
if (XIQueryVersion (clutter_x11_get_default_display (), &major, &minor) == Success)
{
int version = (major * 10) + minor;
if (version < 22)
g_warning("ShellRecorder: xinput version %d.%d is too old", major, minor);
}
else
{
g_warning("ShellRecorder: xinput version could not be queried");
}
}
else
{
g_warning("ShellRecorder: xinput extension unavailable");
}
clutter_stage_ensure_current (stage);
recorder_get_initial_cursor_position (recorder);
}
recorder_update_size (recorder);
}
static void
@ -1715,6 +1532,7 @@ shell_recorder_record (ShellRecorder *recorder,
recorder->last_frame_time = 0;
recorder->state = RECORDER_STATE_RECORDING;
recorder_update_pointer (recorder);
recorder_add_update_pointer_timeout (recorder);
/* Set up repaint hook */

View File

@ -1,8 +1,5 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#define COGL_ENABLE_EXPERIMENTAL_API
#define CLUTTER_ENABLE_EXPERIMENTAL_API
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <meta/display.h>

View File

@ -71,6 +71,9 @@ struct _StButtonPrivate
{
gchar *text;
ClutterInputDevice *device;
ClutterEventSequence *press_sequence;
guint button_mask : 3;
guint is_toggle : 1;
@ -127,27 +130,42 @@ st_button_style_changed (StWidget *widget)
}
static void
st_button_press (StButton *button,
StButtonMask mask)
st_button_press (StButton *button,
ClutterInputDevice *device,
StButtonMask mask,
ClutterEventSequence *sequence)
{
if (button->priv->pressed == 0)
if (button->priv->pressed == 0 || sequence)
st_widget_add_style_pseudo_class (ST_WIDGET (button), "active");
button->priv->pressed |= mask;
button->priv->press_sequence = sequence;
button->priv->device = device;
}
static void
st_button_release (StButton *button,
StButtonMask mask,
int clicked_button)
st_button_release (StButton *button,
ClutterInputDevice *device,
StButtonMask mask,
int clicked_button,
ClutterEventSequence *sequence)
{
button->priv->pressed &= ~mask;
if (button->priv->pressed != 0)
if ((device && button->priv->device != device) ||
(sequence && button->priv->press_sequence != sequence))
return;
else if (!sequence)
{
button->priv->pressed &= ~mask;
if (button->priv->pressed != 0)
return;
}
button->priv->press_sequence = NULL;
button->priv->device = NULL;
st_widget_remove_style_pseudo_class (ST_WIDGET (button), "active");
if (clicked_button)
if (clicked_button || sequence)
{
if (button->priv->is_toggle)
st_button_set_checked (button, !button->priv->is_checked);
@ -162,6 +180,10 @@ st_button_button_press (ClutterActor *actor,
{
StButton *button = ST_BUTTON (actor);
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event);
if (button->priv->press_sequence)
return CLUTTER_EVENT_PROPAGATE;
if (button->priv->button_mask & mask)
{
@ -169,7 +191,7 @@ st_button_button_press (ClutterActor *actor,
clutter_grab_pointer (actor);
button->priv->grabbed |= mask;
st_button_press (button, mask);
st_button_press (button, device, mask, NULL);
return TRUE;
}
@ -183,13 +205,14 @@ st_button_button_release (ClutterActor *actor,
{
StButton *button = ST_BUTTON (actor);
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (event->button);
ClutterInputDevice *device = clutter_event_get_device ((ClutterEvent*) event);
if (button->priv->button_mask & mask)
{
gboolean is_click;
is_click = button->priv->grabbed && st_widget_get_hover (ST_WIDGET (button));
st_button_release (button, mask, is_click ? event->button : 0);
st_button_release (button, device, mask, is_click ? event->button : 0, NULL);
button->priv->grabbed &= ~mask;
if (button->priv->grabbed == 0)
@ -201,6 +224,39 @@ st_button_button_release (ClutterActor *actor,
return FALSE;
}
static gboolean
st_button_touch_event (ClutterActor *actor,
ClutterTouchEvent *event)
{
StButton *button = ST_BUTTON (actor);
StButtonMask mask = ST_BUTTON_MASK_FROM_BUTTON (1);
ClutterEventSequence *sequence;
ClutterInputDevice *device;
if (button->priv->pressed != 0)
return CLUTTER_EVENT_PROPAGATE;
device = clutter_event_get_device ((ClutterEvent*) event);
sequence = clutter_event_get_event_sequence ((ClutterEvent*) event);
if (event->type == CLUTTER_TOUCH_BEGIN && !button->priv->press_sequence)
{
clutter_input_device_sequence_grab (device, sequence, actor);
st_button_press (button, device, 0, sequence);
return CLUTTER_EVENT_STOP;
}
else if (event->type == CLUTTER_TOUCH_END &&
button->priv->device == device &&
button->priv->press_sequence == sequence)
{
st_button_release (button, device, mask, 0, sequence);
clutter_input_device_sequence_ungrab (device, sequence);
return CLUTTER_EVENT_STOP;
}
return CLUTTER_EVENT_PROPAGATE;
}
static gboolean
st_button_key_press (ClutterActor *actor,
ClutterKeyEvent *event)
@ -213,7 +269,7 @@ st_button_key_press (ClutterActor *actor,
event->keyval == CLUTTER_KEY_Return ||
event->keyval == CLUTTER_KEY_KP_Enter)
{
st_button_press (button, ST_BUTTON_ONE);
st_button_press (button, NULL, ST_BUTTON_ONE, NULL);
return TRUE;
}
}
@ -236,7 +292,7 @@ st_button_key_release (ClutterActor *actor,
gboolean is_click;
is_click = (button->priv->pressed & ST_BUTTON_ONE);
st_button_release (button, ST_BUTTON_ONE, is_click ? 1 : 0);
st_button_release (button, NULL, ST_BUTTON_ONE, is_click ? 1 : 0, NULL);
return TRUE;
}
}
@ -252,7 +308,7 @@ st_button_key_focus_out (ClutterActor *actor)
/* If we lose focus between a key press and release, undo the press */
if ((button->priv->pressed & ST_BUTTON_ONE) &&
!(button->priv->grabbed & ST_BUTTON_ONE))
st_button_release (button, ST_BUTTON_ONE, 0);
st_button_release (button, NULL, ST_BUTTON_ONE, 0, NULL);
CLUTTER_ACTOR_CLASS (st_button_parent_class)->key_focus_out (actor);
}
@ -269,9 +325,11 @@ st_button_enter (ClutterActor *actor,
if (button->priv->grabbed)
{
if (st_widget_get_hover (ST_WIDGET (button)))
st_button_press (button, button->priv->grabbed);
st_button_press (button, button->priv->device,
button->priv->grabbed, NULL);
else
st_button_release (button, button->priv->grabbed, 0);
st_button_release (button, button->priv->device,
button->priv->grabbed, 0, NULL);
}
return ret;
@ -289,9 +347,11 @@ st_button_leave (ClutterActor *actor,
if (button->priv->grabbed)
{
if (st_widget_get_hover (ST_WIDGET (button)))
st_button_press (button, button->priv->grabbed);
st_button_press (button, button->priv->device,
button->priv->grabbed, NULL);
else
st_button_release (button, button->priv->grabbed, 0);
st_button_release (button, button->priv->device,
button->priv->grabbed, 0, NULL);
}
return ret;
@ -391,6 +451,7 @@ st_button_class_init (StButtonClass *klass)
actor_class->key_focus_out = st_button_key_focus_out;
actor_class->enter_event = st_button_enter;
actor_class->leave_event = st_button_leave;
actor_class->touch_event = st_button_touch_event;
widget_class->style_changed = st_button_style_changed;
widget_class->get_accessible_type = st_button_accessible_get_type;
@ -679,13 +740,24 @@ void
st_button_fake_release (StButton *button)
{
if (button->priv->pressed)
st_button_release (button, button->priv->pressed, 0);
st_button_release (button, button->priv->device,
button->priv->pressed, 0, NULL);
if (button->priv->grabbed)
{
button->priv->grabbed = 0;
clutter_ungrab_pointer ();
}
if (button->priv->device &&
button->priv->press_sequence)
{
clutter_input_device_sequence_ungrab (button->priv->device,
button->priv->press_sequence);
button->priv->press_sequence = NULL;
}
button->priv->device = NULL;
}
/******************************************************************************/

View File

@ -171,38 +171,32 @@ _st_set_text_from_style (ClutterText *text,
CoglHandle
_st_create_texture_material (CoglHandle src_texture)
{
static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
CoglHandle material;
static CoglPipeline *texture_pipeline_template = NULL;
CoglPipeline *pipeline;
g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
COGL_INVALID_HANDLE);
/* We use a material that has a dummy texture as a base for all
texture materials. The idea is that only the Cogl texture object
would be different in the children so it is likely that Cogl will
be able to share GL programs between all the textures. */
if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
/* The only state used in the pipeline that would affect the shader
generation is the texture type on the layer. Therefore we create
a template pipeline which sets this state and all texture
pipelines are created as a copy of this. That way Cogl can find
the shader state for the pipeline more quickly by looking at the
pipeline ancestry instead of resorting to the shader cache. */
if (G_UNLIKELY (texture_pipeline_template == NULL))
{
static const guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
CoglHandle dummy_texture;
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
dummy_texture =
cogl_texture_new_from_data (1, 1,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
4, white_pixel);
texture_material_template = cogl_material_new ();
cogl_material_set_layer (texture_material_template, 0, dummy_texture);
cogl_handle_unref (dummy_texture);
texture_pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_null_texture (texture_pipeline_template,
0, /* layer */
COGL_TEXTURE_TYPE_2D);
}
material = cogl_material_copy (texture_material_template);
pipeline = cogl_pipeline_copy (texture_pipeline_template);
cogl_material_set_layer (material, 0, src_texture);
if (src_texture != NULL)
cogl_pipeline_set_layer_texture (pipeline, 0, src_texture);
return material;
return pipeline;
}
/*****
@ -349,6 +343,9 @@ CoglHandle
_st_create_shadow_material (StShadow *shadow_spec,
CoglHandle src_texture)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;
CoglHandle material;
@ -375,13 +372,11 @@ _st_create_shadow_material (StShadow *shadow_spec,
&width_out, &height_out, &rowstride_out);
g_free (pixels_in);
texture = cogl_texture_new_from_data (width_out,
height_out,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_A_8,
rowstride_out,
pixels_out);
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width_out, height_out,
COGL_PIXEL_FORMAT_A_8,
rowstride_out,
pixels_out,
NULL));
g_free (pixels_out);

View File

@ -191,6 +191,15 @@ st_scroll_view_fade_set_actor (ClutterActorMeta *meta,
g_return_if_fail (actor == NULL || ST_IS_SCROLL_VIEW (actor));
if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
{
/* if we don't have support for GLSL shaders then we
* forcibly disable the ActorMeta
*/
clutter_actor_meta_set_enabled (meta, FALSE);
return;
}
if (self->vadjustment)
{
g_signal_handlers_disconnect_by_func (self->vadjustment,

View File

@ -21,8 +21,6 @@
#include "config.h"
#define COGL_ENABLE_EXPERIMENTAL_API /* for cogl_framebuffer_allocate */
#include "st-texture-cache.h"
#include "st-private.h"
#include <gtk/gtk.h>
@ -62,7 +60,7 @@ static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE(StTextureCache, st_texture_cache, G_TYPE_OBJECT);
/* We want to preserve the aspect ratio by default, also the default
* material for an empty texture is full opacity white, which we
* pipeline for an empty texture is full opacity white, which we
* definitely don't want. Skip that by setting 0 opacity.
*/
static ClutterTexture *
@ -75,7 +73,7 @@ create_default_texture (void)
/* Reverse the opacity we added while loading */
static void
set_texture_cogl_texture (ClutterTexture *clutter_texture, CoglHandle cogl_texture)
set_texture_cogl_texture (ClutterTexture *clutter_texture, CoglTexture *cogl_texture)
{
clutter_texture_set_cogl_texture (clutter_texture, cogl_texture);
g_object_set (clutter_texture, "opacity", 255, NULL);
@ -146,7 +144,7 @@ st_texture_cache_init (StTextureCache *self)
G_CALLBACK (on_icon_theme_changed), self);
self->priv->keyed_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, cogl_handle_unref);
g_free, cogl_object_unref);
self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
self->priv->file_monitors = g_hash_table_new_full (g_str_hash, g_str_equal,
@ -263,8 +261,6 @@ typedef struct {
StTextureCachePolicy policy;
char *key;
gboolean enforced_square;
guint width;
guint height;
guint scale;
@ -535,81 +531,19 @@ load_pixbuf_async_finish (StTextureCache *cache, GAsyncResult *result, GError **
return g_simple_async_result_get_op_res_gpointer (simple);
}
static CoglHandle
data_to_cogl_handle (const guchar *data,
gboolean has_alpha,
int width,
int height,
int rowstride,
gboolean add_padding)
static CoglTexture *
pixbuf_to_cogl_texture (GdkPixbuf *pixbuf)
{
CoglHandle texture, offscreen;
CoglColor clear_color;
guint size;
GError *error;
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
size = MAX (width, height);
if (!add_padding || width == height)
return cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NONE,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
rowstride,
data);
texture = cogl_texture_new_with_size (size, size,
COGL_TEXTURE_NO_SLICING,
COGL_PIXEL_FORMAT_ANY);
offscreen = cogl_offscreen_new_with_texture (texture);
error = NULL;
if (!cogl_framebuffer_allocate (offscreen, &error))
{
g_warning ("Failed to allocate FBO (sized %d): %s", size, error->message);
cogl_object_unref (texture);
cogl_object_unref (offscreen);
g_clear_error (&error);
return cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NONE,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
COGL_PIXEL_FORMAT_ANY,
rowstride,
data);
}
cogl_color_set_from_4ub (&clear_color, 0, 0, 0, 0);
cogl_push_framebuffer (offscreen);
cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
cogl_pop_framebuffer ();
cogl_handle_unref (offscreen);
cogl_texture_set_region (texture,
0, 0,
(size - width) / 2, (size - height) / 2,
width, height,
width, height,
has_alpha ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
rowstride,
data);
return texture;
}
static CoglHandle
pixbuf_to_cogl_handle (GdkPixbuf *pixbuf,
gboolean add_padding)
{
return data_to_cogl_handle (gdk_pixbuf_get_pixels (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_rowstride (pixbuf),
add_padding);
return COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx,
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
gdk_pixbuf_get_rowstride (pixbuf),
gdk_pixbuf_get_pixels (pixbuf),
NULL));
}
static cairo_surface_t *
@ -639,7 +573,7 @@ finish_texture_load (AsyncTextureLoadData *data,
{
GSList *iter;
StTextureCache *cache;
CoglHandle texdata = NULL;
CoglTexture *texdata = NULL;
cache = data->cache;
@ -648,7 +582,7 @@ finish_texture_load (AsyncTextureLoadData *data,
if (pixbuf == NULL)
goto out;
texdata = pixbuf_to_cogl_handle (pixbuf, data->enforced_square);
texdata = pixbuf_to_cogl_texture (pixbuf);
if (data->policy != ST_TEXTURE_CACHE_POLICY_NONE)
{
@ -657,7 +591,7 @@ finish_texture_load (AsyncTextureLoadData *data,
if (!g_hash_table_lookup_extended (cache->priv->keyed_cache, data->key,
&orig_key, &value))
{
cogl_handle_ref (texdata);
cogl_object_ref (texdata);
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (data->key),
texdata);
}
@ -671,7 +605,7 @@ finish_texture_load (AsyncTextureLoadData *data,
out:
if (texdata)
cogl_handle_unref (texdata);
cogl_object_unref (texdata);
texture_load_data_free (data);
}
@ -762,7 +696,7 @@ st_texture_cache_reset_texture (StTextureCachePropertyBind *bind,
const char *propname)
{
GdkPixbuf *pixbuf;
CoglHandle texdata;
CoglTexture *texdata;
g_object_get (bind->source, propname, &pixbuf, NULL);
@ -770,11 +704,11 @@ st_texture_cache_reset_texture (StTextureCachePropertyBind *bind,
if (pixbuf != NULL)
{
texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
texdata = pixbuf_to_cogl_texture (pixbuf);
g_object_unref (pixbuf);
clutter_texture_set_cogl_texture (bind->texture, texdata);
cogl_handle_unref (texdata);
cogl_object_unref (texdata);
clutter_actor_set_opacity (CLUTTER_ACTOR (bind->texture), 255);
}
@ -817,7 +751,7 @@ st_texture_cache_free_bind (gpointer data)
*
* Create a #ClutterTexture which tracks the #GdkPixbuf value of a GObject property
* named by @property_name. Unlike other methods in StTextureCache, the underlying
* CoglHandle is not shared by default with other invocations to this method.
* #CoglTexture is not shared by default with other invocations to this method.
*
* If the source object is destroyed, the texture will continue to show the last
* value of the property.
@ -868,7 +802,7 @@ st_texture_cache_bind_pixbuf_property (StTextureCache *cache,
*
* Returns: (transfer full): A newly-referenced handle to the texture
*/
CoglHandle
CoglTexture *
st_texture_cache_load (StTextureCache *cache,
const char *key,
StTextureCachePolicy policy,
@ -876,7 +810,7 @@ st_texture_cache_load (StTextureCache *cache,
void *data,
GError **error)
{
CoglHandle texture;
CoglTexture *texture;
texture = g_hash_table_lookup (cache->priv->keyed_cache, key);
if (!texture)
@ -885,9 +819,10 @@ st_texture_cache_load (StTextureCache *cache,
if (texture)
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texture);
else
return COGL_INVALID_HANDLE;
return NULL;
}
cogl_handle_ref (texture);
cogl_object_ref (texture);
return texture;
}
@ -912,7 +847,7 @@ ensure_request (StTextureCache *cache,
AsyncTextureLoadData **request,
ClutterActor *texture)
{
CoglHandle texdata;
CoglTexture *texdata;
AsyncTextureLoadData *pending;
gboolean had_pending;
@ -1011,7 +946,6 @@ load_gicon_with_colors (StTextureCache *cache,
request->icon_info = info;
request->width = request->height = size;
request->scale = scale;
request->enforced_square = TRUE;
load_texture_async (cache, request);
}
@ -1048,7 +982,7 @@ static ClutterActor *
load_from_pixbuf (GdkPixbuf *pixbuf)
{
ClutterTexture *texture;
CoglHandle texdata;
CoglTexture *texdata;
int width = gdk_pixbuf_get_width (pixbuf);
int height = gdk_pixbuf_get_height (pixbuf);
@ -1056,11 +990,11 @@ load_from_pixbuf (GdkPixbuf *pixbuf)
clutter_actor_set_size (CLUTTER_ACTOR (texture), width, height);
texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
texdata = pixbuf_to_cogl_texture (pixbuf);
set_texture_cogl_texture (texture, texdata);
cogl_handle_unref (texdata);
cogl_object_unref (texdata);
return CLUTTER_ACTOR (texture);
}
@ -1336,7 +1270,7 @@ st_texture_cache_load_uri_async (StTextureCache *cache,
return CLUTTER_ACTOR (texture);
}
static CoglHandle
static CoglTexture *
st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
StTextureCachePolicy policy,
const gchar *uri,
@ -1345,7 +1279,7 @@ st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
int scale,
GError **error)
{
CoglHandle texdata;
CoglTexture *texdata;
GdkPixbuf *pixbuf;
char *key;
@ -1359,17 +1293,17 @@ st_texture_cache_load_uri_sync_to_cogl_texture (StTextureCache *cache,
if (!pixbuf)
goto out;
texdata = pixbuf_to_cogl_handle (pixbuf, FALSE);
texdata = pixbuf_to_cogl_texture (pixbuf);
g_object_unref (pixbuf);
if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
{
cogl_handle_ref (texdata);
cogl_object_ref (texdata);
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), texdata);
}
}
else
cogl_handle_ref (texdata);
cogl_object_ref (texdata);
ensure_monitor_for_uri (cache, uri);
@ -1421,23 +1355,23 @@ out:
}
/**
* st_texture_cache_load_file_to_cogl_texture:
* st_texture_cache_load_file_to_cogl_texture: (skip)
* @cache: A #StTextureCache
* @file_path: Path to a file in supported image format
* @scale: Scale factor of the display
*
* This function synchronously loads the given file path
* into a COGL texture. On error, a warning is emitted
* and %COGL_INVALID_HANDLE is returned.
* and %NULL is returned.
*
* Returns: (transfer full): a new #CoglHandle
* Returns: (transfer full): a new #CoglTexture
*/
CoglHandle
CoglTexture *
st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
const gchar *file_path,
gint scale)
{
CoglHandle texture;
CoglTexture *texture;
GFile *file;
char *uri;
GError *error = NULL;
@ -1454,7 +1388,7 @@ st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
{
g_warning ("Failed to load %s: %s", file_path, error->message);
g_clear_error (&error);
return COGL_INVALID_HANDLE;
return NULL;
}
return texture;
}

View File

@ -93,9 +93,9 @@ ClutterActor *st_texture_cache_load_uri_async (StTextureCache *cache,
int available_height,
int scale);
CoglHandle st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
const gchar *file_path,
gint scale);
CoglTexture *st_texture_cache_load_file_to_cogl_texture (StTextureCache *cache,
const gchar *file_path,
gint scale);
cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *cache,
const gchar *file_path,
@ -112,13 +112,13 @@ cairo_surface_t *st_texture_cache_load_file_to_cairo_surface (StTextureCache *ca
* texture handle for the given key, or set @error.
*
*/
typedef CoglHandle (*StTextureCacheLoader) (StTextureCache *cache, const char *key, void *data, GError **error);
typedef CoglTexture * (*StTextureCacheLoader) (StTextureCache *cache, const char *key, void *data, GError **error);
CoglHandle st_texture_cache_load (StTextureCache *cache,
const char *key,
StTextureCachePolicy policy,
StTextureCacheLoader load,
void *data,
GError **error);
CoglTexture * st_texture_cache_load (StTextureCache *cache,
const char *key,
StTextureCachePolicy policy,
StTextureCacheLoader load,
void *data,
GError **error);
#endif /* __ST_TEXTURE_CACHE_H__ */

View File

@ -69,6 +69,8 @@ elliptical_arc (cairo_t *cr,
static CoglHandle
create_corner_material (StCornerSpec *corner)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
CoglHandle texture;
cairo_t *cr;
cairo_surface_t *surface;
@ -166,12 +168,11 @@ create_corner_material (StCornerSpec *corner)
cairo_surface_destroy (surface);
texture = cogl_texture_new_from_data (size, size,
COGL_TEXTURE_NONE,
CLUTTER_CAIRO_FORMAT_ARGB32,
COGL_PIXEL_FORMAT_ANY,
rowstride,
data);
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, size, size,
CLUTTER_CAIRO_FORMAT_ARGB32,
rowstride,
data,
NULL));
g_free (data);
g_assert (texture != COGL_INVALID_HANDLE);
@ -941,6 +942,8 @@ st_theme_node_prerender_background (StThemeNode *node,
float actor_width,
float actor_height)
{
ClutterBackend *backend = clutter_get_default_backend ();
CoglContext *ctx = clutter_backend_get_cogl_context (backend);
StBorderImage *border_image;
CoglHandle texture;
guint radius[4];
@ -1256,12 +1259,11 @@ st_theme_node_prerender_background (StThemeNode *node,
if (interior_path != NULL)
cairo_path_destroy (interior_path);
texture = cogl_texture_new_from_data (width, height,
COGL_TEXTURE_NONE,
CLUTTER_CAIRO_FORMAT_ARGB32,
COGL_PIXEL_FORMAT_ANY,
rowstride,
data);
texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width, height,
CLUTTER_CAIRO_FORMAT_ARGB32,
rowstride,
data,
NULL));
cairo_destroy (cr);
cairo_surface_destroy (surface);