Compare commits

...

49 Commits

Author SHA1 Message Date
6b610b26f8 keyboard: Refactor code resetting IM on window drags
When a window is dragged, the OSK should get hidden. Just
do this in a nicer way.
2018-08-03 17:02:20 +02:00
81956e9b84 keyboard: defer position-changed till we have a rect
Emitting it that soon results in JS warnings, as we don't have
everything in place yet. The position-changed signal will be
emitted from other locations as soon as we have it.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/464

Closes: #464
2018-08-03 13:12:20 +02:00
6b41f82346 Updated Slovenian translation 2018-08-03 11:17:49 +02:00
1fca090374 tools: fix XDG desktop syntax in gnome-shell-overrides-migration
Reported by desktop-file-validate:
error: value "True" for boolean key "NoDisplay" in group "Desktop
Entry" contains invalid characters, boolean values must be "false" or
"true"
2018-08-03 00:49:49 +02:00
da2fc2c9d3 workspace: Simplify detecting added dialogs after closing a window
When trying to close a window in the overview by clicking the close
button and the window doesn't get closed but a dialog is added to the
window afterwards, we close the overview and show the dialog.

Instead of adding a separate listener for the window-added signal to the
WindowOverlay, let the WindowClones remember that the close button was
pressed and activate themselves if a dialog is added after that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180
2018-08-03 00:09:02 +02:00
52cbc299a7 workspace: Fix infinite loop when finding parent window of dialogs
When a dialog is added to a window while the overview is shown, we get
its parent using get_transient_for() so we can add it to the right
window clone.

If we have multiple layers of dialogs we have to do this recursively
until we find the root ancestor. This case currently results in an
infinite loop: Since parent is always set to the same window, the
while-condition will always be true.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/180
2018-08-03 00:09:02 +02:00
9f436ce373 data: Fix comment in schema 2018-08-01 20:04:53 +02:00
d908940ef3 showOSD: Fix handling of defined 'falsy' parameters
For the OSD, all parameters except for the icon are optional - if the
caller doesn't include the 'label' option, the OSD won't show a label
etc.

While this makes sense for an API, it means that we have to be careful
to correctly differentiate an option that was omitted and an option
that has a 'falsy' value like false or 0.

Unfortunately since commit ccaae5d3c we no longer do, with the result
that OSDs meant for the first monitor will show up on all, and a level
of 0 is presented as no level bar instead of an empty one, whoops.

https://bugzilla.gnome.org/show_bug.cgi?id=791669
2018-08-01 13:58:23 +02:00
eeda54f24d Update Brazilian Portuguese translation 2018-08-01 10:15:51 +00:00
b8b5da1e95 Bump version to 3.29.90
Update NEWS.
2018-08-01 03:43:50 +02:00
3a9ad5c577 Update POTFILES.in 2018-07-31 23:55:20 +02:00
d57dc94d9e tools: Migrate changed overrides settings
While the new per-desktop overrides in GIO are easier to use for
both developers and users, it is still inconvenient for everyone
who changed the defaults using the old overrides hack to lose
their settings. Address this by running a small script on startup
that migrates existing settings.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-31 18:36:26 +00:00
393d7246cc Replace custom override schema with per-desktop override
GSettings now recognizes per-desktop overrides that can be used
to change schemas' default values for a particular desktop. This
is not entirely unlike our existing custom override mechanism in
mutter, except that it is not limited to keys in org.gnome.mutter,
and it doesn't require a separate schema - the latter means that
we (and gnome-teak-tool) no longer have to figure out the correct
schema for the current login session and just use the original one.

https://bugzilla.gnome.org/show_bug.cgi?id=786496
2018-07-31 18:36:26 +00:00
6217c3b88d volume: Show overamplified icon when in overdrive
Show an overamplified volume icon if volume is louder the max normalized one.
Use a similar logic as gnome-settings-daemon to delimit values, restricted
to output.
The purpose is to help users remember that visiting some websites or
using some apps can get LOUD.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:15 +00:00
ddd4fd9c24 barLevel: Add "overdrive" capability
Implement for barLevel an overdrive area. This is a zone represented via a
different styling to indicate that you are bypassing the normal zone of
a given level, without reaching yet the maximum limit.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:14 +00:00
d2a97e7f1d volume: Allow volume above 100%
Depending on hardware and recorded volume level, turning up the speakers
to the maximum volume may not be enough and the user will want to amplify
the volume above 100%. Currently this requires opening the sound Settings
panel which gets cumbersome when required repeatedly.

To support this case better, allow raising the sound volume above 100%
directly from the system menu if the feature is enabled via the
`allow-volume-above-100-percent` key in `org.gnome.desktop.sound`.
2018-07-31 18:14:13 +00:00
aa75e89216 osdWindow: Allow levels above 100%
Allow osd representing levels that can be more than 100% by accepting
an optional parameter setting that maximum level.
gnome-settings-daemon will use this to indicate volume levels above 100%,
which our own volume indicator will soon support as well.
2018-07-31 18:14:11 +00:00
3f756dc608 barLevel: Support maxValue higher than 1
Ensure that both barLevel and slider can support a higher maxValue than 1
and computes various positions based on it.
It defaults to 1 if not set.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:10 +00:00
ed8e89bc19 osdWindow: Reuse BarLevel drawing functionality
Reuse the BarLevel class to get similar drawing behavior as Slider.
Rename theme css impacted properties and ensure that the osdWindow
remains accessible.
Ensure we don't force setting a custom border color like on the OSD.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:10 +00:00
c90a4e4849 levelBar: Factor out bar drawing
Split drawing logic from Slider to BarLevel subclass.
This changes part of the theme css from -slider- to -barlevel-.

https://bugzilla.gnome.org/show_bug.cgi?id=790280.
2018-07-31 18:14:09 +00:00
f433b12d6e system: Don't execute Settings
In a9ad91c831, a bug was introduced in the following code:

```c
            this._settingsAction.connect('clicked',
                                         this._onSettingsClicked().bind(this));
```

Notice that the callback is being executed! This commit
fixes that by removing the '()' from the callback.
2018-07-31 13:31:59 -03:00
7ca418a79a Explicitly convert raw data to strings
As strings are guaranteed to use UTF-8 in the GNOME platform, generic
file APIs like g_file_load_contents() return raw data instead. Since
gjs' recent update to mozjs60, this data is now returns as Uint8Array
which cannot simply be treated as string - its toString() method boils
down to arr.join(',') - so use gjs' new ByteArray module to explicitly
convert the data.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/179
2018-07-31 16:28:53 +00:00
a9ad91c831 system: Pick up Settings name and icon from app
The settings action button in the system menu simply launches
gnome-control-center, so we want its icon (and accessible name)
to always match the app. So instead of keeping the button in-sync
with Settings, just look up that information from the app itself.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/433
2018-07-31 16:52:47 +02:00
bd1c7774ee system: Enforce symbolic icons in action buttons
We can simply request the symbolic variant from CSS so that we don't
have to append '-symbolic' to all the names. This will always make
it easier to pick up that information from external sources (like
.desktop files).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/433
2018-07-31 16:52:47 +02:00
91da3789bc windowManager: Fix switch animation between non-adjacent workspaces
Commit e5c95b910d refactored the workspace animation to also handle
animations that involve all surrounding workspaces, but due to an
ill-advised review comment (guess whose) it broke the animation
for non-neighboring workspaces.

Update the code to handle correctly whether in a given direction:
 - we have the target workspace of a given index
 - we have a neighboring workspace
 - we don't need to animate anything

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/182
2018-07-31 06:51:35 +02:00
2991f9f102 util: Fix code style
The C code introduced in 49d8ff38e did not follow
GNOME Shell's C code style. This commit adjusts it
to comply with the correct code style.
2018-07-30 21:23:28 -03:00
49d8ff38e7 Add check_cloexec_fds debug command
Add a debug command (to be executed manually via Alt+F2) to check
that all of gnome-shell's file descriptors have the CLOEXEC flag set.
This is important so that internal file descriptors do not get passed
to apps when they are launched.

It prints a warning message for every fd that does not have the flag set.

fdwalk() is used from the standard library if available (it is not
available in glibc), otherwise we use the same implementation as glib
has internally.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132
2018-07-30 23:11:41 +00:00
4b522a02c3 shell-app: remove child_setup from app launching
When the amount of free memory on the system is somewhat low, gnome-shell
will sometimes fail to launch apps, reporting the error:
  fork(): Cannot allocate memory

fork() is failing here because while cloning the process virtual address
space, Linux worries that the thread being forked may end up COWing the
entire address space of the parent process (gnome-shell, which is
memory-hungry), and there is not enough free memory to permit that to
happen. This check is somewhat irrelevant because we are only forking
to immediately exec(), which will discard the whole virtual address
space anyway.

This issue can be avoided by using a new optimized gspawn codepath in
the latest glib development version, which uses posix_spawn() internally.

For the optimized codepath to be used, we must not pass a child_setup
function, so the the file descriptor management is reimplemented here
using new glib API to pass fds to the child process. The old API will
continue to be used on older glib versions.

We must also change the spawn flags for this code path to be hit.
I checked that gnome-shell's open file descriptors are all CLOEXEC
so using G_SPAWN_LEAVE_DESCRIPTORS_OPEN should be safe.

This will result in more resilient app launching when memory is low,
since the optimized spawn path avoids cloning the virtual address
space of the parent process (gnome-shell) and avoids the irrelevant
memory overcommit check.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/132
2018-07-30 23:11:41 +00:00
ebe6f59d7e windowManager: Make workspace switching gestures follow motion
When 4fg swipe motion happens, set up early the workspace switching
animation with all surrounding workspaces. This allows us to move
all content back and forth in any direction. This works on both
touchcreens and touchpads.

When the gesture is activated, the same data is reused to follow
up with the tween animation.

The threshold has been also doubled, it was fairly small to start
with, and feels better now that workspaces stick to fingers.

https://bugzilla.gnome.org/show_bug.cgi?id=788994
2018-07-30 21:20:52 +00:00
e5c95b910d windowManager: Refactor workspace switching animations
Besides the separation into distinct functions, the stored data has
been made able to generically store windows from all surrounding
workspaces. All while keeping a special mode to animate between two
workspaces (The usual till now), this is the only mode exercised so
far.

In order to ease animations, all window groups are now children of
a common container, which is then animated.
2018-07-30 21:20:50 +00:00
2f76951658 windowManager: Declare variables
Fixes warnings from GJS.
2018-07-30 21:20:49 +00:00
3efd296fc3 app: Consider "new-window" action for opening new windows
While can_open_new_window() uses some elaborate heuristics to predict
whether an application can open multiple windows, open_new_window()
will always simply relaunch the application. This is often the best
we can do, but when an application provides a "new-window" action in
its .desktop file or on the bus, it is much more likely to work as
expected than blindly activating the app and hoping for a particular
behavior.

https://bugzilla.gnome.org/show_bug.cgi?id=756844
2018-07-30 19:21:40 +00:00
6688610c23 screenshot: Add PickColor() method to Screenshot interface
Use the newly added API to implement a color picker method in the
screenshot interface, so that the desktop portal can expose it
to applications.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
d2c75801ea screenshot: Allow bypassing lockdown setting
The setting is only relevant when writing to disk is required. We
will soon expose a screenshot method that doesn't, so make it
possible to ignore it.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
be84a00022 screenshot: Add pick_color() method
Graphical applications like GIMP or GIMP allow picking colors from
any location on-screen. In order to keep supporting this feature
on wayland and in sandboxed apps, we will expose an appropriate
method in the Screenshot interface, so first add a corresponding
method to ShellScreenshot.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:10 +00:00
da537cda43 screenshot: Adopt GIO's async pattern
A custom callback type is more convenient, but only as long as no
other callback type is required. We are about to add functionality
that does not return the filename to a screenshot saved on disk, so
prepare for that by moving to GIO's generic async callback pattern.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
2018-07-30 16:55:09 +00:00
304c667bca windowManager: Add top edge drag gesture to unmake fullscreen window
Fullscreen windows cannot be restored by touch device users unless the
application adds support for it.
As it is unlikely to change all application lets introduce a top edge
drag gesture which unmakes fullscreen windows.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/123
2018-07-28 12:11:41 +02:00
879a81abeb remoteAccess: Make indicator orange
Make the indicator for active remote access use the warning color, to
indicate the severity of allowing remote access.

This only makes the indicator icon orange; the icon in the system menu
is still white.
2018-07-27 18:10:35 +02:00
e68ca5adbd Updated Spanish translation 2018-07-27 13:38:45 +02:00
cf69fe4b18 gdm, util: Always allow to retry login in unlock mode
When in lockscreen mode there's no point of resetting the auth login as there's
no welcome screen, and that would just cause the UI to freeze, with no reason.
This could have been useful if we were stopping the user to login for a given
time after ALLOWED_FAILURES attempts, but this is not the case yet.
2018-07-25 20:32:42 +00:00
8f848925f6 authPrompt: Do not enable sensitivity if retries are disallowed
Set the sensitivity of the UI according to the canRetry parameter and thus
if no more logins are allowed don't take any input.

Fixes #311
2018-07-25 20:32:42 +00:00
d21657fe61 authPrompt: Unset preemptiveAnswer on reset
When we get a reset signal the preemptiveAnswer should be also unset or it will
be used next time the user authPrompt will be activated, even without any further
user interaction.

Fixes #311
2018-07-25 20:32:41 +00:00
ce3555382b workspaceThumbnail: Sync clone position changes with actor
We need to update the clone position if window actor (not the meta window)
position changed.

https://bugzilla.gnome.org/show_bug.cgi?id=776588
2018-07-24 11:08:25 +00:00
837a00c3f0 workspace: Recompute bounding box on window 'position-changed'
We need to update the clone position if window size changed
also, rename meta window 'size-changed' callback accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=792681
2018-07-24 11:08:25 +00:00
132c8e0cf8 icons: update to current metaphors
- sync with adwaita-icon-theme metaphors
2018-07-24 11:05:55 +02:00
9c62522419 Update POTFILES.in 2018-07-23 23:14:12 +02:00
0d5bae3844 Add remote access indication and control
Add an indicator for when there is something access the display server
remotely. This could be 1) remote desktop, 2) screen cast or 3) remote
control, but all effectively applications using
org.freedesktop.portal.ScreenCast or org.gnome.portal.RemoteDesktop as
well as gnome-remote-desktop using the corresponding org.gnome.Mutter
APIs directly.

As it is now, it'll simply show a single icon for when anything is
having an active session, and a single action "Turn off" that'll close
every active session.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/160
2018-07-23 14:03:26 +02:00
97f6a35b46 Update French translation 2018-07-20 09:00:03 +00:00
43e8dfacb4 build: Don't use libdir for systemd unit path
Some systems define it to /usr/lib64 on 64-bit systems, which is not
where systemd looks for unit files. Just hardcode 'lib' in the install
prefix until we get to use the pkg-config file.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/424
2018-07-18 23:03:30 +02:00
46 changed files with 2229 additions and 1074 deletions

19
NEWS
View File

@ -1,3 +1,22 @@
3.29.90
=======
* Add remote access indication on wayland [Jonas; !160]
* Fix wrong window positions in overview on wayland [Marco; #776588]
* Add gesture to unfullscreen a window [Jan-Michael; !123]
* Add PickColor method to screenshot D-Bus interface [Florian; #286]
* Consider "new-window" action when opening new windows [Florian; #756844]
* Make workspace switching gestures follow motion [Carlos; #788994]
* Support audio volumes above 100% [Didier; #790280]
* Misc. bug fixes [Florian, Daniel; #424, !132, !182, #433, !179, #786496]
Contributors:
Jonas Ådahl, Jan-Michael Brummer, Piotr Drąg, Daniel Drake, Carlos Garnacho,
Florian Müllner, Georges Basile Stavracas Neto, Didier Roche, Jakub Steiner,
Marco Trevisan (Treviño)
Translators:
Charles Monzat [fr], Daniel Mustieles [es]
3.29.4 3.29.4
====== ======
* Fix "Clear All" for calendar events [Florian; #325] * Fix "Clear All" for calendar events [Florian; #325]

View File

@ -24,3 +24,9 @@
/* Define if _NL_TIME_FIRST_WEEKDATE is available */ /* Define if _NL_TIME_FIRST_WEEKDATE is available */
#mesondefine HAVE__NL_TIME_FIRST_WEEKDAY #mesondefine HAVE__NL_TIME_FIRST_WEEKDAY
/* Define if you have the `g_desktop_app_info_launch_uris_as_manager_with_fds` function */
#mesondefine HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
/* Define if fdwalk is available in libc */
#mesondefine HAVE_FDWALK

View File

@ -0,0 +1,6 @@
[org.gnome.mutter:GNOME]
attach-modal-dialogs=true
edge-tiling=true
dynamic-workspaces=true
workspaces-only-on-primary=true
focus-change-on-pointer-rest=true

View File

@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=GNOME settings overrides migration
NoDisplay=true
Exec=@libexecdir@/gnome-shell-overrides-migration.sh

View File

@ -92,6 +92,16 @@ schema = configure_file(
configuration: schemaconf, configuration: schemaconf,
install_dir: schemadir install_dir: schemadir
) )
install_data('00_org.gnome.shell.gschema.override', install_dir: schemadir)
overrides_migration_conf = configuration_data()
overrides_migration_conf.set('libexecdir', libexecdir)
overrides_migration = configure_file(
input: 'gnome-shell-overrides-migration.desktop.in',
output: 'gnome-shell-overrides-migration.desktop',
configuration: overrides_migration_conf,
install_dir: autostartdir
)
if have_systemd if have_systemd
unitconf = configuration_data() unitconf = configuration_data()

View File

@ -91,6 +91,23 @@
<arg type="s" direction="out" name="filename_used"/> <arg type="s" direction="out" name="filename_used"/>
</method> </method>
<!--
PickColor:
Picks a color and returns the result.
The @result vardict contains:
<variablelist>
<varlistentry>
<term>color (ddd)</term>
<listitem><para>The color, RGB values in the range [0,1].</para></listitem>
</varlistentry>
</variablelist>
-->
<method name="PickColor">
<arg type="a{sv}" direction="out" name="result"/>
</method>
<!-- <!--
FlashArea: FlashArea:
@x: the X coordinate of the area to flash @x: the X coordinate of the area to flash

View File

@ -190,6 +190,7 @@
</key> </key>
</schema> </schema>
<!-- unused, change 00_org.gnome.shell.gschema.override instead -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/" <schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@"> gettext-domain="@GETTEXT_PACKAGE@">
<key name="attach-modal-dialogs" type="b"> <key name="attach-modal-dialogs" type="b">

View File

@ -128,12 +128,15 @@ StScrollBar {
.slider { .slider {
height: 1em; height: 1em;
-slider-height: 0.3em; -barlevel-height: 0.3em;
-slider-background-color: $insensitive_bg_color; //background of the trough -barlevel-background-color: $insensitive_bg_color; //background of the trough
-slider-border-color: $borders_color; //trough border color -barlevel-border-color: $borders_color; //trough border color
-slider-active-background-color: $selected_bg_color; //active trough fill -barlevel-active-background-color: $selected_bg_color; //active trough fill
-slider-active-border-color: darken($selected_bg_color,10%); //active trough border -barlevel-active-border-color: darken($selected_bg_color,10%); //active trough border
-slider-border-width: 1px; -barlevel-overdrive-color: $destructive_color;
-barlevel-overdrive-border-color: darken($destructive_color,10%);
-barlevel-overdrive-separator-width: 0.2em;
-barlevel-border-width: 1px;
-slider-handle-radius: 6px; -slider-handle-radius: 6px;
} }
@ -585,13 +588,11 @@ StScrollBar {
.osd-monitor-label { font-size: 3em; } .osd-monitor-label { font-size: 3em; }
.level { .level {
height: 0.6em; height: 0.6em;
border-radius: 0.3em; -barlevel-height: 0.6em;
background-color: transparentize(darken($osd_bg_color,15%),0.5); -barlevel-background-color: transparentize(darken($osd_bg_color,15%),0.5);
color: $osd_fg_color; -barlevel-active-background-color: $osd_fg_color;
} -barlevel-overdrive-color: $destructive_color;
.level-bar { -barlevel-overdrive-separator-width: 0.2em;
background-color: $osd_fg_color;
border-radius: 0.3em;
} }
} }
@ -825,6 +826,8 @@ StScrollBar {
.screencast-indicator { color: $warning_color; } .screencast-indicator { color: $warning_color; }
.remote-access-indicator { color: $warning_color; }
&.solid { &.solid {
background-color: black; background-color: black;
/* transition from transparent to solid */ /* transition from transparent to solid */
@ -1122,6 +1125,7 @@ StScrollBar {
} }
.system-menu-action { .system-menu-action {
-st-icon-style: symbolic;
color: $fg_color; color: $fg_color;
border-radius: 32px; /* wish we could do 50% */ border-radius: 32px; /* wish we could do 50% */
padding: 13px; padding: 13px;

View File

@ -14,7 +14,7 @@
id="svg7384" id="svg7384"
height="32" height="32"
sodipodi:docname="key-layout.svg" sodipodi:docname="key-layout.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"> inkscape:version="0.92.3 (2405546, 2018-03-11)">
<sodipodi:namedview <sodipodi:namedview
pagecolor="#ffffff" pagecolor="#ffffff"
bordercolor="#666666" bordercolor="#666666"
@ -24,17 +24,21 @@
guidetolerance="10" guidetolerance="10"
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:window-width="1919" inkscape:window-width="3440"
inkscape:window-height="1011" inkscape:window-height="1376"
id="namedview19" id="namedview19"
showgrid="false" showgrid="false"
inkscape:zoom="14.75" inkscape:zoom="1"
inkscape:cx="1.220339" inkscape:cx="46.246852"
inkscape:cy="11.842802" inkscape:cy="17.474578"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="55" inkscape:window-y="27"
inkscape:window-maximized="0" inkscape:window-maximized="1"
inkscape:current-layer="svg7384" /> inkscape:current-layer="svg7384">
<inkscape:grid
type="xygrid"
id="grid861" />
</sodipodi:namedview>
<metadata <metadata
id="metadata90"> id="metadata90">
<rdf:RDF> <rdf:RDF>
@ -92,23 +96,34 @@
style="display:inline" style="display:inline"
id="g4953" /> id="g4953" />
<g <g
style="stroke-width:0.5;enable-background:new"
id="g3561"
inkscape:label="preferences-desktop-locale" inkscape:label="preferences-desktop-locale"
id="g11728" transform="matrix(2,0,0,2,135.99464,-895.9793)">
transform="matrix(2,0,0,2,-522.0004,-1086)"
style="display:inline;stroke-width:1">
<rect
style="fill:none;stroke:none;stroke-width:1"
id="rect11724"
width="16"
height="16"
x="20"
y="326"
transform="translate(241.0002,217)" />
<path <path
style="fill:#e5e5e5;fill-opacity:1;stroke:none;stroke-width:1" sodipodi:nodetypes="cc"
d="m 265.69612,545.23396 c -3.58218,0 -4.66582,1.39975 -4.66582,1.39975 v 10.04946 c 0,0 1.08364,-1.07673 4.66582,-1.07673 2.9161,0 4.47225,1.07673 7.17818,1.07673 2.08923,0 3.19429,-1.39975 3.19429,-1.39975 v -10.04946 c 0,0 -1.14095,1.04084 -3.23018,1.04084 -3.3734,0 -3.97619,-1.04084 -7.14229,-1.04084 z m 2.93145,2.77148 c 1.32876,0 2.375,1.08037 2.375,2.4375 0,1.35713 -1.04624,2.46875 -2.375,2.46875 -1.32876,0 -2.40625,-1.11162 -2.40625,-2.46875 0,-1.35713 1.07749,-2.4375 2.40625,-2.4375 z m -4.5625,0.96875 0.96875,1.03125 -0.9375,-0.0312 0.9375,1 -0.96875,-0.0312 0.96875,1.03125 -1,-0.0312 0.0312,-1 h -0.0312 l 0.0312,-0.9688 h -0.0312 z m 4.5625,0 c -0.794,0 -1.46875,0.6578 -1.46875,1.46875 0,0.81095 0.67475,1.46875 1.46875,1.46875 0.79399,0 1.4375,-0.6578 1.4375,-1.46875 0,-0.81095 -0.64351,-1.46875 -1.4375,-1.46875 z m 4.375,0 v 1 l 0.0312,0.96875 h -0.0312 l 0.0312,1 -1,0.0312 0.96875,-1.03125 -0.96875,0.0312 0.9375,-1 -0.9375,0.0312 z m -7.9375,2.96875 0.96875,1.03125 -1,-0.0312 z m 6.9375,0 0.0312,1 -1,0.0312 z m -5.9375,1 0.96875,1.03125 -1,-0.0312 z m 4.9375,0 0.0312,1 -1,0.0312 z"
id="path11726"
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
sodipodi:nodetypes="sccssccsssssssccccccccccccsssssccccccccccccccccccccccccccc" /> id="path3535"
d="m -65,450 v 12"
style="fill:#e5e5e5;fill-opacity:1;fill-rule:evenodd;stroke:#e5e5e5;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3537"
d="m -65,456 h 4 l 1,2 h 5 v -6 h -4 l -1,-2 h -5 z"
style="fill:none;fill-rule:evenodd;stroke:#e5e5e5;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;vector-effect:none;fill:#e5e5e5;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m -65,456 h 4 l 1,2 h 5 v -6 h -4 l -1,-2 h -5 z"
id="path3539"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:none;stroke-width:0.89050001;marker:none;enable-background:new"
id="rect3543"
y="448"
x="-68"
height="16"
width="16" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -13,10 +13,102 @@
height="64px" height="64px"
id="svg3393" id="svg3393"
version="1.1" version="1.1"
inkscape:version="0.48.5 r10040" inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="New document 2"> sodipodi:docname="no-notifications.svg">
<defs <defs
id="defs3395" /> id="defs3395">
<clipPath
id="clipPath6262-0"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6264-6"
width="3.8250003"
height="6.3750005"
x="26.849981"
y="220.75" />
</clipPath>
<clipPath
id="clipPath6258-0"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6260-6"
width="2.8977275"
height="5.3129687"
x="26.965673"
y="221.28162" />
</clipPath>
<clipPath
id="clipPath6254-6"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none"
id="rect6256-6"
width="1.876245"
height="4.8783236"
x="26.998718"
y="221.50153" />
</clipPath>
<clipPath
id="clipPath8028-3"
clipPathUnits="userSpaceOnUse">
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m -73,-30 -7,-7 v -4.5 h 16.5 v 4.5 l -7.5,7 z"
id="path8030-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6810-7-87-7">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none"
id="rect6812-2-4-5"
width="14"
height="11"
x="21"
y="281" />
</clipPath>
<clipPath
id="clipPath6262"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6264"
width="3.8250003"
height="6.3750005"
x="26.849981"
y="220.75" />
</clipPath>
<clipPath
id="clipPath6258"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none"
id="rect6260"
width="2.8977275"
height="5.3129687"
x="26.965673"
y="221.28162" />
</clipPath>
<clipPath
id="clipPath6254"
clipPathUnits="userSpaceOnUse">
<rect
style="color:#bebebe;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:2;marker:none"
id="rect6256"
width="1.876245"
height="4.8783236"
x="26.998718"
y="221.50153" />
</clipPath>
<inkscape:path-effect
effect="spiro"
id="path-effect3951"
is_visible="true" />
</defs>
<sodipodi:namedview <sodipodi:namedview
id="base" id="base"
pagecolor="#ffffff" pagecolor="#ffffff"
@ -24,17 +116,17 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="5.5" inkscape:zoom="1"
inkscape:cx="32" inkscape:cx="125.08157"
inkscape:cy="32" inkscape:cy="-13.805087"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:grid-bbox="true" inkscape:grid-bbox="true"
inkscape:window-width="697" inkscape:window-width="1664"
inkscape:window-height="613" inkscape:window-height="1034"
inkscape:window-x="100" inkscape:window-x="1479"
inkscape:window-y="77" inkscape:window-y="252"
inkscape:window-maximized="0" /> inkscape:window-maximized="0" />
<metadata <metadata
id="metadata3398"> id="metadata3398">
@ -54,7 +146,7 @@
inkscape:groupmode="layer"> inkscape:groupmode="layer">
<g <g
style="display:inline" style="display:inline"
transform="matrix(4,0,0,4,0.29733827,-0.35415646)" transform="matrix(4,0,0,4,-79.702662,-0.35415646)"
id="g19245"> id="g19245">
<g <g
id="g19247" id="g19247"
@ -71,15 +163,15 @@
transform="translate(-323.02908,-649.02581)"> transform="translate(-323.02908,-649.02581)">
<path <path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 l 0,2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 1.61114,0 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 l 0,-5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z" d="m 331.9377,653 c 0.0187,0.16677 0.0625,0.32822 0.0625,0.5 0,2.48528 -2.01472,4.5 -4.5,4.5 -0.11769,0 -0.22834,-0.0224 -0.34375,-0.0312 v 2.21875 c 0,1.00412 0.80838,1.8125 1.8125,1.8125 l 1.54511,-5e-5 2,2.04688 2.0625,-2.04688 h 1.61114 c 1.00413,0 1.8125,-0.80838 1.8125,-1.8125 v -5.375 c 0,-1.00412 -0.80837,-1.8125 -1.8125,-1.8125 z"
id="path19253" id="path19253"
sodipodi:nodetypes="csscsscccssssc" sodipodi:nodetypes="csscsscccssssc"
style="opacity:0.5;color:#000000;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> style="color:#000000;display:inline;overflow:visible;visibility:visible;opacity:0.5;fill:#c3c3c3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;enable-background:accumulate" />
<path <path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 1.03125,0 -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 l 0.0625,1.3751 -1.03125,0 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 L 326.96895,651 z" d="m 327.5002,650 c -1.933,0 -3.5,1.567 -3.5,3.5 0,1.933 1.567,3.5 3.5,3.5 1.933,0 3.5,-1.567 3.5,-3.5 0,-1.933 -1.567,-3.5 -3.5,-3.5 z m -0.53125,1 h 1.03125 l -0.0625,1.375 a 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.125,0.125 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 l 1.15625,-0.75 0.5,0.90625 -1.21875,0.625 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0.0937 0.19951718,0.19951718 0 0 0 0,0.0625 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0625 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0312,0.0312 l 1.25,0.625 -0.53125,0.90625 -1.15625,-0.781 a 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,0 0.19951718,0.19951718 0 0 0 -0.125,0.0937 0.19951718,0.19951718 0 0 0 -0.0312,0.0312 0.19951718,0.19951718 0 0 0 0,0.0312 0.19951718,0.19951718 0 0 0 0,0.0625 L 328.0002,656 h -1.03125 l 0.0937,-1.375 a 0.19951718,0.19951718 0 0 0 -0.0312,-0.0937 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0625,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 0.19951718,0.19951718 0 0 0 -0.0937,0.0312 l -1.1875,0.78125 -0.5,-0.90625 1.25,-0.625 a 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,-0.0625 0.19951718,0.19951718 0 0 0 -0.0312,-0.0312 0.19951718,0.19951718 0 0 0 -0.0312,0 l -1.25,-0.625 0.5,-0.90625 1.1875,0.75 a 0.19951718,0.19951718 0 0 0 0.0312,0.0312 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0625,0 0.19951718,0.19951718 0 0 0 0.0312,0 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0312 0.19951718,0.19951718 0 0 0 0,-0.0312 0.19951718,0.19951718 0 0 0 0.0312,-0.0625 0.19951718,0.19951718 0 0 0 0,-0.0312 z"
id="path19255" id="path19255"
style="color:#000000;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate" />
</g> </g>
<g <g
id="g19257" id="g19257"
@ -110,5 +202,22 @@
style="display:inline" style="display:inline"
transform="translate(-323.02908,-649.02581)" /> transform="translate(-323.02908,-649.02581)" />
</g> </g>
<g
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
inkscape:label="preferences-system-notifications"
id="g13967"
transform="matrix(4,0,0,4,-1044.0008,-2172)">
<path
inkscape:connector-curvature="0"
d="m 268.94244,544.94838 c -2.20914,0 -3.33013,1.5 -4,4 l -1,5 c -0.10831,0.54156 -0.44772,1 -1,1 v 1 h 12 v -1 c -0.55229,0 -0.89169,-0.45844 -1,-1 l -1,-5 c -0.53033,-2.5 -1.79086,-4 -4,-4 z"
id="path40220"
sodipodi:nodetypes="ccsccccscc"
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal" />
<path
inkscape:connector-curvature="0"
d="m 269.11822,556.94838 a 1.5,1.5 0 0 0 1.41211,1 1.5,1.5 0 0 0 1.41211,-1 z"
id="path40774"
style="opacity:1;vector-effect:none;fill:#bebebe;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:normal" />
</g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -242,11 +242,11 @@ var AuthPrompt = new Lang.Class({
this.emit('prompted'); this.emit('prompted');
}, },
_onVerificationFailed() { _onVerificationFailed(userVerifier, canRetry) {
this._queryingService = null; this._queryingService = null;
this.clear(); this.clear();
this.updateSensitivity(true); this.updateSensitivity(canRetry);
this.setActorInDefaultButtonWell(null); this.setActorInDefaultButtonWell(null);
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
}, },
@ -439,6 +439,7 @@ var AuthPrompt = new Lang.Class({
this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING;
this.cancelButton.reactive = true; this.cancelButton.reactive = true;
this.nextButton.label = _("Next"); this.nextButton.label = _("Next");
this._preemptiveAnswer = null;
if (this._userVerifier) if (this._userVerifier)
this._userVerifier.cancel(); this._userVerifier.cancel();

View File

@ -537,12 +537,13 @@ var ShellUserVerifier = new Lang.Class({
_verificationFailed(retry) { _verificationFailed(retry) {
// For Not Listed / enterprise logins, immediately reset // For Not Listed / enterprise logins, immediately reset
// the dialog // the dialog
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we // Otherwise, when in login mode we allow ALLOWED_FAILURES attempts.
// go back to the welcome screen. // After that, we go back to the welcome screen.
this._failCounter++; this._failCounter++;
let canRetry = retry && this._userName && let canRetry = retry && this._userName &&
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY); (this._reauthOnly ||
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY));
if (canRetry) { if (canRetry) {
if (!this.hasPendingMessages) { if (!this.hasPendingMessages) {
@ -565,7 +566,7 @@ var ShellUserVerifier = new Lang.Class({
} }
} }
this.emit('verification-failed'); this.emit('verification-failed', canRetry);
}, },
_onConversationStopped(client, serviceName) { _onConversationStopped(client, serviceName) {

View File

@ -43,6 +43,7 @@
<file>ui/audioDeviceSelection.js</file> <file>ui/audioDeviceSelection.js</file>
<file>ui/backgroundMenu.js</file> <file>ui/backgroundMenu.js</file>
<file>ui/background.js</file> <file>ui/background.js</file>
<file>ui/barLevel.js</file>
<file>ui/boxpointer.js</file> <file>ui/boxpointer.js</file>
<file>ui/calendar.js</file> <file>ui/calendar.js</file>
<file>ui/checkBox.js</file> <file>ui/checkBox.js</file>
@ -130,6 +131,7 @@
<file>ui/status/rfkill.js</file> <file>ui/status/rfkill.js</file>
<file>ui/status/volume.js</file> <file>ui/status/volume.js</file>
<file>ui/status/bluetooth.js</file> <file>ui/status/bluetooth.js</file>
<file>ui/status/remoteAccess.js</file>
<file>ui/status/screencast.js</file> <file>ui/status/screencast.js</file>
<file>ui/status/system.js</file> <file>ui/status/system.js</file>
<file>ui/status/thunderbolt.js</file> <file>ui/status/thunderbolt.js</file>

View File

@ -112,6 +112,8 @@ function createExtensionObject(uuid, dir, type) {
let metadataContents, success, tag; let metadataContents, success, tag;
try { try {
[success, metadataContents, tag] = metadataFile.load_contents(null); [success, metadataContents, tag] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) { } catch (e) {
throw new Error('Failed to load metadata.json: ' + e); throw new Error('Failed to load metadata.json: ' + e);
} }

210
js/ui/barLevel.js Normal file
View File

@ -0,0 +1,210 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Atk = imports.gi.Atk;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals;
var BarLevel = new Lang.Class({
Name: "BarLevel",
_init(value, params) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
this._maxValue = 1;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this._overdriveStart = 1;
this._barLevelWidth = 0;
if (params == undefined)
params = {}
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false,
reactive: params['reactive'] || false,
accessible_role: params['accessibleRole'] || Atk.Role.LEVEL_BAR });
this.actor.connect('repaint', this._barLevelRepaint.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
this._barLevelWidth = box.get_width();
});
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this));
},
setValue(value) {
if (isNaN(value))
throw TypeError('The bar level value must be a number');
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
setMaximumValue(value) {
if (isNaN(value))
throw TypeError('The bar level max value must be a number');
this._maxValue = Math.max(value, 1);
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint();
},
setOverdriveStart(value) {
if (isNaN(value))
throw TypeError('The overdrive limit value must be a number');
if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`);
this._overdriveStart = value;
this._value = Math.max(Math.min(value, this._maxValue), 0);
this.actor.queue_repaint();
},
_barLevelRepaint(area) {
let cr = area.get_context();
let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size();
let barLevelHeight = themeNode.get_length('-barlevel-height');
let barLevelBorderRadius = Math.min(width, barLevelHeight) / 2;
let fgColor = themeNode.get_foreground_color();
let barLevelColor = themeNode.get_color('-barlevel-background-color');
let barLevelActiveColor = themeNode.get_color('-barlevel-active-background-color');
let barLevelOverdriveColor = themeNode.get_color('-barlevel-overdrive-color');
let barLevelBorderWidth = Math.min(themeNode.get_length('-barlevel-border-width'), 1);
let [hasBorderColor, barLevelBorderColor] =
themeNode.lookup_color('-barlevel-border-color', false);
if (!hasBorderColor)
barLevelBorderColor = barLevelColor;
let [hasActiveBorderColor, barLevelActiveBorderColor] =
themeNode.lookup_color('-barlevel-active-border-color', false);
if (!hasActiveBorderColor)
barLevelActiveBorderColor = barLevelActiveColor;
let [hasOverdriveBorderColor, barLevelOverdriveBorderColor] =
themeNode.lookup_color('-barlevel-overdrive-border-color', false);
if (!hasOverdriveBorderColor)
barLevelOverdriveBorderColor = barLevelOverdriveColor;
const TAU = Math.PI * 2;
let endX = 0;
if (this._maxValue > 0)
endX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._value / this._maxValue;
let overdriveSeparatorX = barLevelBorderRadius + (width - 2 * barLevelBorderRadius) * this._overdriveStart / this._maxValue;
let overdriveActive = this._overdriveStart !== this._maxValue;
let overdriveSeparatorWidth = 0;
if (overdriveActive)
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
/* background bar */
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* normal progress bar */
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
cr.lineTo(x, (height - barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* overdrive progress barLevel */
x = Math.min(endX, overdriveSeparatorX) + overdriveSeparatorWidth / 2;
if (this._value > this._overdriveStart) {
cr.moveTo(x, (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(x, (height - barLevelHeight) / 2);
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelOverdriveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
}
/* end progress bar arc */
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
/* draw overdrive separator */
if (overdriveActive) {
cr.moveTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX + overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height + barLevelHeight) / 2);
cr.lineTo(overdriveSeparatorX - overdriveSeparatorWidth / 2, (height - barLevelHeight) / 2);
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, fgColor);
else
Clutter.cairo_set_source_color(cr, barLevelColor);
cr.fill();
}
cr.$dispose();
},
_getCurrentValue(actor) {
return this._value;
},
_getOverdriveStart(actor) {
return this._overdriveStart;
},
_getMinimumValue(actor) {
return 0;
},
_getMaximumValue(actor) {
return this._maxValue;
},
_setCurrentValue(actor, value) {
this._value = value;
},
_valueChanged(barLevel, value, property) {
this._customAccessible.notify("accessible-value");
},
get value() {
return this._value;
}
});
Signals.addSignalMethods(BarLevel.prototype);

View File

@ -472,6 +472,8 @@ var KeyboardModel = new Lang.Class({
_loadModel(groupName) { _loadModel(groupName) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName)); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName));
let [success, contents] = file.load_contents(null); let [success, contents] = file.load_contents(null);
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
return JSON.parse(contents); return JSON.parse(contents);
}, },
@ -490,13 +492,18 @@ var FocusTracker = new Lang.Class({
_init() { _init() {
this._currentWindow = null; this._currentWindow = null;
this._currentWindowPositionId = 0;
global.display.connect('notify::focus-window', () => { global.display.connect('notify::focus-window', () => {
this._setCurrentWindow(global.display.focus_window); this._setCurrentWindow(global.display.focus_window);
this.emit('window-changed', this._currentWindow); this.emit('window-changed', this._currentWindow);
}); });
global.display.connect('grab-op-begin', (display, window, op) => {
if (window == this._currentWindow &&
(op == Meta.GrabOp.MOVING || op == Meta.GrabOp.KEYBOARD_MOVING))
this.emit('reset');
});
/* Valid for wayland clients */ /* Valid for wayland clients */
Main.inputMethod.connect('cursor-location-changed', (o, rect) => { Main.inputMethod.connect('cursor-location-changed', (o, rect) => {
let newRect = { x: rect.get_x(), y: rect.get_y(), width: rect.get_width(), height: rect.get_height() }; let newRect = { x: rect.get_x(), y: rect.get_y(), width: rect.get_width(), height: rect.get_height() };
@ -518,18 +525,7 @@ var FocusTracker = new Lang.Class({
}, },
_setCurrentWindow(window) { _setCurrentWindow(window) {
if (this._currentWindow)
this._currentWindow.disconnect(this._currentWindowPositionId);
this._currentWindow = window; this._currentWindow = window;
if (window) {
this._currentWindowPositionId = this._currentWindow.connect('position-changed', () => {
if (global.display.get_grab_op() == Meta.GrabOp.NONE)
this.emit('position-changed');
else
this.emit('reset');
});
}
}, },
_setCurrentRect(rect) { _setCurrentRect(rect) {

View File

@ -4,6 +4,7 @@ const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const St = imports.gi.St; const St = imports.gi.St;
const BarLevel = imports.ui.barLevel;
const Lang = imports.lang; const Lang = imports.lang;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Main = imports.ui.main; const Main = imports.ui.main;
@ -17,16 +18,18 @@ var LEVEL_ANIMATION_TIME = 0.1;
var LevelBar = new Lang.Class({ var LevelBar = new Lang.Class({
Name: 'LevelBar', Name: 'LevelBar',
Extends: BarLevel.BarLevel,
_init() { _init() {
this._level = 0; this._level = 0;
this._maxLevel = 100;
this.actor = new St.Bin({ style_class: 'level', let params = {
x_align: St.Align.START, styleClass: 'level',
y_fill: true }); }
this._bar = new St.Widget({ style_class: 'level-bar' }); this.parent(this._level, params);
this.actor.set_child(this._bar); this.actor.accessible_name = _("Volume");
this.actor.connect('notify::width', () => { this.level = this.level; }); this.actor.connect('notify::width', () => { this.level = this.level; });
}, },
@ -36,12 +39,19 @@ var LevelBar = new Lang.Class({
}, },
set level(value) { set level(value) {
this._level = Math.max(0, Math.min(value, 100)); this._level = Math.max(0, Math.min(value, this._maxLevel));
let alloc = this.actor.get_allocation_box(); this.setValue(this._level / 100);
let newWidth = Math.round((alloc.x2 - alloc.x1) * this._level / 100); },
if (newWidth != this._bar.width)
this._bar.width = newWidth; get maxLevel() {
return this._maxLevel;
},
set maxLevel(value) {
this._maxLevel = Math.max(100, value);
this.setMaximumValue(this._maxLevel / 100);
} }
}); });
@ -140,6 +150,12 @@ var OsdWindow = new Lang.Class({
} }
}, },
setMaxLevel(maxLevel) {
if (maxLevel === undefined)
maxLevel = 100;
this._level.maxLevel = maxLevel;
},
show() { show() {
if (!this._icon.gicon) if (!this._icon.gicon)
return; return;
@ -189,6 +205,7 @@ var OsdWindow = new Lang.Class({
this.actor.hide(); this.actor.hide();
this.setLabel(null); this.setLabel(null);
this.setLevel(null); this.setLevel(null);
this.setMaxLevel(null);
}, },
_relayout() { _relayout() {
@ -233,24 +250,25 @@ var OsdWindowManager = new Lang.Class({
this._osdWindows.length = Main.layoutManager.monitors.length; this._osdWindows.length = Main.layoutManager.monitors.length;
}, },
_showOsdWindow(monitorIndex, icon, label, level) { _showOsdWindow(monitorIndex, icon, label, level, maxLevel) {
this._osdWindows[monitorIndex].setIcon(icon); this._osdWindows[monitorIndex].setIcon(icon);
this._osdWindows[monitorIndex].setLabel(label); this._osdWindows[monitorIndex].setLabel(label);
this._osdWindows[monitorIndex].setLevel(level); this._osdWindows[monitorIndex].setLevel(level);
this._osdWindows[monitorIndex].setMaxLevel(maxLevel);
this._osdWindows[monitorIndex].show(); this._osdWindows[monitorIndex].show();
}, },
show(monitorIndex, icon, label, level) { show(monitorIndex, icon, label, level, maxLevel) {
if (monitorIndex != -1) { if (monitorIndex != -1) {
for (let i = 0; i < this._osdWindows.length; i++) { for (let i = 0; i < this._osdWindows.length; i++) {
if (i == monitorIndex) if (i == monitorIndex)
this._showOsdWindow(i, icon, label, level); this._showOsdWindow(i, icon, label, level, maxLevel);
else else
this._osdWindows[i].cancel(); this._osdWindows[i].cancel();
} }
} else { } else {
for (let i = 0; i < this._osdWindows.length; i++) for (let i = 0; i < this._osdWindows.length; i++)
this._showOsdWindow(i, icon, label, level); this._showOsdWindow(i, icon, label, level, maxLevel);
} }
}, },

View File

@ -313,6 +313,8 @@ var PadDiagram = new Lang.Class({
_init(params) { _init(params) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css'); let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css');
let [success, css, etag] = file.load_contents(null); let [success, css, etag] = file.load_contents(null);
if (css instanceof Uint8Array)
css = imports.byteArray.toString(css);
this._curEdited = null; this._curEdited = null;
this._prevEdited = null; this._prevEdited = null;
this._css = css; this._css = css;

View File

@ -710,6 +710,7 @@ var AggregateMenu = new Lang.Class({
this._bluetooth = null; this._bluetooth = null;
} }
this._remoteAccess = new imports.ui.status.remoteAccess.RemoteAccessApplet();
this._power = new imports.ui.status.power.Indicator(); this._power = new imports.ui.status.power.Indicator();
this._rfkill = new imports.ui.status.rfkill.Indicator(); this._rfkill = new imports.ui.status.rfkill.Indicator();
this._volume = new imports.ui.status.volume.Indicator(); this._volume = new imports.ui.status.volume.Indicator();
@ -730,6 +731,7 @@ var AggregateMenu = new Lang.Class({
if (this._bluetooth) { if (this._bluetooth) {
this._indicators.add_child(this._bluetooth.indicators); this._indicators.add_child(this._bluetooth.indicators);
} }
this._indicators.add_child(this._remoteAccess.indicators);
this._indicators.add_child(this._rfkill.indicators); this._indicators.add_child(this._rfkill.indicators);
this._indicators.add_child(this._volume.indicators); this._indicators.add_child(this._volume.indicators);
this._indicators.add_child(this._power.indicators); this._indicators.add_child(this._power.indicators);
@ -744,6 +746,7 @@ var AggregateMenu = new Lang.Class({
if (this._bluetooth) { if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu); this.menu.addMenuItem(this._bluetooth.menu);
} }
this.menu.addMenuItem(this._remoteAccess.menu);
this.menu.addMenuItem(this._location.menu); this.menu.addMenuItem(this._location.menu);
this.menu.addMenuItem(this._rfkill.menu); this.menu.addMenuItem(this._rfkill.menu);
this.menu.addMenuItem(this._power.menu); this.menu.addMenuItem(this._power.menu);

View File

@ -62,7 +62,11 @@ var RunDialog = new Lang.Class({
'rt': () => { 'rt': () => {
Main.reloadThemeResource(); Main.reloadThemeResource();
Main.loadTheme(); Main.loadTheme();
} },
'check_cloexec_fds': () => {
Shell.util_check_cloexec_fds();
},
}; };

View File

@ -55,6 +55,9 @@ const ScreenshotIface = '<node> \
<arg type="i" direction="in" name="width"/> \ <arg type="i" direction="in" name="width"/> \
<arg type="i" direction="in" name="height"/> \ <arg type="i" direction="in" name="height"/> \
</method> \ </method> \
<method name="PickColor"> \
<arg type="a{sv}" direction="out" name="result"/> \
</method> \
</interface> \ </interface> \
</node>'; </node>';
@ -72,10 +75,13 @@ var ScreenshotService = new Lang.Class({
Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null); Gio.DBus.session.own_name('org.gnome.Shell.Screenshot', Gio.BusNameOwnerFlags.REPLACE, null, null);
}, },
_createScreenshot(invocation) { _createScreenshot(invocation, needsDisk=true) {
let lockedDown = false;
if (needsDisk)
lockedDown = this._lockdownSettings.get_boolean('disable-save-to-disk')
let sender = invocation.get_sender(); let sender = invocation.get_sender();
if (this._screenShooter.has(sender) || if (this._screenShooter.has(sender) || lockedDown) {
this._lockdownSettings.get_boolean('disable-save-to-disk')) {
invocation.return_value(GLib.Variant.new('(bs)', [false, ''])); invocation.return_value(GLib.Variant.new('(bs)', [false, '']));
return null; return null;
} }
@ -110,7 +116,7 @@ var ScreenshotService = new Lang.Class({
y + height <= global.screen_height; y + height <= global.screen_height;
}, },
_onScreenshotComplete(obj, result, area, filenameUsed, flash, invocation) { _onScreenshotComplete(result, area, filenameUsed, flash, invocation) {
if (result) { if (result) {
if (flash) { if (flash) {
let flashspot = new Flashspot(area); let flashspot = new Flashspot(area);
@ -157,9 +163,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot) if (!screenshot)
return; return;
screenshot.screenshot_area (x, y, width, height, filename, screenshot.screenshot_area (x, y, width, height, filename,
(obj, result, area, filenameUsed) => { (o, res) => {
this._onScreenshotComplete(obj, result, area, filenameUsed, try {
flash, invocation); let [result, area, filenameUsed] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
}); });
}, },
@ -169,9 +181,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot) if (!screenshot)
return; return;
screenshot.screenshot_window (include_frame, include_cursor, filename, screenshot.screenshot_window (include_frame, include_cursor, filename,
(obj, result, area, filenameUsed) => { (o, res) => {
this._onScreenshotComplete(obj, result, area, filenameUsed, try {
flash, invocation); let [result, area, filenameUsed] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
}); });
}, },
@ -181,9 +199,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot) if (!screenshot)
return; return;
screenshot.screenshot(include_cursor, filename, screenshot.screenshot(include_cursor, filename,
(obj, result, area, filenameUsed) => { (o, res) => {
this._onScreenshotComplete(obj, result, area, filenameUsed, try {
flash, invocation); let [result, area, filenameUsed] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
}); });
}, },
@ -215,6 +239,34 @@ var ScreenshotService = new Lang.Class({
let flashspot = new Flashspot({ x : x, y : y, width: width, height: height}); let flashspot = new Flashspot({ x : x, y : y, width: width, height: height});
flashspot.fire(); flashspot.fire();
invocation.return_value(null); invocation.return_value(null);
},
PickColorAsync(params, invocation) {
let pickPixel = new PickPixel();
pickPixel.show();
pickPixel.connect('finished', (pickPixel, coords) => {
if (coords) {
let screenshot = this._createScreenshot(invocation, false);
if (!screenshot)
return;
screenshot.pick_color(...coords, (o, res) => {
let [success, color] = screenshot.pick_color_finish(res);
let { red, green, blue } = color;
let retval = GLib.Variant.new('(a{sv})', [{
color: GLib.Variant.new('(ddd)', [
red / 255.0,
green / 255.0,
blue / 255.0
])
}]);
this._removeShooterForSender(invocation.get_sender());
invocation.return_value(retval);
});
} else {
invocation.return_error_literal(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED,
"Operation was cancelled");
}
});
} }
}); });
@ -341,6 +393,54 @@ var SelectArea = new Lang.Class({
}); });
Signals.addSignalMethods(SelectArea.prototype); Signals.addSignalMethods(SelectArea.prototype);
var PickPixel = new Lang.Class({
Name: 'PickPixel',
_init() {
this._result = null;
this._group = new St.Widget({ visible: false,
reactive: true });
Main.uiGroup.add_actor(this._group);
this._grabHelper = new GrabHelper.GrabHelper(this._group);
this._group.connect('button-release-event',
this._onButtonRelease.bind(this));
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint);
},
show() {
if (!this._grabHelper.grab({ actor: this._group,
onUngrab: this._onUngrab.bind(this) }))
return;
global.display.set_cursor(Meta.Cursor.CROSSHAIR);
Main.uiGroup.set_child_above_sibling(this._group, null);
this._group.visible = true;
},
_onButtonRelease(actor, event) {
this._result = event.get_coords();
this._grabHelper.ungrab();
return Clutter.EVENT_PROPAGATE;
},
_onUngrab() {
global.display.set_cursor(Meta.Cursor.DEFAULT);
this.emit('finished', this._result);
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._group.destroy();
return GLib.SOURCE_REMOVE;
});
}
});
Signals.addSignalMethods(PickPixel.prototype);
var FLASHSPOT_ANIMATION_OUT_TIME = 0.5; // seconds var FLASHSPOT_ANIMATION_OUT_TIME = 0.5; // seconds
var Flashspot = new Lang.Class({ var Flashspot = new Lang.Class({

View File

@ -117,6 +117,8 @@ function _loadMode(file, info) {
let fileContent, success, tag, newMode; let fileContent, success, tag, newMode;
try { try {
[success, fileContent, tag] = file.load_contents(null); [success, fileContent, tag] = file.load_contents(null);
if (fileContent instanceof Uint8Array)
fileContent = imports.byteArray.toString(fileContent);
newMode = JSON.parse(fileContent); newMode = JSON.parse(fileContent);
} catch(e) { } catch(e) {
return; return;

View File

@ -145,15 +145,20 @@ var GnomeShell = new Lang.Class({
for (let param in params) for (let param in params)
params[param] = params[param].deep_unpack(); params[param] = params[param].deep_unpack();
let monitorIndex = params['monitor'] || -1; let { monitor: monitorIndex,
let label = params['label'] || undefined; label,
let level = params['level'] || undefined; level,
max_level: maxLevel,
icon: serializedIcon } = params;
if (monitorIndex === undefined)
monitorIndex = -1;
let icon = null; let icon = null;
if (params['icon']) if (serializedIcon)
icon = Gio.Icon.new_for_string(params['icon']); icon = Gio.Icon.new_for_string(serializedIcon);
Main.osdWindowManager.show(monitorIndex, icon, label, level); Main.osdWindowManager.show(monitorIndex, icon, label, level, maxLevel);
}, },
FocusApp(id) { FocusApp(id) {

View File

@ -7,55 +7,38 @@ const Lang = imports.lang;
const St = imports.gi.St; const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const BarLevel = imports.ui.barLevel;
var SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */ var SLIDER_SCROLL_STEP = 0.02; /* Slider scrolling step in % */
var Slider = new Lang.Class({ var Slider = new Lang.Class({
Name: "Slider", Name: "Slider",
Extends: BarLevel.BarLevel,
_init(value) { _init(value) {
if (isNaN(value)) let params = {
// Avoid spreading NaNs around styleClass: 'slider',
throw TypeError('The slider value must be a number'); canFocus: true,
this._value = Math.max(Math.min(value, 1), 0); reactive: true,
this._sliderWidth = 0; accessibleRole: Atk.Role.SLIDER,
}
this.parent(value, params)
this.actor = new St.DrawingArea({ style_class: 'slider',
can_focus: true,
reactive: true,
accessible_role: Atk.Role.SLIDER });
this.actor.connect('repaint', this._sliderRepaint.bind(this));
this.actor.connect('button-press-event', this._startDragging.bind(this)); this.actor.connect('button-press-event', this._startDragging.bind(this));
this.actor.connect('touch-event', this._touchDragging.bind(this)); this.actor.connect('touch-event', this._touchDragging.bind(this));
this.actor.connect('scroll-event', this._onScrollEvent.bind(this)); this.actor.connect('scroll-event', this._onScrollEvent.bind(this));
this.actor.connect('key-press-event', this.onKeyPressEvent.bind(this)); this.actor.connect('key-press-event', this.onKeyPressEvent.bind(this));
this.actor.connect('allocation-changed', (actor, box) => {
this._sliderWidth = box.get_width();
});
this._releaseId = this._motionId = 0; this._releaseId = this._motionId = 0;
this._dragging = false; this._dragging = false;
this._customAccessible = St.GenericAccessible.new_for_actor(this.actor);
this.actor.set_accessible(this._customAccessible);
this._customAccessible.connect('get-current-value', this._getCurrentValue.bind(this));
this._customAccessible.connect('get-minimum-value', this._getMinimumValue.bind(this));
this._customAccessible.connect('get-maximum-value', this._getMaximumValue.bind(this));
this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this)); this._customAccessible.connect('get-minimum-increment', this._getMinimumIncrement.bind(this));
this._customAccessible.connect('set-current-value', this._setCurrentValue.bind(this));
this.connect('value-changed', this._valueChanged.bind(this));
}, },
setValue(value) { _barLevelRepaint(area) {
if (isNaN(value)) this.parent(area);
throw TypeError('The slider value must be a number');
this._value = Math.max(Math.min(value, 1), 0); // Add handle
this.actor.queue_repaint();
},
_sliderRepaint(area) {
let cr = area.get_context(); let cr = area.get_context();
let themeNode = area.get_theme_node(); let themeNode = area.get_theme_node();
let [width, height] = area.get_surface_size(); let [width, height] = area.get_surface_size();
@ -66,41 +49,9 @@ var Slider = new Lang.Class({
let [hasHandleColor, handleBorderColor] = let [hasHandleColor, handleBorderColor] =
themeNode.lookup_color('-slider-handle-border-color', false); themeNode.lookup_color('-slider-handle-border-color', false);
let sliderHeight = themeNode.get_length('-slider-height');
let sliderBorderWidth = themeNode.get_length('-slider-border-width');
let sliderBorderRadius = Math.min(width, sliderHeight) / 2;
let sliderBorderColor = themeNode.get_color('-slider-border-color');
let sliderColor = themeNode.get_color('-slider-background-color');
let sliderActiveBorderColor = themeNode.get_color('-slider-active-border-color');
let sliderActiveColor = themeNode.get_color('-slider-active-background-color');
const TAU = Math.PI * 2; const TAU = Math.PI * 2;
let handleX = handleRadius + (width - 2 * handleRadius) * this._value; let handleX = handleRadius + (width - 2 * handleRadius) * this._value / this._maxValue;
cr.arc(sliderBorderRadius + sliderBorderWidth, height / 2, sliderBorderRadius, TAU * 1/4, TAU * 3/4);
cr.lineTo(handleX, (height - sliderHeight) / 2);
cr.lineTo(handleX, (height + sliderHeight) / 2);
cr.lineTo(sliderBorderRadius + sliderBorderWidth, (height + sliderHeight) / 2);
Clutter.cairo_set_source_color(cr, sliderActiveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, sliderActiveBorderColor);
cr.setLineWidth(sliderBorderWidth);
cr.stroke();
cr.arc(width - sliderBorderRadius - sliderBorderWidth, height / 2, sliderBorderRadius, TAU * 3/4, TAU * 1/4);
cr.lineTo(handleX, (height + sliderHeight) / 2);
cr.lineTo(handleX, (height - sliderHeight) / 2);
cr.lineTo(width - sliderBorderRadius - sliderBorderWidth, (height - sliderHeight) / 2);
Clutter.cairo_set_source_color(cr, sliderColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, sliderBorderColor);
cr.setLineWidth(sliderBorderWidth);
cr.stroke();
let handleY = height / 2; let handleY = height / 2;
let color = themeNode.get_foreground_color(); let color = themeNode.get_foreground_color();
@ -208,7 +159,7 @@ var Slider = new Lang.Class({
delta = -dy * SLIDER_SCROLL_STEP; delta = -dy * SLIDER_SCROLL_STEP;
} }
this._value = Math.min(Math.max(0, this._value + delta), 1); this._value = Math.min(Math.max(0, this._value + delta), this._maxValue);
this.actor.queue_repaint(); this.actor.queue_repaint();
this.emit('value-changed', this._value); this.emit('value-changed', this._value);
@ -230,7 +181,7 @@ var Slider = new Lang.Class({
let key = event.get_key_symbol(); let key = event.get_key_symbol();
if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) { if (key == Clutter.KEY_Right || key == Clutter.KEY_Left) {
let delta = key == Clutter.KEY_Right ? 0.1 : -0.1; let delta = key == Clutter.KEY_Right ? 0.1 : -0.1;
this._value = Math.max(0, Math.min(this._value + delta, 1)); this._value = Math.max(0, Math.min(this._value + delta, this._maxValue));
this.actor.queue_repaint(); this.actor.queue_repaint();
this.emit('drag-begin'); this.emit('drag-begin');
this.emit('value-changed', this._value); this.emit('value-changed', this._value);
@ -246,7 +197,7 @@ var Slider = new Lang.Class({
relX = absX - sliderX; relX = absX - sliderX;
relY = absY - sliderY; relY = absY - sliderY;
let width = this._sliderWidth; let width = this._barLevelWidth;
let handleRadius = this.actor.get_theme_node().get_length('-slider-handle-radius'); let handleRadius = this.actor.get_theme_node().get_length('-slider-handle-radius');
let newvalue; let newvalue;
@ -256,38 +207,14 @@ var Slider = new Lang.Class({
newvalue = 1; newvalue = 1;
else else
newvalue = (relX - handleRadius) / (width - 2 * handleRadius); newvalue = (relX - handleRadius) / (width - 2 * handleRadius);
this._value = newvalue; this._value = newvalue * this._maxValue;
this.actor.queue_repaint(); this.actor.queue_repaint();
this.emit('value-changed', this._value); this.emit('value-changed', this._value);
}, },
_getCurrentValue(actor) {
return this._value;
},
_getMinimumValue(actor) {
return 0;
},
_getMaximumValue(actor) {
return 1;
},
_getMinimumIncrement(actor) { _getMinimumIncrement(actor) {
return 0.1; return 0.1;
}, },
_setCurrentValue(actor, value) {
this._value = value;
},
_valueChanged(slider, value, property) {
this._customAccessible.notify ("accessible-value");
},
get value() {
return this._value;
}
}); });
Signals.addSignalMethods(Slider.prototype); Signals.addSignalMethods(Slider.prototype);

View File

@ -0,0 +1,81 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
const Meta = imports.gi.Meta;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
var RemoteAccessApplet = new Lang.Class({
Name: 'RemoteAccessApplet',
Extends: PanelMenu.SystemIndicator,
_init() {
this.parent();
let backend = Meta.get_backend();
let controller = backend.get_remote_access_controller();
if (!controller)
return;
// We can't possibly know about all types of screen sharing on X11, so
// showing these controls on X11 might give a false sense of security.
// Thus, only enable these controls when using Wayland, where we are
// in control of sharing.
if (!Meta.is_wayland_compositor())
return;
this._handles = new Set();
this._indicator = null;
this._menuSection = null;
controller.connect('new-handle', (controller, handle) => {
this._onNewHandle(handle);
});
},
_ensureControls() {
if (this._indicator)
return;
this._indicator = this._addIndicator();
this._indicator.icon_name = 'screen-shared-symbolic';
this._indicator.add_style_class_name('remote-access-indicator');
this._item =
new PopupMenu.PopupSubMenuMenuItem(_("Screen is Being Shared"),
true);
this._item.menu.addAction(_("Turn off"),
() => {
for (let handle of this._handles)
handle.stop();
});
this._item.icon.icon_name = 'screen-shared-symbolic';
this.menu.addMenuItem(this._item);
},
_sync() {
if (this._handles.size == 0) {
this._indicator.visible = false;
this._item.actor.visible = false;
} else {
this._indicator.visible = true;
this._item.actor.visible = true;
}
},
_onStopped(handle) {
this._handles.delete(handle);
this._sync();
},
_onNewHandle(handle) {
this._handles.add(handle);
handle.connect('stopped', this._onStopped.bind(this));
if (this._handles.size == 1) {
this._ensureControls();
this._sync();
}
},
});

View File

@ -261,8 +261,19 @@ var Indicator = new Lang.Class({
item = new PopupMenu.PopupBaseMenuItem({ reactive: false, item = new PopupMenu.PopupBaseMenuItem({ reactive: false,
can_focus: false }); can_focus: false });
this._settingsAction = this._createActionButton('preferences-system-symbolic', _("Settings")); let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
this._settingsAction.connect('clicked', () => { this._onSettingsClicked(); }); 'gnome-control-center.desktop'
);
if (app) {
let [icon, name] = [app.app_info.get_icon().names[0],
app.get_name()];
this._settingsAction = this._createActionButton(icon, name);
this._settingsAction.connect('clicked',
this._onSettingsClicked.bind(this));
} else {
log('Missing required core component Settings, expect trouble…');
this._settingsAction = new St.Widget();
}
item.actor.add(this._settingsAction, { expand: true, x_fill: false }); item.actor.add(this._settingsAction, { expand: true, x_fill: false });
this._orientationLockAction = this._createActionButton('', _("Orientation Lock")); this._orientationLockAction = this._createActionButton('', _("Orientation Lock"));
@ -280,7 +291,7 @@ var Indicator = new Lang.Class({
'icon-name', 'icon-name',
bindFlags); bindFlags);
this._lockScreenAction = this._createActionButton('changes-prevent-symbolic', _("Lock")); this._lockScreenAction = this._createActionButton('changes-prevent', _("Lock"));
this._lockScreenAction.connect('clicked', () => { this._lockScreenAction.connect('clicked', () => {
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE); this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
this._systemActions.activateLockScreen(); this._systemActions.activateLockScreen();
@ -291,7 +302,7 @@ var Indicator = new Lang.Class({
'visible', 'visible',
bindFlags); bindFlags);
this._suspendAction = this._createActionButton('media-playback-pause-symbolic', _("Suspend")); this._suspendAction = this._createActionButton('media-playback-pause', _("Suspend"));
this._suspendAction.connect('clicked', () => { this._suspendAction.connect('clicked', () => {
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE); this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
this._systemActions.activateSuspend(); this._systemActions.activateSuspend();
@ -301,7 +312,7 @@ var Indicator = new Lang.Class({
'visible', 'visible',
bindFlags); bindFlags);
this._powerOffAction = this._createActionButton('system-shutdown-symbolic', _("Power Off")); this._powerOffAction = this._createActionButton('system-shutdown', _("Power Off"));
this._powerOffAction.connect('clicked', () => { this._powerOffAction.connect('clicked', () => {
this.menu.itemActivated(BoxPointer.PopupAnimation.NONE); this.menu.itemActivated(BoxPointer.PopupAnimation.NONE);
this._systemActions.activatePowerOff(); this._systemActions.activatePowerOff();
@ -330,8 +341,7 @@ var Indicator = new Lang.Class({
_onSettingsClicked() { _onSettingsClicked() {
this.menu.itemActivated(); this.menu.itemActivated();
let app = Shell.AppSystem.get_default().lookup_app('gnome-control-center.desktop');
Main.overview.hide(); Main.overview.hide();
app.activate(); this._settingsApp.activate();
} }
}); });

View File

@ -12,6 +12,8 @@ const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const Slider = imports.ui.slider; const Slider = imports.ui.slider;
const ALLOW_AMPLIFIED_VOLUME_KEY = 'allow-volume-above-100-percent';
var VOLUME_NOTIFY_ID = 1; var VOLUME_NOTIFY_ID = 1;
// Each Gvc.MixerControl is a connection to PulseAudio, // Each Gvc.MixerControl is a connection to PulseAudio,
@ -36,6 +38,11 @@ var StreamSlider = new Lang.Class({
this.item = new PopupMenu.PopupBaseMenuItem({ activate: false }); this.item = new PopupMenu.PopupBaseMenuItem({ activate: false });
this._slider = new Slider.Slider(0); this._slider = new Slider.Slider(0);
this._soundSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.sound' });
this._soundSettings.connect('changed::' + ALLOW_AMPLIFIED_VOLUME_KEY, this._amplifySettingsChanged.bind(this));
this._amplifySettingsChanged();
this._slider.connect('value-changed', this._sliderChanged.bind(this)); this._slider.connect('value-changed', this._sliderChanged.bind(this));
this._slider.connect('drag-end', this._notifyVolumeChange.bind(this)); this._slider.connect('drag-end', this._notifyVolumeChange.bind(this));
@ -135,21 +142,40 @@ var StreamSlider = new Lang.Class({
this.emit('stream-updated'); this.emit('stream-updated');
}, },
_amplifySettingsChanged() {
this._allowAmplified = this._soundSettings.get_boolean(ALLOW_AMPLIFIED_VOLUME_KEY);
if (this._allowAmplified)
this._slider.setMaximumValue(this.getMaxLevel() / 100);
else
this._slider.setMaximumValue(1);
if (this._stream)
this._updateVolume();
},
getIcon() { getIcon() {
if (!this._stream) if (!this._stream)
return null; return null;
let icons = ["audio-volume-muted-symbolic",
"audio-volume-low-symbolic",
"audio-volume-medium-symbolic",
"audio-volume-high-symbolic",
"audio-volume-overamplified-symbolic"];
let volume = this._stream.volume; let volume = this._stream.volume;
let n;
if (this._stream.is_muted || volume <= 0) { if (this._stream.is_muted || volume <= 0) {
return 'audio-volume-muted-symbolic'; n = 0;
} else { } else {
let n = Math.floor(3 * volume / this._control.get_vol_max_norm()) + 1; n = Math.ceil(3 * volume / this._control.get_vol_max_norm());
if (n < 2) if (n < 1)
return 'audio-volume-low-symbolic'; n = 1;
if (n >= 3) else if (n > 3)
return 'audio-volume-high-symbolic'; n = 4;
return 'audio-volume-medium-symbolic';
} }
return icons[n];
}, },
getLevel() { getLevel() {
@ -157,6 +183,14 @@ var StreamSlider = new Lang.Class({
return null; return null;
return 100 * this._stream.volume / this._control.get_vol_max_norm(); return 100 * this._stream.volume / this._control.get_vol_max_norm();
},
getMaxLevel() {
let maxVolume = this._control.get_vol_max_norm();
if (this._allowAmplified)
maxVolume = this._control.get_vol_max_amplified();
return 100 * maxVolume / this._control.get_vol_max_norm();
} }
}); });
Signals.addSignalMethods(StreamSlider.prototype); Signals.addSignalMethods(StreamSlider.prototype);
@ -310,6 +344,10 @@ var VolumeMenu = new Lang.Class({
getLevel() { getLevel() {
return this._output.getLevel(); return this._output.getLevel();
},
getMaxLevel() {
return this._output.getMaxLevel();
} }
}); });
@ -346,8 +384,9 @@ var Indicator = new Lang.Class({
return result; return result;
let gicon = new Gio.ThemedIcon({ name: this._volumeMenu.getIcon() }); let gicon = new Gio.ThemedIcon({ name: this._volumeMenu.getIcon() });
let level = this._volumeMenu.getLevel(); let level = parseInt(this._volumeMenu.getLevel());
Main.osdWindowManager.show(-1, gicon, null, level); let maxLevel = parseInt(this._volumeMenu.getMaxLevel());
Main.osdWindowManager.show(-1, gicon, null, level, maxLevel);
return result; return result;
} }
}); });

View File

@ -3,6 +3,7 @@
const Clutter = imports.gi.Clutter; const Clutter = imports.gi.Clutter;
const GLib = imports.gi.GLib; const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Lang = imports.lang; const Lang = imports.lang;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta; const Meta = imports.gi.Meta;
@ -34,6 +35,7 @@ var WINDOW_ANIMATION_TIME = 0.25;
var DIM_BRIGHTNESS = -0.3; var DIM_BRIGHTNESS = -0.3;
var DIM_TIME = 0.500; var DIM_TIME = 0.500;
var UNDIM_TIME = 0.250; var UNDIM_TIME = 0.250;
var MOTION_THRESHOLD = 100;
var ONE_SECOND = 1000; // in ms var ONE_SECOND = 1000; // in ms
@ -213,20 +215,12 @@ var WorkspaceTracker = new Lang.Class({
global.display.connect('restacked', global.display.connect('restacked',
this._windowsRestacked.bind(this)); this._windowsRestacked.bind(this));
this._workspaceSettings = this._getWorkspaceSettings(); this._workspaceSettings = new Gio.Settings({ schema_id: 'org.gnome.mutter' });
this._workspaceSettings.connect('changed::dynamic-workspaces', this._queueCheckWorkspaces.bind(this)); this._workspaceSettings.connect('changed::dynamic-workspaces', this._queueCheckWorkspaces.bind(this));
this._nWorkspacesChanged(); this._nWorkspacesChanged();
}, },
_getWorkspaceSettings() {
let settings = global.get_overrides_settings();
if (settings &&
settings.settings_schema.list_keys().indexOf('dynamic-workspaces') > -1)
return settings;
return new Gio.Settings({ schema_id: 'org.gnome.mutter' });
},
blockUpdates() { blockUpdates() {
this._pauseWorkspaceCheck = true; this._pauseWorkspaceCheck = true;
}, },
@ -495,13 +489,8 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
}, },
_checkActivated() { _checkActivated() {
const MOTION_THRESHOLD = 50;
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
let dir; let dir;
if ((allowedModes & Main.actionMode) == 0)
return;
if (this._dy < -MOTION_THRESHOLD) if (this._dy < -MOTION_THRESHOLD)
dir = Meta.MotionDirection.DOWN; dir = Meta.MotionDirection.DOWN;
else if (this._dy > MOTION_THRESHOLD) else if (this._dy > MOTION_THRESHOLD)
@ -511,26 +500,35 @@ var TouchpadWorkspaceSwitchAction = new Lang.Class({
else if (this._dx > MOTION_THRESHOLD) else if (this._dx > MOTION_THRESHOLD)
dir = Meta.MotionDirection.LEFT; dir = Meta.MotionDirection.LEFT;
else else
return; return false;
this.emit('activated', dir); this.emit('activated', dir);
return true;
}, },
_handleEvent(actor, event) { _handleEvent(actor, event) {
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE) if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if (event.get_touchpad_gesture_finger_count() != 4) if (event.get_touchpad_gesture_finger_count() != 4)
return Clutter.EVENT_PROPAGATE; return Clutter.EVENT_PROPAGATE;
if ((allowedModes & Main.actionMode) == 0)
return Clutter.EVENT_PROPAGATE;
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) { if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
let [dx, dy] = event.get_gesture_motion_delta(); let [dx, dy] = event.get_gesture_motion_delta();
this._dx += dx; // Scale deltas up a bit to make it feel snappier
this._dy += dy; this._dx += dx * 2;
this._dy += dy * 2;
this.emit('motion', this._dx, this._dy);
} else { } else {
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END) if ((event.get_gesture_phase() == Clutter.TouchpadGesturePhase.END && ! this._checkActivated()) ||
this._checkActivated(); event.get_gesture_phase() == Clutter.TouchpadGesturePhase.CANCEL)
this.emit('cancel');
this._dx = 0; this._dx = 0;
this._dy = 0; this._dy = 0;
@ -544,14 +542,14 @@ Signals.addSignalMethods(TouchpadWorkspaceSwitchAction.prototype);
var WorkspaceSwitchAction = new Lang.Class({ var WorkspaceSwitchAction = new Lang.Class({
Name: 'WorkspaceSwitchAction', Name: 'WorkspaceSwitchAction',
Extends: Clutter.SwipeAction, Extends: Clutter.SwipeAction,
Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] } }, Signals: { 'activated': { param_types: [Meta.MotionDirection.$gtype] },
'motion': { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
'cancel': { param_types: [] }},
_init() { _init() {
const MOTION_THRESHOLD = 50;
this.parent(); this.parent();
this.set_n_touch_points(4); this.set_n_touch_points(4);
this.set_threshold_trigger_distance(MOTION_THRESHOLD, MOTION_THRESHOLD); this._swept = false;
global.display.connect('grab-op-begin', () => { global.display.connect('grab-op-begin', () => {
this.cancel(); this.cancel();
@ -561,13 +559,35 @@ var WorkspaceSwitchAction = new Lang.Class({
vfunc_gesture_prepare(actor) { vfunc_gesture_prepare(actor) {
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW; let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
this._swept = false;
if (!this.parent(actor)) if (!this.parent(actor))
return false; return false;
return (allowedModes & Main.actionMode); return (allowedModes & Main.actionMode);
}, },
vfunc_swept(actor, direction) { vfunc_gesture_progress(actor) {
let [x, y] = this.get_motion_coords(0);
let [xPress, yPress] = this.get_press_coords(0);
this.emit('motion', x - xPress, y - yPress);
return true;
},
vfunc_gesture_cancel(actor) {
if (!this._swept)
this.emit('cancel');
},
vfunc_swipe(actor, direction) {
let [x, y] = this.get_motion_coords(0);
let [xPress, yPress] = this.get_press_coords(0);
if (Math.abs(x - xPress) < MOTION_THRESHOLD &&
Math.abs(y - yPress) < MOTION_THRESHOLD) {
this.emit('cancel');
return;
}
let dir; let dir;
if (direction & Clutter.SwipeDirection.UP) if (direction & Clutter.SwipeDirection.UP)
@ -579,6 +599,7 @@ var WorkspaceSwitchAction = new Lang.Class({
else if (direction & Clutter.SwipeDirection.RIGHT) else if (direction & Clutter.SwipeDirection.RIGHT)
dir = Meta.MotionDirection.LEFT; dir = Meta.MotionDirection.LEFT;
this._swept = true;
this.emit('activated', dir); this.emit('activated', dir);
} }
}); });
@ -635,8 +656,8 @@ var AppSwitchAction = new Lang.Class({
if (this.get_n_current_points() == 3) { if (this.get_n_current_points() == 3) {
for (let i = 0; i < this.get_n_current_points(); i++) { for (let i = 0; i < this.get_n_current_points(); i++) {
[startX, startY] = this.get_press_coords(i); let [startX, startY] = this.get_press_coords(i);
[x, y] = this.get_motion_coords(i); let [x, y] = this.get_motion_coords(i);
if (Math.abs(x - startX) > MOTION_THRESHOLD || if (Math.abs(x - startX) > MOTION_THRESHOLD ||
Math.abs(y - startY) > MOTION_THRESHOLD) Math.abs(y - startY) > MOTION_THRESHOLD)
@ -700,7 +721,14 @@ var WindowManager = new Lang.Class({
this._isWorkspacePrepended = false; this._isWorkspacePrepended = false;
this._switchData = null; this._switchData = null;
this._shellwm.connect('kill-switch-workspace', this._switchWorkspaceDone.bind(this)); this._shellwm.connect('kill-switch-workspace', (shellwm) => {
if (this._switchData) {
if (this._switchData.inProgress)
this._switchWorkspaceDone(shellwm);
else if (!this._switchData.gestureActivated)
this._finishWorkspaceSwitch(this._switchData);
}
});
this._shellwm.connect('kill-window-effects', (shellwm, actor) => { this._shellwm.connect('kill-window-effects', (shellwm, actor) => {
this._minimizeWindowDone(shellwm, actor); this._minimizeWindowDone(shellwm, actor);
this._mapWindowDone(shellwm, actor); this._mapWindowDone(shellwm, actor);
@ -982,12 +1010,16 @@ var WindowManager = new Lang.Class({
false, -1, 1); false, -1, 1);
let gesture = new WorkspaceSwitchAction(); let gesture = new WorkspaceSwitchAction();
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this)); gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
global.stage.add_action(gesture); global.stage.add_action(gesture);
// This is not a normal Clutter.GestureAction, doesn't need add_action() // This is not a normal Clutter.GestureAction, doesn't need add_action()
gesture = new TouchpadWorkspaceSwitchAction(global.stage); gesture = new TouchpadWorkspaceSwitchAction(global.stage);
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this)); gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
gesture = new AppSwitchAction(); gesture = new AppSwitchAction();
gesture.connect('activated', this._switchApp.bind(this)); gesture.connect('activated', this._switchApp.bind(this));
@ -999,6 +1031,14 @@ var WindowManager = new Lang.Class({
Main.keyboard.show(Main.layoutManager.bottomIndex); Main.keyboard.show(Main.layoutManager.bottomIndex);
}); });
global.stage.add_action(gesture); global.stage.add_action(gesture);
gesture = new EdgeDragAction.EdgeDragAction(St.Side.TOP, mode);
gesture.connect('activated', () => {
let currentWindow = global.display.focus_window;
if (currentWindow)
currentWindow.unmake_fullscreen();
});
global.stage.add_action(gesture);
}, },
_showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) { _showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) {
@ -1008,11 +1048,52 @@ var WindowManager = new Lang.Class({
return this._currentPadOsd.actor; return this._currentPadOsd.actor;
}, },
_switchWorkspaceMotion(action, xRel, yRel) {
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
if (!this._switchData)
this._prepareWorkspaceSwitch(activeWorkspace.index(), -1);
if (yRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.DOWN])
yRel = 0;
if (yRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.UP])
yRel = 0;
if (xRel < 0 && !this._switchData.surroundings[Meta.MotionDirection.RIGHT])
xRel = 0;
if (xRel > 0 && !this._switchData.surroundings[Meta.MotionDirection.LEFT])
xRel = 0;
this._switchData.container.set_position(xRel, yRel);
},
_switchWorkspaceCancel() {
if (!this._switchData || this._switchData.inProgress)
return;
let switchData = this._switchData;
this._switchData = null;
Tweener.addTween(switchData.container,
{ x: 0,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete: this._finishWorkspaceSwitch,
onCompleteScope: this,
onCompleteParams: [switchData],
});
},
_actionSwitchWorkspace(action, direction) { _actionSwitchWorkspace(action, direction) {
let workspaceManager = global.workspace_manager; let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace(); let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace.get_neighbor(direction); let newWs = activeWorkspace.get_neighbor(direction);
if (newWs == activeWorkspace) {
this._switchWorkspaceCancel();
} else {
this._switchData.gestureActivated = true;
this.actionMoveWorkspace(newWs); this.actionMoveWorkspace(newWs);
}
}, },
_lookupIndex(windows, metaWindow) { _lookupIndex(windows, metaWindow) {
@ -1692,63 +1773,104 @@ var WindowManager = new Lang.Class({
if (this._switchData == null) if (this._switchData == null)
return; return;
// Update stacking of windows in inGroup (aka the workspace we are
// switching to). Windows in outGroup are about to be hidden anyway,
// so we just ignore them here.
let windows = global.get_window_actors(); let windows = global.get_window_actors();
let sibling = null; let lastCurSibling = null;
let lastDirSibling = [];
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
if (windows[i].get_parent() != this._switchData.inGroup) if (windows[i].get_parent() == this._switchData.curGroup) {
continue; this._switchData.curGroup.set_child_above_sibling(windows[i], lastCurSibling);
lastCurSibling = windows[i];
} else {
for (let dir of Object.values(Meta.MotionDirection)) {
let info = this._switchData.surroundings[dir];
if (!info || windows[i].get_parent() != info.actor)
continue;
this._switchData.inGroup.set_child_above_sibling(windows[i], sibling); let sibling = lastDirSibling[dir];
sibling = windows[i]; if (sibling == undefined)
sibling = null;
info.actor.set_child_above_sibling(windows[i], sibling);
lastDirSibling[dir] = windows[i];
break;
}
}
} }
}, },
_switchWorkspace(shellwm, from, to, direction) { _getPositionForDirection(direction) {
if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) {
shellwm.completed_switch_workspace();
return;
}
let windows = global.get_window_actors();
/* @direction is the direction that the "camera" moves, so the
* screen contents have to move one screen's worth in the
* opposite direction.
*/
let xDest = 0, yDest = 0; let xDest = 0, yDest = 0;
if (direction == Meta.MotionDirection.UP || if (direction == Meta.MotionDirection.UP ||
direction == Meta.MotionDirection.UP_LEFT || direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.UP_RIGHT) direction == Meta.MotionDirection.UP_RIGHT)
yDest = global.screen_height - Main.panel.actor.height; yDest = -global.screen_height + Main.panel.actor.height;
else if (direction == Meta.MotionDirection.DOWN || else if (direction == Meta.MotionDirection.DOWN ||
direction == Meta.MotionDirection.DOWN_LEFT || direction == Meta.MotionDirection.DOWN_LEFT ||
direction == Meta.MotionDirection.DOWN_RIGHT) direction == Meta.MotionDirection.DOWN_RIGHT)
yDest = -global.screen_height + Main.panel.actor.height; yDest = global.screen_height - Main.panel.actor.height;
if (direction == Meta.MotionDirection.LEFT || if (direction == Meta.MotionDirection.LEFT ||
direction == Meta.MotionDirection.UP_LEFT || direction == Meta.MotionDirection.UP_LEFT ||
direction == Meta.MotionDirection.DOWN_LEFT) direction == Meta.MotionDirection.DOWN_LEFT)
xDest = global.screen_width; xDest = -global.screen_width;
else if (direction == Meta.MotionDirection.RIGHT || else if (direction == Meta.MotionDirection.RIGHT ||
direction == Meta.MotionDirection.UP_RIGHT || direction == Meta.MotionDirection.UP_RIGHT ||
direction == Meta.MotionDirection.DOWN_RIGHT) direction == Meta.MotionDirection.DOWN_RIGHT)
xDest = -global.screen_width; xDest = global.screen_width;
let switchData = {}; return [xDest, yDest];
this._switchData = switchData; },
switchData.inGroup = new Clutter.Actor();
switchData.outGroup = new Clutter.Actor(); _prepareWorkspaceSwitch(from, to, direction) {
switchData.movingWindowBin = new Clutter.Actor(); if (this._switchData)
switchData.windows = []; return;
let wgroup = global.window_group; let wgroup = global.window_group;
wgroup.add_actor(switchData.inGroup); let windows = global.get_window_actors();
wgroup.add_actor(switchData.outGroup); let switchData = {};
this._switchData = switchData;
switchData.curGroup = new Clutter.Actor();
switchData.movingWindowBin = new Clutter.Actor();
switchData.windows = [];
switchData.surroundings = {};
switchData.gestureActivated = false;
switchData.inProgress = false;
switchData.container = new Clutter.Actor();
switchData.container.add_actor(switchData.curGroup);
wgroup.add_actor(switchData.movingWindowBin); wgroup.add_actor(switchData.movingWindowBin);
wgroup.add_actor(switchData.container);
let workspaceManager = global.workspace_manager;
let curWs = workspaceManager.get_workspace_by_index (from);
for (let dir of Object.values(Meta.MotionDirection)) {
let ws = null;
if (to < 0)
ws = curWs.get_neighbor(dir);
else if (dir == direction)
ws = workspaceManager.get_workspace_by_index(to);
if (ws == null || ws == curWs) {
switchData.surroundings[dir] = null;
continue;
}
let info = { index: ws.index(),
actor: new Clutter.Actor() };
switchData.surroundings[dir] = info;
switchData.container.add_actor(info.actor);
info.actor.raise_top();
let [x, y] = this._getPositionForDirection(dir);
info.actor.set_position(x, y);
}
switchData.movingWindowBin.raise_top();
for (let i = 0; i < windows.length; i++) { for (let i = 0; i < windows.length; i++) {
let actor = windows[i]; let actor = windows[i];
@ -1769,20 +1891,70 @@ var WindowManager = new Lang.Class({
actor.reparent(switchData.movingWindowBin); actor.reparent(switchData.movingWindowBin);
} else if (window.get_workspace().index() == from) { } else if (window.get_workspace().index() == from) {
switchData.windows.push(record); switchData.windows.push(record);
actor.reparent(switchData.outGroup); actor.reparent(switchData.curGroup);
} else if (window.get_workspace().index() == to) { } else {
switchData.windows.push(record); let visible = false;
actor.reparent(switchData.inGroup); for (let dir of Object.values(Meta.MotionDirection)) {
actor.show(); let info = switchData.surroundings[dir];
if (!info || info.index != window.get_workspace().index())
continue;
switchData.windows.push(record);
actor.reparent(info.actor);
visible = true;
break;
}
actor.visible = visible;
} }
} }
},
switchData.inGroup.set_position(-xDest, -yDest); _finishWorkspaceSwitch(switchData) {
switchData.inGroup.raise_top(); this._switchData = null;
switchData.movingWindowBin.raise_top(); for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
if (w.window.is_destroyed()) // Window gone
continue;
Tweener.addTween(switchData.outGroup, w.window.reparent(w.parent);
if (w.window.get_meta_window().get_workspace() !=
global.workspace_manager.get_active_workspace())
w.window.hide();
}
Tweener.removeTweens(switchData.container);
switchData.container.destroy();
switchData.movingWindowBin.destroy();
this._movingWindow = null;
},
_switchWorkspace(shellwm, from, to, direction) {
if (!Main.sessionMode.hasWorkspaces || !this._shouldAnimate()) {
shellwm.completed_switch_workspace();
return;
}
// If we come from a gesture, switchData will already be set,
// and we don't want to overwrite it.
if (!this._switchData)
this._prepareWorkspaceSwitch(from, to, direction);
this._switchData.inProgress = true;
let [xDest, yDest] = this._getPositionForDirection(direction);
/* @direction is the direction that the "camera" moves, so the
* screen contents have to move one screen's worth in the
* opposite direction.
*/
xDest = -xDest;
yDest = -yDest;
Tweener.addTween(this._switchData.container,
{ x: xDest, { x: xDest,
y: yDest, y: yDest,
time: WINDOW_ANIMATION_TIME, time: WINDOW_ANIMATION_TIME,
@ -1791,39 +1963,10 @@ var WindowManager = new Lang.Class({
onCompleteScope: this, onCompleteScope: this,
onCompleteParams: [shellwm] onCompleteParams: [shellwm]
}); });
Tweener.addTween(switchData.inGroup,
{ x: 0,
y: 0,
time: WINDOW_ANIMATION_TIME,
transition: 'easeOutQuad'
});
}, },
_switchWorkspaceDone(shellwm) { _switchWorkspaceDone(shellwm) {
let switchData = this._switchData; this._finishWorkspaceSwitch(this._switchData);
if (!switchData)
return;
this._switchData = null;
for (let i = 0; i < switchData.windows.length; i++) {
let w = switchData.windows[i];
if (w.window.is_destroyed()) // Window gone
continue;
if (w.window.get_parent() == switchData.outGroup) {
w.window.reparent(w.parent);
w.window.hide();
} else
w.window.reparent(w.parent);
}
Tweener.removeTweens(switchData.inGroup);
Tweener.removeTweens(switchData.outGroup);
switchData.inGroup.destroy();
switchData.outGroup.destroy();
switchData.movingWindowBin.destroy();
if (this._movingWindow)
this._movingWindow = null;
shellwm.completed_switch_workspace(); shellwm.completed_switch_workspace();
}, },

View File

@ -137,8 +137,10 @@ var WindowClone = new Lang.Class({
this._dragSlot = [0, 0, 0, 0]; this._dragSlot = [0, 0, 0, 0];
this._stackAbove = null; this._stackAbove = null;
this._windowClone._updateId = this.metaWindow.connect('size-changed', this._windowClone._sizeChangedId = this.metaWindow.connect('size-changed',
this._onRealWindowSizeChanged.bind(this)); this._onMetaWindowSizeChanged.bind(this));
this._windowClone._posChangedId = this.metaWindow.connect('position-changed',
this._computeBoundingBox.bind(this));
this._windowClone._destroyId = this._windowClone._destroyId =
this.realWindow.connect('destroy', () => { this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything // First destroy the clone and then destroy everything
@ -177,6 +179,7 @@ var WindowClone = new Lang.Class({
this.inDrag = false; this.inDrag = false;
this._selected = false; this._selected = false;
this._closeRequested = false;
}, },
set slot(slot) { set slot(slot) {
@ -192,7 +195,6 @@ var WindowClone = new Lang.Class({
deleteAll() { deleteAll() {
// Delete all windows, starting from the bottom-most (most-modal) one // Delete all windows, starting from the bottom-most (most-modal) one
let windows = this.actor.get_children(); let windows = this.actor.get_children();
for (let i = windows.length - 1; i >= 1; i--) { for (let i = windows.length - 1; i >= 1; i--) {
let realWindow = windows[i].source; let realWindow = windows[i].source;
@ -202,12 +204,24 @@ var WindowClone = new Lang.Class({
} }
this.metaWindow.delete(global.get_current_time()); this.metaWindow.delete(global.get_current_time());
this._closeRequested = true;
}, },
addAttachedDialog(win) { addDialog(win) {
this._doAddAttachedDialog(win, win.get_compositor_private()); let parent = win.get_transient_for();
this._computeBoundingBox(); while (parent.is_attached_dialog())
this.emit('size-changed'); parent = parent.get_transient_for();
// Display dialog if it is attached to our metaWindow
if (win.is_attached_dialog() && parent == this.metaWindow) {
this._doAddAttachedDialog(win, win.get_compositor_private());
this._onMetaWindowSizeChanged();
}
// The dialog popped up after the user tried to close the window,
// assume it's a close confirmation and leave the overview
if (this._closeRequested)
this._activate();
}, },
hasAttachedDialogs() { hasAttachedDialogs() {
@ -216,15 +230,14 @@ var WindowClone = new Lang.Class({
_doAddAttachedDialog(metaWin, realWin) { _doAddAttachedDialog(metaWin, realWin) {
let clone = new Clutter.Clone({ source: realWin }); let clone = new Clutter.Clone({ source: realWin });
clone._updateId = metaWin.connect('size-changed', () => { clone._sizeChangedId = metaWin.connect('size-changed',
this._computeBoundingBox(); this._onMetaWindowSizeChanged.bind(this));
this.emit('size-changed'); clone._posChangedId = metaWin.connect('position-changed',
}); this._onMetaWindowSizeChanged.bind(this));
clone._destroyId = realWin.connect('destroy', () => { clone._destroyId = realWin.connect('destroy', () => {
clone.destroy(); clone.destroy();
this._computeBoundingBox(); this._onMetaWindowSizeChanged();
this.emit('size-changed');
}); });
this.actor.add_child(clone); this.actor.add_child(clone);
}, },
@ -321,12 +334,13 @@ var WindowClone = new Lang.Class({
else else
realWindow = child.source; realWindow = child.source;
realWindow.meta_window.disconnect(child._updateId); realWindow.meta_window.disconnect(child._sizeChangedId);
realWindow.meta_window.disconnect(child._posChangedId);
realWindow.disconnect(child._destroyId); realWindow.disconnect(child._destroyId);
}); });
}, },
_onRealWindowSizeChanged() { _onMetaWindowSizeChanged() {
this._computeBoundingBox(); this._computeBoundingBox();
this.emit('size-changed'); this.emit('size-changed');
}, },
@ -461,14 +475,12 @@ var WindowOverlay = new Lang.Class({
button._overlap = 0; button._overlap = 0;
this._idleToggleCloseId = 0; this._idleToggleCloseId = 0;
button.connect('clicked', this._closeWindow.bind(this)); button.connect('clicked', () => this._windowClone.deleteAll());
windowClone.actor.connect('destroy', this._onDestroy.bind(this)); windowClone.actor.connect('destroy', this._onDestroy.bind(this));
windowClone.connect('show-chrome', this._onShowChrome.bind(this)); windowClone.connect('show-chrome', this._onShowChrome.bind(this));
windowClone.connect('hide-chrome', this._onHideChrome.bind(this)); windowClone.connect('hide-chrome', this._onHideChrome.bind(this));
this._windowAddedId = 0;
button.hide(); button.hide();
title.hide(); title.hide();
@ -589,43 +601,12 @@ var WindowOverlay = new Lang.Class({
Tweener.addTween(actor, params); Tweener.addTween(actor, params);
}, },
_closeWindow(actor) {
let metaWindow = this._windowClone.metaWindow;
this._workspace = metaWindow.get_workspace();
this._windowAddedId = this._workspace.connect('window-added',
this._onWindowAdded.bind(this));
this._windowClone.deleteAll();
},
_windowCanClose() { _windowCanClose() {
return this._windowClone.metaWindow.can_close() && return this._windowClone.metaWindow.can_close() &&
!this._windowClone.hasAttachedDialogs(); !this._windowClone.hasAttachedDialogs();
}, },
_onWindowAdded(workspace, win) {
let metaWindow = this._windowClone.metaWindow;
if (win.get_transient_for() == metaWindow) {
workspace.disconnect(this._windowAddedId);
this._windowAddedId = 0;
// use an idle handler to avoid mapping problems -
// see comment in Workspace._windowAdded
let id = Mainloop.idle_add(() => {
this._windowClone.emit('selected');
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] this._windowClone.emit');
}
},
_onDestroy() { _onDestroy() {
if (this._windowAddedId > 0) {
this._workspace.disconnect(this._windowAddedId);
this._windowAddedId = 0;
}
if (this._idleToggleCloseId > 0) { if (this._idleToggleCloseId > 0) {
Mainloop.source_remove(this._idleToggleCloseId); Mainloop.source_remove(this._idleToggleCloseId);
this._idleToggleCloseId = 0; this._idleToggleCloseId = 0;
@ -1515,21 +1496,17 @@ var Workspace = new Lang.Class({
return; return;
if (!this._isOverviewWindow(win)) { if (!this._isOverviewWindow(win)) {
if (metaWin.is_attached_dialog()) { if (metaWin.get_transient_for() == null)
let parent = metaWin.get_transient_for(); return;
while (parent.is_attached_dialog())
parent = metaWin.get_transient_for();
let idx = this._lookupIndex (parent); // Let the top-most ancestor handle all transients
if (idx < 0) { let parent = metaWin.find_root_ancestor();
// parent was not created yet, it will take care let clone = this._windows.find(c => c.metaWindow == parent);
// of the dialog when created
return;
}
let clone = this._windows[idx]; // If no clone was found, the parent hasn't been created yet
clone.addAttachedDialog(metaWin); // and will take care of the dialog when added
} if (clone)
clone.addDialog(metaWin);
return; return;
} }

View File

@ -68,7 +68,7 @@ var WindowClone = new Lang.Class({
this.realWindow = realWindow; this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window; this.metaWindow = realWindow.meta_window;
this.clone._updateId = this.metaWindow.connect('position-changed', this.clone._updateId = this.realWindow.connect('notify::position',
this._onPositionChanged.bind(this)); this._onPositionChanged.bind(this));
this.clone._destroyId = this.realWindow.connect('destroy', () => { this.clone._destroyId = this.realWindow.connect('destroy', () => {
// First destroy the clone and then destroy everything // First destroy the clone and then destroy everything
@ -153,7 +153,7 @@ var WindowClone = new Lang.Class({
let clone = new Clutter.Clone({ source: realDialog }); let clone = new Clutter.Clone({ source: realDialog });
this._updateDialogPosition(realDialog, clone); this._updateDialogPosition(realDialog, clone);
clone._updateId = metaDialog.connect('position-changed', dialog => { clone._updateId = realDialog.connect('notify::position', dialog => {
this._updateDialogPosition(dialog, clone); this._updateDialogPosition(dialog, clone);
}); });
clone._destroyId = realDialog.connect('destroy', () => { clone._destroyId = realDialog.connect('destroy', () => {
@ -171,7 +171,6 @@ var WindowClone = new Lang.Class({
}, },
_onPositionChanged() { _onPositionChanged() {
let rect = this.metaWindow.get_frame_rect();
this.actor.set_position(this.realWindow.x, this.realWindow.y); this.actor.set_position(this.realWindow.x, this.realWindow.y);
}, },
@ -179,7 +178,7 @@ var WindowClone = new Lang.Class({
this.actor.get_children().forEach(child => { this.actor.get_children().forEach(child => {
let realWindow = child.source; let realWindow = child.source;
realWindow.meta_window.disconnect(child._updateId); realWindow.disconnect(child._updateId);
realWindow.disconnect(child._destroyId); realWindow.disconnect(child._destroyId);
}); });
}, },
@ -417,7 +416,7 @@ var WorkspaceThumbnail = new Lang.Class({
} else if (metaWin.is_attached_dialog()) { } else if (metaWin.is_attached_dialog()) {
let parent = metaWin.get_transient_for(); let parent = metaWin.get_transient_for();
while (parent.is_attached_dialog()) while (parent.is_attached_dialog())
parent = metaWin.get_transient_for(); parent = parent.get_transient_for();
let idx = this._lookupIndex (parent); let idx = this._lookupIndex (parent);
if (idx < 0) { if (idx < 0) {

View File

@ -1,5 +1,5 @@
project('gnome-shell', 'c', project('gnome-shell', 'c',
version: '3.29.4', version: '3.29.90',
meson_version: '>= 0.42.0', meson_version: '>= 0.42.0',
license: 'GPLv2+' license: 'GPLv2+'
) )
@ -23,9 +23,9 @@ gi_req = '>= 1.49.1'
gjs_req = '>= 1.47.0' gjs_req = '>= 1.47.0'
gtk_req = '>= 3.15.0' gtk_req = '>= 3.15.0'
json_glib_req = '>= 0.13.2' json_glib_req = '>= 0.13.2'
mutter_req = '>= 3.29.4' mutter_req = '>= 3.29.90'
polkit_req = '>= 0.100' polkit_req = '>= 0.100'
schemas_req = '>= 3.21.3' schemas_req = '>= 3.27.90'
startup_req = '>= 0.11' startup_req = '>= 0.11'
ibus_req = '>= 1.5.2' ibus_req = '>= 1.5.2'
@ -44,10 +44,12 @@ datadir = join_paths(prefix, get_option('datadir'))
libdir = join_paths(prefix, get_option('libdir')) libdir = join_paths(prefix, get_option('libdir'))
libexecdir = join_paths(prefix, get_option('libexecdir')) libexecdir = join_paths(prefix, get_option('libexecdir'))
mandir = join_paths(prefix, get_option('mandir')) mandir = join_paths(prefix, get_option('mandir'))
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
pkgdatadir = join_paths(datadir, meson.project_name()) pkgdatadir = join_paths(datadir, meson.project_name())
pkglibdir = join_paths(libdir, meson.project_name()) pkglibdir = join_paths(libdir, meson.project_name())
autostartdir = join_paths(sysconfdir, 'xdg', 'autostart')
convertdir = join_paths(datadir, 'GConf', 'gsettings') convertdir = join_paths(datadir, 'GConf', 'gsettings')
desktopdir = join_paths(datadir, 'applications') desktopdir = join_paths(datadir, 'applications')
ifacedir = join_paths(datadir, 'dbus-1', 'interfaces') ifacedir = join_paths(datadir, 'dbus-1', 'interfaces')
@ -64,7 +66,7 @@ plugindir = get_variable('BROWSER_PLUGIN_DIR', mozplugindir)
# systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir', # systemduserunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
# define_variable: ['prefix', prefix]) # define_variable: ['prefix', prefix])
# and uncomment systemd_dep below # and uncomment systemd_dep below
systemduserunitdir = join_paths(libdir, 'systemd', 'user') systemduserunitdir = join_paths(prefix, 'lib', 'systemd', 'user')
keybindings_dep = dependency('gnome-keybindings', required: false) keybindings_dep = dependency('gnome-keybindings', required: false)
if keybindings_dep.found() if keybindings_dep.found()
@ -161,6 +163,11 @@ cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
cdata.set('HAVE_NETWORKMANAGER', have_networkmanager) cdata.set('HAVE_NETWORKMANAGER', have_networkmanager)
cdata.set('HAVE_SYSTEMD', have_systemd) cdata.set('HAVE_SYSTEMD', have_systemd)
# New API added in glib-2.57.2
cdata.set('HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS',
cc.has_function('g_desktop_app_info_launch_uris_as_manager_with_fds',
dependencies : gio_dep)
)
cdata.set('HAVE_FDWALK', cc.has_function('fdwalk')) cdata.set('HAVE_FDWALK', cc.has_function('fdwalk'))
cdata.set('HAVE_MALLINFO', cc.has_function('mallinfo')) cdata.set('HAVE_MALLINFO', cc.has_function('mallinfo'))
cdata.set('HAVE_SYS_RESOURCE_H', cc.has_header('sys/resource.h')) cdata.set('HAVE_SYS_RESOURCE_H', cc.has_header('sys/resource.h'))
@ -168,6 +175,10 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY') cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY')
) )
cdata.set('HAVE_FDWALK',
cc.has_function('fdwalk')
)
config_h = configure_file( config_h = configure_file(
input: 'config.h.meson', input: 'config.h.meson',
output: 'config.h', output: 'config.h',
@ -194,6 +205,7 @@ subdir('src')
subdir('po') subdir('po')
subdir('data') subdir('data')
subdir('tests') subdir('tests')
subdir('tools')
if get_option('gtk_doc') if get_option('gtk_doc')
subdir('docs/reference') subdir('docs/reference')

View File

@ -40,6 +40,7 @@ js/ui/messageList.js
js/ui/messageTray.js js/ui/messageTray.js
js/ui/mpris.js js/ui/mpris.js
js/ui/notificationDaemon.js js/ui/notificationDaemon.js
js/ui/osdWindow.js
js/ui/overviewControls.js js/ui/overviewControls.js
js/ui/overview.js js/ui/overview.js
js/ui/padOsd.js js/ui/padOsd.js
@ -58,6 +59,7 @@ js/ui/status/location.js
js/ui/status/network.js js/ui/status/network.js
js/ui/status/nightLight.js js/ui/status/nightLight.js
js/ui/status/power.js js/ui/status/power.js
js/ui/status/remoteAccess.js
js/ui/status/rfkill.js js/ui/status/rfkill.js
js/ui/status/system.js js/ui/status/system.js
js/ui/status/thunderbolt.js js/ui/status/thunderbolt.js

164
po/es.po
View File

@ -9,8 +9,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell.master\n" "Project-Id-Version: gnome-shell.master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2018-04-13 19:54+0000\n" "POT-Creation-Date: 2018-07-24 18:34+0000\n"
"PO-Revision-Date: 2018-04-25 12:54+0200\n" "PO-Revision-Date: 2018-07-27 13:15+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n" "Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: es <gnome-es-list@gnome.org>\n" "Language-Team: es <gnome-es-list@gnome.org>\n"
"Language: es\n" "Language: es\n"
@ -18,7 +18,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Gtranslator 2.91.6\n" "X-Generator: Gtranslator 2.91.7\n"
#: data/50-gnome-shell-system.xml:6 #: data/50-gnome-shell-system.xml:6
msgid "System" msgid "System"
@ -366,20 +366,20 @@ msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: js/gdm/loginDialog.js:315 #: js/gdm/loginDialog.js:319
msgid "Choose Session" msgid "Choose Session"
msgstr "Elegir sesión" msgstr "Elegir sesión"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: js/gdm/loginDialog.js:458 #: js/gdm/loginDialog.js:462
msgid "Not listed?" msgid "Not listed?"
msgstr "¿No está en la lista?" msgstr "¿No está en la lista?"
#. Translators: this message is shown below the username entry field #. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm #. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:887 #: js/gdm/loginDialog.js:891
#, javascript-format #, javascript-format
msgid "(e.g., user or %s)" msgid "(e.g., user or %s)"
msgstr "(ej., usuario o %s)" msgstr "(ej., usuario o %s)"
@ -387,12 +387,12 @@ msgstr "(ej., usuario o %s)"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (and don't even care of which one)
#: js/gdm/loginDialog.js:892 js/ui/components/networkAgent.js:243 #: js/gdm/loginDialog.js:896 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:261 #: js/ui/components/networkAgent.js:261
msgid "Username: " msgid "Username: "
msgstr "Nombre de usuario:" msgstr "Nombre de usuario:"
#: js/gdm/loginDialog.js:1228 #: js/gdm/loginDialog.js:1234
msgid "Login Window" msgid "Login Window"
msgstr "Ventana de inicio de sesión" msgstr "Ventana de inicio de sesión"
@ -405,7 +405,7 @@ msgstr "Error de autenticación"
#. as a cue to display our own message. #. as a cue to display our own message.
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: js/gdm/util.js:482 #: js/gdm/util.js:485
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(o pase el dedo)" msgstr "(o pase el dedo)"
@ -645,23 +645,23 @@ msgstr "Frecuentes"
msgid "All" msgid "All"
msgstr "Todas" msgstr "Todas"
#: js/ui/appDisplay.js:1886 #: js/ui/appDisplay.js:1890
msgid "New Window" msgid "New Window"
msgstr "Ventana nueva" msgstr "Ventana nueva"
#: js/ui/appDisplay.js:1900 #: js/ui/appDisplay.js:1904
msgid "Launch using Dedicated Graphics Card" msgid "Launch using Dedicated Graphics Card"
msgstr "Lanzar usando la tarjeta gráfica dedicada" msgstr "Lanzar usando la tarjeta gráfica dedicada"
#: js/ui/appDisplay.js:1927 js/ui/dash.js:285 #: js/ui/appDisplay.js:1931 js/ui/dash.js:285
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Quitar de los favoritos" msgstr "Quitar de los favoritos"
#: js/ui/appDisplay.js:1933 #: js/ui/appDisplay.js:1937
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Añadir a los favoritos" msgstr "Añadir a los favoritos"
#: js/ui/appDisplay.js:1943 #: js/ui/appDisplay.js:1947
msgid "Show Details" msgid "Show Details"
msgstr "Mostrar detalles" msgstr "Mostrar detalles"
@ -808,35 +808,35 @@ msgctxt "event list time"
msgid "All Day" msgid "All Day"
msgstr "Todo el día" msgstr "Todo el día"
#: js/ui/calendar.js:864 #: js/ui/calendar.js:866
msgctxt "calendar heading" msgctxt "calendar heading"
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%A, %d de %B" msgstr "%A, %d de %B"
#: js/ui/calendar.js:868 #: js/ui/calendar.js:870
msgctxt "calendar heading" msgctxt "calendar heading"
msgid "%A, %B %d, %Y" msgid "%A, %B %d, %Y"
msgstr "%A, %d de %B de %Y" msgstr "%A, %d de %B de %Y"
#: js/ui/calendar.js:1086 #: js/ui/calendar.js:1100
msgid "No Notifications" msgid "No Notifications"
msgstr "No hay notificaciones" msgstr "No hay notificaciones"
#: js/ui/calendar.js:1089 #: js/ui/calendar.js:1103
msgid "No Events" msgid "No Events"
msgstr "No hay eventos" msgstr "No hay eventos"
#: js/ui/calendar.js:1117 #: js/ui/calendar.js:1131
msgid "Clear All" msgid "Clear All"
msgstr "Limpiar todo" msgstr "Limpiar todo"
#. Translators: %s is an application name #. Translators: %s is an application name
#: js/ui/closeDialog.js:44 #: js/ui/closeDialog.js:47
#, javascript-format #, javascript-format
msgid "“%s” is not responding." msgid "“%s” is not responding."
msgstr "«%s» no responde." msgstr "«%s» no responde."
#: js/ui/closeDialog.js:45 #: js/ui/closeDialog.js:48
msgid "" msgid ""
"You may choose to wait a short while for it to continue or force the " "You may choose to wait a short while for it to continue or force the "
"application to quit entirely." "application to quit entirely."
@ -844,11 +844,11 @@ msgstr ""
"Puede elegir esperar un momento para que continúe o forzar a la aplicación a " "Puede elegir esperar un momento para que continúe o forzar a la aplicación a "
"terminar." "terminar."
#: js/ui/closeDialog.js:61 #: js/ui/closeDialog.js:64
msgid "Force Quit" msgid "Force Quit"
msgstr "Forzar la salida" msgstr "Forzar la salida"
#: js/ui/closeDialog.js:64 #: js/ui/closeDialog.js:67
msgid "Wait" msgid "Wait"
msgstr "Esperar" msgstr "Esperar"
@ -865,7 +865,7 @@ msgstr "Dispositivo externo desconectado"
msgid "Open with %s" msgid "Open with %s"
msgstr "Abrir con %s" msgstr "Abrir con %s"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295 #: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:297
msgid "Password:" msgid "Password:"
msgstr "Contraseña:" msgstr "Contraseña:"
@ -902,11 +902,11 @@ msgstr "Contraseña de la clave privada:"
msgid "Service: " msgid "Service: "
msgstr "Servicio:" msgstr "Servicio:"
#: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:659 #: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:664
msgid "Authentication required by wireless network" msgid "Authentication required by wireless network"
msgstr "La red inalámbrica requiere autenticación" msgstr "La red inalámbrica requiere autenticación"
#: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:660 #: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:665
#, javascript-format #, javascript-format
msgid "" msgid ""
"Passwords or encryption keys are required to access the wireless network " "Passwords or encryption keys are required to access the wireless network "
@ -915,7 +915,7 @@ msgstr ""
"Se necesitan contraseñas o claves de cifrado para acceder a la red " "Se necesitan contraseñas o claves de cifrado para acceder a la red "
"inalámbrica «%s»." "inalámbrica «%s»."
#: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:663 #: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:668
msgid "Wired 802.1X authentication" msgid "Wired 802.1X authentication"
msgstr "Autenticación 802.1X cableada" msgstr "Autenticación 802.1X cableada"
@ -923,15 +923,15 @@ msgstr "Autenticación 802.1X cableada"
msgid "Network name: " msgid "Network name: "
msgstr "Nombre de la red: " msgstr "Nombre de la red: "
#: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:667 #: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:672
msgid "DSL authentication" msgid "DSL authentication"
msgstr "Autenticación DSL" msgstr "Autenticación DSL"
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:673 #: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:678
msgid "PIN code required" msgid "PIN code required"
msgstr "Código PIN requerido" msgstr "Código PIN requerido"
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:674 #: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:679
msgid "PIN code is needed for the mobile broadband device" 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" msgstr "Se necesita un código PIN para el dispositivo de banda ancha móvil"
@ -939,17 +939,17 @@ msgstr "Se necesita un código PIN para el dispositivo de banda ancha móvil"
msgid "PIN: " msgid "PIN: "
msgstr "PIN: " msgstr "PIN: "
#: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:680 #: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:685
msgid "Mobile broadband network password" msgid "Mobile broadband network password"
msgstr "Contraseña de la red de banda ancha móvil" msgstr "Contraseña de la red de banda ancha móvil"
#: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:664 #: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:669
#: js/ui/components/networkAgent.js:668 js/ui/components/networkAgent.js:681 #: js/ui/components/networkAgent.js:673 js/ui/components/networkAgent.js:686
#, javascript-format #, javascript-format
msgid "A password is required to connect to “%s”." msgid "A password is required to connect to “%s”."
msgstr "Se requiere una contraseña para conectarse a «%s»." msgstr "Se requiere una contraseña para conectarse a «%s»."
#: js/ui/components/networkAgent.js:648 js/ui/status/network.js:1691 #: js/ui/components/networkAgent.js:653 js/ui/status/network.js:1704
msgid "Network Manager" msgid "Network Manager"
msgstr "Gestor de la red" msgstr "Gestor de la red"
@ -969,7 +969,7 @@ msgstr "Autenticar"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327 #: js/ui/components/polkitAgent.js:283 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again." msgid "Sorry, that didnt work. Please try again."
msgstr "Eso no ha funcionado. Inténtelo de nuevo." msgstr "Eso no ha funcionado. Inténtelo de nuevo."
@ -1301,13 +1301,13 @@ msgid "Leave On"
msgstr "Dejar activada" msgstr "Dejar activada"
#: js/ui/kbdA11yDialog.js:59 js/ui/status/bluetooth.js:143 #: js/ui/kbdA11yDialog.js:59 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:1281 #: js/ui/status/network.js:1294
msgid "Turn On" msgid "Turn On"
msgstr "Encender" msgstr "Encender"
#: js/ui/kbdA11yDialog.js:67 js/ui/status/bluetooth.js:143 #: js/ui/kbdA11yDialog.js:67 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:154 js/ui/status/network.js:337 #: js/ui/status/network.js:154 js/ui/status/network.js:337
#: js/ui/status/network.js:1281 js/ui/status/network.js:1396 #: js/ui/status/network.js:1294 js/ui/status/network.js:1409
#: js/ui/status/nightLight.js:47 js/ui/status/rfkill.js:90 #: js/ui/status/nightLight.js:47 js/ui/status/rfkill.js:90
#: js/ui/status/rfkill.js:117 #: js/ui/status/rfkill.js:117
msgid "Turn Off" msgid "Turn Off"
@ -1369,7 +1369,7 @@ msgstr "Ver fuente"
msgid "Web Page" msgid "Web Page"
msgstr "Página web" msgstr "Página web"
#: js/ui/messageTray.js:1493 #: js/ui/messageTray.js:1495
msgid "System Information" msgid "System Information"
msgstr "Información del sistema" msgstr "Información del sistema"
@ -1443,22 +1443,22 @@ msgstr "Pulse Esc para salir"
msgid "Press any key to exit" msgid "Press any key to exit"
msgstr "Pulse cualquier tecla para salir" msgstr "Pulse cualquier tecla para salir"
#: js/ui/panel.js:355 #: js/ui/panel.js:356
msgid "Quit" msgid "Quit"
msgstr "Salir" msgstr "Salir"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: js/ui/panel.js:411 #: js/ui/panel.js:412
msgid "Activities" msgid "Activities"
msgstr "Actividades" msgstr "Actividades"
#: js/ui/panel.js:692 #: js/ui/panel.js:693
msgctxt "System menu in the top bar" msgctxt "System menu in the top bar"
msgid "System" msgid "System"
msgstr "Sistema" msgstr "Sistema"
#: js/ui/panel.js:811 #: js/ui/panel.js:816
msgid "Top Bar" msgid "Top Bar"
msgstr "Barra superior" msgstr "Barra superior"
@ -1467,7 +1467,7 @@ msgstr "Barra superior"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: js/ui/popupMenu.js:291 #: js/ui/popupMenu.js:300
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-intl"
@ -1475,15 +1475,15 @@ msgstr "toggle-switch-intl"
msgid "Enter a Command" msgid "Enter a Command"
msgstr "Introducir un comando" msgstr "Introducir un comando"
#: js/ui/runDialog.js:110 js/ui/windowMenu.js:175 #: js/ui/runDialog.js:110 js/ui/windowMenu.js:174
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
#: js/ui/runDialog.js:273 #: js/ui/runDialog.js:274
msgid "Restart is not available on Wayland" msgid "Restart is not available on Wayland"
msgstr "Reiniciar si no está disponible en Wayland" msgstr "Reiniciar si no está disponible en Wayland"
#: js/ui/runDialog.js:278 #: js/ui/runDialog.js:279
msgid "Restarting…" msgid "Restarting…"
msgstr "Reiniciando…" msgstr "Reiniciando…"
@ -1690,7 +1690,7 @@ msgid "<unknown>"
msgstr "<desconocido>" msgstr "<desconocido>"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:441 js/ui/status/network.js:1310 #: js/ui/status/network.js:441 js/ui/status/network.js:1323
#, javascript-format #, javascript-format
msgid "%s Off" msgid "%s Off"
msgstr "%s apagada" msgstr "%s apagada"
@ -1716,7 +1716,7 @@ msgid "%s Disconnecting"
msgstr "Desconectando %s" msgstr "Desconectando %s"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:459 js/ui/status/network.js:1302 #: js/ui/status/network.js:459 js/ui/status/network.js:1315
#, javascript-format #, javascript-format
msgid "%s Connecting" msgid "%s Connecting"
msgstr "Conectando %s" msgstr "Conectando %s"
@ -1756,7 +1756,7 @@ msgid "Mobile Broadband Settings"
msgstr "Configuración de banda ancha móvil" msgstr "Configuración de banda ancha móvil"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:578 js/ui/status/network.js:1307 #: js/ui/status/network.js:578 js/ui/status/network.js:1320
#, javascript-format #, javascript-format
msgid "%s Hardware Disabled" msgid "%s Hardware Disabled"
msgstr "Hardware %s desactivado" msgstr "Hardware %s desactivado"
@ -1812,81 +1812,81 @@ msgstr "No hay redes"
msgid "Use hardware switch to turn off" msgid "Use hardware switch to turn off"
msgstr "Usar el interruptor hardware para apagar" msgstr "Usar el interruptor hardware para apagar"
#: js/ui/status/network.js:1173 #: js/ui/status/network.js:1186
msgid "Select Network" msgid "Select Network"
msgstr "Seleccionar red" msgstr "Seleccionar red"
#: js/ui/status/network.js:1179 #: js/ui/status/network.js:1192
msgid "Wi-Fi Settings" msgid "Wi-Fi Settings"
msgstr "Configuración de Wi-Fi" msgstr "Configuración de Wi-Fi"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:1298 #: js/ui/status/network.js:1311
#, javascript-format #, javascript-format
msgid "%s Hotspot Active" msgid "%s Hotspot Active"
msgstr "Punto de acceso %s activo" msgstr "Punto de acceso %s activo"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:1313 #: js/ui/status/network.js:1326
#, javascript-format #, javascript-format
msgid "%s Not Connected" msgid "%s Not Connected"
msgstr "%s no conectado" msgstr "%s no conectado"
#: js/ui/status/network.js:1413 #: js/ui/status/network.js:1426
msgid "connecting…" msgid "connecting…"
msgstr "conectando…" msgstr "conectando…"
#. Translators: this is for network connections that require some kind of key or password #. Translators: this is for network connections that require some kind of key or password
#: js/ui/status/network.js:1416 #: js/ui/status/network.js:1429
msgid "authentication required" msgid "authentication required"
msgstr "se necesita autenticación" msgstr "se necesita autenticación"
#: js/ui/status/network.js:1418 #: js/ui/status/network.js:1431
msgid "connection failed" msgid "connection failed"
msgstr "falló la conexión" msgstr "falló la conexión"
#: js/ui/status/network.js:1472 #: js/ui/status/network.js:1485
msgid "VPN Settings" msgid "VPN Settings"
msgstr "Configuración de VPN" msgstr "Configuración de VPN"
#: js/ui/status/network.js:1485 #: js/ui/status/network.js:1498
msgid "VPN" msgid "VPN"
msgstr "VPN" msgstr "VPN"
#: js/ui/status/network.js:1495 #: js/ui/status/network.js:1508
msgid "VPN Off" msgid "VPN Off"
msgstr "VPN apagada" msgstr "VPN apagada"
#: js/ui/status/network.js:1559 js/ui/status/rfkill.js:93 #: js/ui/status/network.js:1572 js/ui/status/rfkill.js:93
msgid "Network Settings" msgid "Network Settings"
msgstr "Configuración de la red" msgstr "Configuración de la red"
#: js/ui/status/network.js:1588 #: js/ui/status/network.js:1601
#, javascript-format #, javascript-format
msgid "%s Wired Connection" msgid "%s Wired Connection"
msgid_plural "%s Wired Connections" msgid_plural "%s Wired Connections"
msgstr[0] "%s conexión cableada" msgstr[0] "%s conexión cableada"
msgstr[1] "%s conexiones cableadas" msgstr[1] "%s conexiones cableadas"
#: js/ui/status/network.js:1592 #: js/ui/status/network.js:1605
#, javascript-format #, javascript-format
msgid "%s Wi-Fi Connection" msgid "%s Wi-Fi Connection"
msgid_plural "%s Wi-Fi Connections" msgid_plural "%s Wi-Fi Connections"
msgstr[0] "%s conexión inalámbrica" msgstr[0] "%s conexión inalámbrica"
msgstr[1] "%s conexiones inalámbricas" msgstr[1] "%s conexiones inalámbricas"
#: js/ui/status/network.js:1596 #: js/ui/status/network.js:1609
#, javascript-format #, javascript-format
msgid "%s Modem Connection" msgid "%s Modem Connection"
msgid_plural "%s Modem Connections" msgid_plural "%s Modem Connections"
msgstr[0] "%s conexión por módem" msgstr[0] "%s conexión por módem"
msgstr[1] "%s conexiones por módem" msgstr[1] "%s conexiones por módem"
#: js/ui/status/network.js:1728 #: js/ui/status/network.js:1741
msgid "Connection failed" msgid "Connection failed"
msgstr "Falló la conexión" msgstr "Falló la conexión"
#: js/ui/status/network.js:1729 #: js/ui/status/network.js:1742
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "Falló la activación de la conexión de red" msgstr "Falló la activación de la conexión de red"
@ -1937,6 +1937,15 @@ msgstr "%d%02d para la carga completa (%d%%)"
msgid "%d%%" msgid "%d%%"
msgstr "%d%%" msgstr "%d%%"
#: js/ui/status/remoteAccess.js:45
msgid "Screen is Being Shared"
msgstr "Se está compartiendo la pantalla"
#: js/ui/status/remoteAccess.js:47
#| msgid "Turn Off"
msgid "Turn off"
msgstr "Apagar"
#. The menu only appears when airplane mode is on, so just #. The menu only appears when airplane mode is on, so just
#. statically build it as if it was on, rather than dynamically #. statically build it as if it was on, rather than dynamically
#. changing the menu contents. #. changing the menu contents.
@ -1968,16 +1977,16 @@ msgstr "Suspender"
msgid "Power Off" msgid "Power Off"
msgstr "Apagar" msgstr "Apagar"
#: js/ui/status/thunderbolt.js:294 #: js/ui/status/thunderbolt.js:298
msgid "Thunderbolt" msgid "Thunderbolt"
msgstr "Thunderbolt" msgstr "Thunderbolt"
#. we are done #. we are done
#: js/ui/status/thunderbolt.js:350 #: js/ui/status/thunderbolt.js:354
msgid "Unknown Thunderbolt device" msgid "Unknown Thunderbolt device"
msgstr "Dispositivo Thunderbolt desconocido" msgstr "Dispositivo Thunderbolt desconocido"
#: js/ui/status/thunderbolt.js:351 #: js/ui/status/thunderbolt.js:355
msgid "" msgid ""
"New device has been detected while you were away. Please disconnect and " "New device has been detected while you were away. Please disconnect and "
"reconnect the device to start using it." "reconnect the device to start using it."
@ -1985,13 +1994,12 @@ msgstr ""
"Se ha detectado un dispositivo nuevo mientras estaba fuera. Desconéctelo y " "Se ha detectado un dispositivo nuevo mientras estaba fuera. Desconéctelo y "
"vuélvalo a conectar para empezar a usarlo." "vuélvalo a conectar para empezar a usarlo."
#: js/ui/status/thunderbolt.js:356 #: js/ui/status/thunderbolt.js:360
msgid "Thunderbolt authorization error" msgid "Thunderbolt authorization error"
msgstr "Error de autorización de Thunderbolt" msgstr "Error de autorización de Thunderbolt"
#: js/ui/status/thunderbolt.js:357 #: js/ui/status/thunderbolt.js:361
#, javascript-format #, javascript-format
#| msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s" msgid "Could not authorize the Thunderbolt device: %s"
msgstr "No se pudo autorizar el dispositivo Thunderbolt: %s" msgstr "No se pudo autorizar el dispositivo Thunderbolt: %s"
@ -2076,7 +2084,7 @@ msgstr[1] "La configuración se revertirá en %d segundos"
#. Translators: This represents the size of a window. The first number is #. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height. #. * the width of the window and the second is the height.
#: js/ui/windowManager.js:660 #: js/ui/windowManager.js:668
#, javascript-format #, javascript-format
msgid "%d × %d" msgid "%d × %d"
msgstr "%d × %d" msgstr "%d × %d"
@ -2129,19 +2137,19 @@ msgstr "Subir a un área de trabajo"
msgid "Move to Workspace Down" msgid "Move to Workspace Down"
msgstr "Bajar a un área de trabajo" msgstr "Bajar a un área de trabajo"
#: js/ui/windowMenu.js:140 #: js/ui/windowMenu.js:139
msgid "Move to Monitor Up" msgid "Move to Monitor Up"
msgstr "Mover a la pantalla de arriba" msgstr "Mover a la pantalla de arriba"
#: js/ui/windowMenu.js:149 #: js/ui/windowMenu.js:148
msgid "Move to Monitor Down" msgid "Move to Monitor Down"
msgstr "Mover a la pantalla de abajo" msgstr "Mover a la pantalla de abajo"
#: js/ui/windowMenu.js:158 #: js/ui/windowMenu.js:157
msgid "Move to Monitor Left" msgid "Move to Monitor Left"
msgstr "Mover a la pantalla de la izquierda" msgstr "Mover a la pantalla de la izquierda"
#: js/ui/windowMenu.js:167 #: js/ui/windowMenu.js:166
msgid "Move to Monitor Right" msgid "Move to Monitor Right"
msgstr "Mover a la pantalla de la derecha" msgstr "Mover a la pantalla de la derecha"
@ -2172,12 +2180,12 @@ msgstr ""
msgid "List possible modes" msgid "List possible modes"
msgstr "Listar los modos posibles" msgstr "Listar los modos posibles"
#: src/shell-app.c:270 #: src/shell-app.c:272
msgctxt "program" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Desconocido" msgstr "Desconocido"
#: src/shell-app.c:511 #: src/shell-app.c:523
#, c-format #, c-format
msgid "Failed to launch “%s”" msgid "Failed to launch “%s”"
msgstr "Falló al lanzar «%s»" msgstr "Falló al lanzar «%s»"

View File

@ -14,22 +14,22 @@
# Alain Lojewski <allomervan@gmail.com>, 2014-2018. # Alain Lojewski <allomervan@gmail.com>, 2014-2018.
# Erwan Georget <egeorget@opmbx.org>, 2016. # Erwan Georget <egeorget@opmbx.org>, 2016.
# Claude Paroz <claude@2xlibre.net>, 2010-2011, 2016. # Claude Paroz <claude@2xlibre.net>, 2010-2011, 2016.
# Charles Monzat <superboa@hotmail.fr>, 2016. # Charles Monzat <superboa@hotmail.fr>, 2016, 2018.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master fr\n" "Project-Id-Version: gnome-shell master fr\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2018-03-03 10:22+0000\n" "POT-Creation-Date: 2018-04-13 19:54+0000\n"
"PO-Revision-Date: 2018-03-01 09:00+0100\n" "PO-Revision-Date: 2018-04-18 19:30+0200\n"
"Last-Translator: Alain Lojewski <allomervan@gmail.com>\n" "Last-Translator: Charles Monzat <superboa@hotmail.fr>\n"
"Language-Team: français <gnomefr@traduc.org>\n" "Language-Team: français <gnomefr@traduc.org>\n"
"Language: fr\n" "Language: fr\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 1.8.12\n" "X-Generator: Gtranslator 2.91.7\n"
#: data/50-gnome-shell-system.xml:6 #: data/50-gnome-shell-system.xml:6
msgid "System" msgid "System"
@ -234,7 +234,7 @@ msgstr ""
#: data/org.gnome.shell.gschema.xml.in:116 #: data/org.gnome.shell.gschema.xml.in:116
msgid "Keybinding to open the overview" msgid "Keybinding to open the overview"
msgstr "Combinaison de touches pour ouvrir la vue d'ensemble" msgstr "Combinaison de touches pour ouvrir la vue densemble"
#: data/org.gnome.shell.gschema.xml.in:117 #: data/org.gnome.shell.gschema.xml.in:117
msgid "Keybinding to open the Activities Overview." msgid "Keybinding to open the Activities Overview."
@ -329,7 +329,7 @@ msgstr ""
#: data/org.gnome.shell.gschema.xml.in:206 #: data/org.gnome.shell.gschema.xml.in:206
msgid "Enable edge tiling when dropping windows on screen edges" msgid "Enable edge tiling when dropping windows on screen edges"
msgstr "Activer lempilage des fenêtres déposées sur les bords de l'écran" msgstr "Activer lempilage des fenêtres déposées sur les bords de lécran"
#: data/org.gnome.shell.gschema.xml.in:214 #: data/org.gnome.shell.gschema.xml.in:214
msgid "Workspaces are managed dynamically" msgid "Workspaces are managed dynamically"
@ -362,7 +362,7 @@ msgstr ""
"préférences de %s :" "préférences de %s :"
#: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71 #: js/gdm/authPrompt.js:147 js/ui/audioDeviceSelection.js:71
#: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:148 #: js/ui/components/networkAgent.js:117 js/ui/components/polkitAgent.js:153
#: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197 #: js/ui/endSessionDialog.js:482 js/ui/extensionDownloader.js:197
#: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919 #: js/ui/shellMountOperation.js:343 js/ui/status/network.js:919
msgid "Cancel" msgid "Cancel"
@ -682,12 +682,12 @@ msgstr "Ajouter aux favoris"
msgid "Show Details" msgid "Show Details"
msgstr "Afficher les détails" msgstr "Afficher les détails"
#: js/ui/appFavorites.js:138 #: js/ui/appFavorites.js:140
#, javascript-format #, javascript-format
msgid "%s has been added to your favorites." msgid "%s has been added to your favorites."
msgstr "%s a été ajouté à vos favoris." msgstr "%s a été ajouté à vos favoris."
#: js/ui/appFavorites.js:172 #: js/ui/appFavorites.js:174
#, javascript-format #, javascript-format
msgid "%s has been removed from your favorites." msgid "%s has been removed from your favorites."
msgstr "%s a été supprimé de vos favoris." msgstr "%s a été supprimé de vos favoris."
@ -897,7 +897,7 @@ msgstr "Disque externe déconnecté"
msgid "Open with %s" msgid "Open with %s"
msgstr "Ouvrir avec %s" msgstr "Ouvrir avec %s"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:284 #: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295
msgid "Password:" msgid "Password:"
msgstr "Mot de passe :" msgstr "Mot de passe :"
@ -985,15 +985,15 @@ msgstr "Un mot de passe est requis pour se connecter à « %s »."
msgid "Network Manager" msgid "Network Manager"
msgstr "Gestionnaire de réseau" msgstr "Gestionnaire de réseau"
#: js/ui/components/polkitAgent.js:43 #: js/ui/components/polkitAgent.js:48
msgid "Authentication Required" msgid "Authentication Required"
msgstr "Authentification nécessaire" msgstr "Authentification nécessaire"
#: js/ui/components/polkitAgent.js:71 #: js/ui/components/polkitAgent.js:76
msgid "Administrator" msgid "Administrator"
msgstr "Administrateur" msgstr "Administrateur"
#: js/ui/components/polkitAgent.js:151 #: js/ui/components/polkitAgent.js:156
msgid "Authenticate" msgid "Authenticate"
msgstr "Sauthentifier" msgstr "Sauthentifier"
@ -1001,7 +1001,7 @@ msgstr "Sauthentifier"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: js/ui/components/polkitAgent.js:270 js/ui/shellMountOperation.js:327 #: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again." msgid "Sorry, that didnt work. Please try again."
msgstr "Échec de lauthentification. Essayez à nouveau." msgstr "Échec de lauthentification. Essayez à nouveau."
@ -1061,7 +1061,7 @@ msgstr "Ajouter des horloges locales…"
msgid "World Clocks" msgid "World Clocks"
msgstr "Horloges locales" msgstr "Horloges locales"
#: js/ui/dateMenu.js:225 #: js/ui/dateMenu.js:227
msgid "Weather" msgid "Weather"
msgstr "Météo" msgstr "Météo"
@ -1069,7 +1069,7 @@ msgstr "Météo"
#. libgweather for the possible condition strings. If at all #. libgweather for the possible condition strings. If at all
#. possible, the sentence should match the grammatical case etc. of #. possible, the sentence should match the grammatical case etc. of
#. the inserted conditions. #. the inserted conditions.
#: js/ui/dateMenu.js:289 #: js/ui/dateMenu.js:291
#, javascript-format #, javascript-format
msgid "%s all day." msgid "%s all day."
msgstr "%s toute la journée." msgstr "%s toute la journée."
@ -1078,7 +1078,7 @@ msgstr "%s toute la journée."
#. libgweather for the possible condition strings. If at all #. libgweather for the possible condition strings. If at all
#. possible, the sentence should match the grammatical case etc. of #. possible, the sentence should match the grammatical case etc. of
#. the inserted conditions. #. the inserted conditions.
#: js/ui/dateMenu.js:295 #: js/ui/dateMenu.js:297
#, javascript-format #, javascript-format
msgid "%s, then %s later." msgid "%s, then %s later."
msgstr "%s, puis %s plus tard." msgstr "%s, puis %s plus tard."
@ -1087,30 +1087,30 @@ msgstr "%s, puis %s plus tard."
#. libgweather for the possible condition strings. If at all #. libgweather for the possible condition strings. If at all
#. possible, the sentence should match the grammatical case etc. of #. possible, the sentence should match the grammatical case etc. of
#. the inserted conditions. #. the inserted conditions.
#: js/ui/dateMenu.js:301 #: js/ui/dateMenu.js:303
#, javascript-format #, javascript-format
msgid "%s, then %s, followed by %s later." msgid "%s, then %s, followed by %s later."
msgstr "%s, puis %s, suivi par %s plus tard." msgstr "%s, puis %s, suivi par %s plus tard."
#: js/ui/dateMenu.js:312 #: js/ui/dateMenu.js:314
msgid "Select a location…" msgid "Select a location…"
msgstr "Choisir un emplacement…" msgstr "Choisir un emplacement…"
#: js/ui/dateMenu.js:315 #: js/ui/dateMenu.js:317
msgid "Loading…" msgid "Loading…"
msgstr "Chargement…" msgstr "Chargement…"
#. Translators: %s is a temperature with unit, e.g. "23℃" #. Translators: %s is a temperature with unit, e.g. "23℃"
#: js/ui/dateMenu.js:321 #: js/ui/dateMenu.js:323
#, javascript-format #, javascript-format
msgid "Feels like %s." msgid "Feels like %s."
msgstr "Température ressentie : %s." msgstr "Température ressentie : %s."
#: js/ui/dateMenu.js:324 #: js/ui/dateMenu.js:326
msgid "Go online for weather information" msgid "Go online for weather information"
msgstr "Chercher les informations météorologiques en ligne" msgstr "Chercher les informations météorologiques en ligne"
#: js/ui/dateMenu.js:326 #: js/ui/dateMenu.js:328
msgid "Weather information is currently unavailable" msgid "Weather information is currently unavailable"
msgstr "Les informations météorologiques ne sont pas disponibles actuellement" msgstr "Les informations météorologiques ne sont pas disponibles actuellement"
@ -1706,7 +1706,7 @@ msgstr "Paramètres de confidentialité"
#: js/ui/status/location.js:196 #: js/ui/status/location.js:196
msgid "Location In Use" msgid "Location In Use"
msgstr "Localisation en cours d'utilisation" msgstr "Localisation en cours dutilisation"
#: js/ui/status/location.js:200 #: js/ui/status/location.js:200
msgid "Location Disabled" msgid "Location Disabled"
@ -1947,11 +1947,11 @@ msgstr "Reprendre"
#: js/ui/status/nightLight.js:71 #: js/ui/status/nightLight.js:71
msgid "Disable Until Tomorrow" msgid "Disable Until Tomorrow"
msgstr "Désactiver jusqu'à demain" msgstr "Désactiver jusquà demain"
#: js/ui/status/power.js:61 #: js/ui/status/power.js:61
msgid "Power Settings" msgid "Power Settings"
msgstr "Paramètres de gestion de l'énergie" msgstr "Paramètres de gestion de lénergie"
#: js/ui/status/power.js:77 #: js/ui/status/power.js:77
msgid "Fully Charged" msgid "Fully Charged"
@ -2011,16 +2011,16 @@ msgstr "Mettre en veille"
msgid "Power Off" msgid "Power Off"
msgstr "Éteindre" msgstr "Éteindre"
#: js/ui/status/thunderbolt.js:272 #: js/ui/status/thunderbolt.js:294
msgid "Thunderbolt" msgid "Thunderbolt"
msgstr "Interface Thunderbolt" msgstr "Interface Thunderbolt"
#. we are done #. we are done
#: js/ui/status/thunderbolt.js:328 #: js/ui/status/thunderbolt.js:350
msgid "Unknown Thunderbolt device" msgid "Unknown Thunderbolt device"
msgstr "Périphérique Thunderbolt inconnu" msgstr "Périphérique Thunderbolt inconnu"
#: js/ui/status/thunderbolt.js:329 #: js/ui/status/thunderbolt.js:351
msgid "" msgid ""
"New device has been detected while you were away. Please disconnect and " "New device has been detected while you were away. Please disconnect and "
"reconnect the device to start using it." "reconnect the device to start using it."
@ -2028,13 +2028,14 @@ msgstr ""
"Un nouveau périphérique a été détecté pendant votre absence. Veuillez le " "Un nouveau périphérique a été détecté pendant votre absence. Veuillez le "
"débrancher et rebrancher avant de commencer à lutiliser" "débrancher et rebrancher avant de commencer à lutiliser"
#: js/ui/status/thunderbolt.js:334 #: js/ui/status/thunderbolt.js:356
msgid "Thunderbolt authorization error" msgid "Thunderbolt authorization error"
msgstr "Erreur dautorisation Thunderbolt" msgstr "Erreur dautorisation Thunderbolt"
#: js/ui/status/thunderbolt.js:335 #: js/ui/status/thunderbolt.js:357
#, javascript-format #, javascript-format
msgid "Could not authorize the thunderbolt device: %s" #| msgid "Could not authorize the thunderbolt device: %s"
msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Impossible dautoriser le périphérique Thunderbolt : %s" msgstr "Impossible dautoriser le périphérique Thunderbolt : %s"
#: js/ui/status/volume.js:128 #: js/ui/status/volume.js:128

File diff suppressed because it is too large Load Diff

160
po/sl.po
View File

@ -8,8 +8,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: gnome-shell master\n" "Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n" "Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2018-04-17 15:11+0000\n" "POT-Creation-Date: 2018-07-30 17:00+0000\n"
"PO-Revision-Date: 2018-04-17 18:32+0200\n" "PO-Revision-Date: 2018-07-30 22:14+0200\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n" "Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n" "Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: sl\n" "Language: sl\n"
@ -352,20 +352,20 @@ msgctxt "button"
msgid "Sign In" msgid "Sign In"
msgstr "Prijava" msgstr "Prijava"
#: js/gdm/loginDialog.js:315 #: js/gdm/loginDialog.js:319
msgid "Choose Session" msgid "Choose Session"
msgstr "Izbor seje" msgstr "Izbor seje"
#. translators: this message is shown below the user list on the #. translators: this message is shown below the user list on the
#. login screen. It can be activated to reveal an entry for #. login screen. It can be activated to reveal an entry for
#. manually entering the username. #. manually entering the username.
#: js/gdm/loginDialog.js:458 #: js/gdm/loginDialog.js:462
msgid "Not listed?" msgid "Not listed?"
msgstr "Ali uporabniškega imena ni na seznamu?" msgstr "Ali uporabniškega imena ni na seznamu?"
#. Translators: this message is shown below the username entry field #. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm #. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:887 #: js/gdm/loginDialog.js:891
#, javascript-format #, javascript-format
msgid "(e.g., user or %s)" msgid "(e.g., user or %s)"
msgstr "(na primer, uporabnika ali %s)" msgstr "(na primer, uporabnika ali %s)"
@ -373,12 +373,12 @@ msgstr "(na primer, uporabnika ali %s)"
#. TTLS and PEAP are actually much more complicated, but this complication #. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication #. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one) #. (and don't even care of which one)
#: js/gdm/loginDialog.js:892 js/ui/components/networkAgent.js:243 #: js/gdm/loginDialog.js:896 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:261 #: js/ui/components/networkAgent.js:261
msgid "Username: " msgid "Username: "
msgstr "Uporabniško ime: " msgstr "Uporabniško ime: "
#: js/gdm/loginDialog.js:1228 #: js/gdm/loginDialog.js:1234
msgid "Login Window" msgid "Login Window"
msgstr "Prijavno okno" msgstr "Prijavno okno"
@ -391,7 +391,7 @@ msgstr "Napaka overitve"
#. as a cue to display our own message. #. as a cue to display our own message.
#. Translators: this message is shown below the password entry field #. Translators: this message is shown below the password entry field
#. to indicate the user can swipe their finger instead #. to indicate the user can swipe their finger instead
#: js/gdm/util.js:482 #: js/gdm/util.js:485
msgid "(or swipe finger)" msgid "(or swipe finger)"
msgstr "(ali pa povlecite prst)" msgstr "(ali pa povlecite prst)"
@ -643,23 +643,23 @@ msgstr "Pogosti"
msgid "All" msgid "All"
msgstr "Vsi" msgstr "Vsi"
#: js/ui/appDisplay.js:1886 #: js/ui/appDisplay.js:1890
msgid "New Window" msgid "New Window"
msgstr "Novo okno" msgstr "Novo okno"
#: js/ui/appDisplay.js:1900 #: js/ui/appDisplay.js:1904
msgid "Launch using Dedicated Graphics Card" msgid "Launch using Dedicated Graphics Card"
msgstr "Zaženi z uporabo določene grafične kartice" msgstr "Zaženi z uporabo določene grafične kartice"
#: js/ui/appDisplay.js:1927 js/ui/dash.js:285 #: js/ui/appDisplay.js:1931 js/ui/dash.js:285
msgid "Remove from Favorites" msgid "Remove from Favorites"
msgstr "Odstrani iz priljubljenih" msgstr "Odstrani iz priljubljenih"
#: js/ui/appDisplay.js:1933 #: js/ui/appDisplay.js:1937
msgid "Add to Favorites" msgid "Add to Favorites"
msgstr "Dodaj med priljubljene" msgstr "Dodaj med priljubljene"
#: js/ui/appDisplay.js:1943 #: js/ui/appDisplay.js:1947
msgid "Show Details" msgid "Show Details"
msgstr "Pokaži besedilo" msgstr "Pokaži besedilo"
@ -806,35 +806,35 @@ msgctxt "event list time"
msgid "All Day" msgid "All Day"
msgstr "Celodnevno" msgstr "Celodnevno"
#: js/ui/calendar.js:864 #: js/ui/calendar.js:866
msgctxt "calendar heading" msgctxt "calendar heading"
msgid "%A, %B %d" msgid "%A, %B %d"
msgstr "%A, %d. %m." msgstr "%A, %d. %m."
#: js/ui/calendar.js:868 #: js/ui/calendar.js:870
msgctxt "calendar heading" msgctxt "calendar heading"
msgid "%A, %B %d, %Y" msgid "%A, %B %d, %Y"
msgstr "%A, %d %B %Y" msgstr "%A, %d %B %Y"
#: js/ui/calendar.js:1086 #: js/ui/calendar.js:1100
msgid "No Notifications" msgid "No Notifications"
msgstr "Ni obvestil" msgstr "Ni obvestil"
#: js/ui/calendar.js:1089 #: js/ui/calendar.js:1103
msgid "No Events" msgid "No Events"
msgstr "Ni dogodkov" msgstr "Ni dogodkov"
#: js/ui/calendar.js:1117 #: js/ui/calendar.js:1131
msgid "Clear All" msgid "Clear All"
msgstr "Počisti vse" msgstr "Počisti vse"
#. Translators: %s is an application name #. Translators: %s is an application name
#: js/ui/closeDialog.js:44 #: js/ui/closeDialog.js:47
#, javascript-format #, javascript-format
msgid "“%s” is not responding." msgid "“%s” is not responding."
msgstr "Program »%s« se ne odziva." msgstr "Program »%s« se ne odziva."
#: js/ui/closeDialog.js:45 #: js/ui/closeDialog.js:48
msgid "" msgid ""
"You may choose to wait a short while for it to continue or force the " "You may choose to wait a short while for it to continue or force the "
"application to quit entirely." "application to quit entirely."
@ -842,11 +842,11 @@ msgstr ""
"Lahko počakate, če se program morda začne spet odzivati, lahko pa vsilite " "Lahko počakate, če se program morda začne spet odzivati, lahko pa vsilite "
"končanje delovanja." "končanje delovanja."
#: js/ui/closeDialog.js:61 #: js/ui/closeDialog.js:64
msgid "Force Quit" msgid "Force Quit"
msgstr "Vsili končanje" msgstr "Vsili končanje"
#: js/ui/closeDialog.js:64 #: js/ui/closeDialog.js:67
msgid "Wait" msgid "Wait"
msgstr "Počakaj" msgstr "Počakaj"
@ -863,7 +863,7 @@ msgstr "Zunanji pogon je odklopljen"
msgid "Open with %s" msgid "Open with %s"
msgstr "Odpri s programom %s" msgstr "Odpri s programom %s"
#: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:295 #: js/ui/components/keyring.js:107 js/ui/components/polkitAgent.js:297
msgid "Password:" msgid "Password:"
msgstr "Geslo:" msgstr "Geslo:"
@ -900,11 +900,11 @@ msgstr "Geslo zasebnega ključa: "
msgid "Service: " msgid "Service: "
msgstr "Storitev: " msgstr "Storitev: "
#: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:659 #: js/ui/components/networkAgent.js:292 js/ui/components/networkAgent.js:664
msgid "Authentication required by wireless network" msgid "Authentication required by wireless network"
msgstr "Zahtevana overitev za brezžično omrežje" msgstr "Zahtevana overitev za brezžično omrežje"
#: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:660 #: js/ui/components/networkAgent.js:293 js/ui/components/networkAgent.js:665
#, javascript-format #, javascript-format
msgid "" msgid ""
"Passwords or encryption keys are required to access the wireless network " "Passwords or encryption keys are required to access the wireless network "
@ -913,7 +913,7 @@ msgstr ""
"Za povezavo v brezžično omrežje »%s« je zahtevano geslo oziroma šifrirni " "Za povezavo v brezžično omrežje »%s« je zahtevano geslo oziroma šifrirni "
"ključ." "ključ."
#: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:663 #: js/ui/components/networkAgent.js:297 js/ui/components/networkAgent.js:668
msgid "Wired 802.1X authentication" msgid "Wired 802.1X authentication"
msgstr "Žična overitev 802.1X" msgstr "Žična overitev 802.1X"
@ -921,15 +921,15 @@ msgstr "Žična overitev 802.1X"
msgid "Network name: " msgid "Network name: "
msgstr "Naziv omrežja: " msgstr "Naziv omrežja: "
#: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:667 #: js/ui/components/networkAgent.js:304 js/ui/components/networkAgent.js:672
msgid "DSL authentication" msgid "DSL authentication"
msgstr "Overitev DSL" msgstr "Overitev DSL"
#: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:673 #: js/ui/components/networkAgent.js:311 js/ui/components/networkAgent.js:678
msgid "PIN code required" msgid "PIN code required"
msgstr "Zahtevana koda PIN" msgstr "Zahtevana koda PIN"
#: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:674 #: js/ui/components/networkAgent.js:312 js/ui/components/networkAgent.js:679
msgid "PIN code is needed for the mobile broadband device" msgid "PIN code is needed for the mobile broadband device"
msgstr "Za napravo mobilnega širokopasovnega dostopa je zahtevana koda PIN." msgstr "Za napravo mobilnega širokopasovnega dostopa je zahtevana koda PIN."
@ -937,17 +937,17 @@ msgstr "Za napravo mobilnega širokopasovnega dostopa je zahtevana koda PIN."
msgid "PIN: " msgid "PIN: "
msgstr "Koda PIN: " msgstr "Koda PIN: "
#: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:680 #: js/ui/components/networkAgent.js:320 js/ui/components/networkAgent.js:685
msgid "Mobile broadband network password" msgid "Mobile broadband network password"
msgstr "Geslo mobilnega širokopasovnega dostopa" msgstr "Geslo mobilnega širokopasovnega dostopa"
#: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:664 #: js/ui/components/networkAgent.js:321 js/ui/components/networkAgent.js:669
#: js/ui/components/networkAgent.js:668 js/ui/components/networkAgent.js:681 #: js/ui/components/networkAgent.js:673 js/ui/components/networkAgent.js:686
#, javascript-format #, javascript-format
msgid "A password is required to connect to “%s”." msgid "A password is required to connect to “%s”."
msgstr "Za povezavo z omrežjem »%s« je zahtevano geslo." msgstr "Za povezavo z omrežjem »%s« je zahtevano geslo."
#: js/ui/components/networkAgent.js:648 js/ui/status/network.js:1691 #: js/ui/components/networkAgent.js:653 js/ui/status/network.js:1704
msgid "Network Manager" msgid "Network Manager"
msgstr "Upravljalnik omrežij" msgstr "Upravljalnik omrežij"
@ -967,7 +967,7 @@ msgstr "Overi"
#. * requested authentication was not gained; this can happen #. * requested authentication was not gained; this can happen
#. * because of an authentication error (like invalid password), #. * because of an authentication error (like invalid password),
#. * for instance. #. * for instance.
#: js/ui/components/polkitAgent.js:281 js/ui/shellMountOperation.js:327 #: js/ui/components/polkitAgent.js:283 js/ui/shellMountOperation.js:327
msgid "Sorry, that didnt work. Please try again." msgid "Sorry, that didnt work. Please try again."
msgstr "Overitev je spodletela.. Poskusite znova." msgstr "Overitev je spodletela.. Poskusite znova."
@ -1309,13 +1309,13 @@ msgid "Leave On"
msgstr "Pusti omogočeno" msgstr "Pusti omogočeno"
#: js/ui/kbdA11yDialog.js:59 js/ui/status/bluetooth.js:143 #: js/ui/kbdA11yDialog.js:59 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:1281 #: js/ui/status/network.js:1294
msgid "Turn On" msgid "Turn On"
msgstr "Omogoči" msgstr "Omogoči"
#: js/ui/kbdA11yDialog.js:67 js/ui/status/bluetooth.js:143 #: js/ui/kbdA11yDialog.js:67 js/ui/status/bluetooth.js:143
#: js/ui/status/network.js:154 js/ui/status/network.js:337 #: js/ui/status/network.js:154 js/ui/status/network.js:337
#: js/ui/status/network.js:1281 js/ui/status/network.js:1396 #: js/ui/status/network.js:1294 js/ui/status/network.js:1409
#: js/ui/status/nightLight.js:47 js/ui/status/rfkill.js:90 #: js/ui/status/nightLight.js:47 js/ui/status/rfkill.js:90
#: js/ui/status/rfkill.js:117 #: js/ui/status/rfkill.js:117
msgid "Turn Off" msgid "Turn Off"
@ -1377,7 +1377,7 @@ msgstr "Poglej vir"
msgid "Web Page" msgid "Web Page"
msgstr "Spletna stran" msgstr "Spletna stran"
#: js/ui/messageTray.js:1493 #: js/ui/messageTray.js:1495
msgid "System Information" msgid "System Information"
msgstr "Podrobnosti sistema" msgstr "Podrobnosti sistema"
@ -1451,22 +1451,22 @@ msgstr "Pritisnite tipko Esc za končanje"
msgid "Press any key to exit" msgid "Press any key to exit"
msgstr "Pritisnite katerokoli tipko za končanje" msgstr "Pritisnite katerokoli tipko za končanje"
#: js/ui/panel.js:355 #: js/ui/panel.js:356
msgid "Quit" msgid "Quit"
msgstr "Končaj" msgstr "Končaj"
#. Translators: If there is no suitable word for "Activities" #. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview". #. in your language, you can use the word for "Overview".
#: js/ui/panel.js:411 #: js/ui/panel.js:412
msgid "Activities" msgid "Activities"
msgstr "Dejavnosti" msgstr "Dejavnosti"
#: js/ui/panel.js:692 #: js/ui/panel.js:693
msgctxt "System menu in the top bar" msgctxt "System menu in the top bar"
msgid "System" msgid "System"
msgstr "Sistem" msgstr "Sistem"
#: js/ui/panel.js:811 #: js/ui/panel.js:816
msgid "Top Bar" msgid "Top Bar"
msgstr "Vrhnja vrstica" msgstr "Vrhnja vrstica"
@ -1475,7 +1475,7 @@ msgstr "Vrhnja vrstica"
#. "ON" and "OFF") or "toggle-switch-intl" (for toggle #. "ON" and "OFF") or "toggle-switch-intl" (for toggle
#. switches containing "◯" and "|"). Other values will #. switches containing "◯" and "|"). Other values will
#. simply result in invisible toggle switches. #. simply result in invisible toggle switches.
#: js/ui/popupMenu.js:291 #: js/ui/popupMenu.js:300
msgid "toggle-switch-us" msgid "toggle-switch-us"
msgstr "toggle-switch-intl" msgstr "toggle-switch-intl"
@ -1483,15 +1483,15 @@ msgstr "toggle-switch-intl"
msgid "Enter a Command" msgid "Enter a Command"
msgstr "Vnos ukaza" msgstr "Vnos ukaza"
#: js/ui/runDialog.js:110 js/ui/windowMenu.js:175 #: js/ui/runDialog.js:110 js/ui/windowMenu.js:174
msgid "Close" msgid "Close"
msgstr "Zapri" msgstr "Zapri"
#: js/ui/runDialog.js:273 #: js/ui/runDialog.js:274
msgid "Restart is not available on Wayland" msgid "Restart is not available on Wayland"
msgstr "Na sistemu Wayland je na voljo ponovni zagon" msgstr "Na sistemu Wayland je na voljo ponovni zagon"
#: js/ui/runDialog.js:278 #: js/ui/runDialog.js:279
msgid "Restarting…" msgid "Restarting…"
msgstr "Ponovno zaganjanje ...." msgstr "Ponovno zaganjanje ...."
@ -1706,7 +1706,7 @@ msgid "<unknown>"
msgstr "<neznano>" msgstr "<neznano>"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:441 js/ui/status/network.js:1310 #: js/ui/status/network.js:441 js/ui/status/network.js:1323
#, javascript-format #, javascript-format
msgid "%s Off" msgid "%s Off"
msgstr "%s izklopljeno" msgstr "%s izklopljeno"
@ -1732,7 +1732,7 @@ msgid "%s Disconnecting"
msgstr "%s poteka prekinjanje povezave" msgstr "%s poteka prekinjanje povezave"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:459 js/ui/status/network.js:1302 #: js/ui/status/network.js:459 js/ui/status/network.js:1315
#, javascript-format #, javascript-format
msgid "%s Connecting" msgid "%s Connecting"
msgstr "%s poteka vzpostavljanje povezave" msgstr "%s poteka vzpostavljanje povezave"
@ -1772,7 +1772,7 @@ msgid "Mobile Broadband Settings"
msgstr "Nastavitve mobilnega širokopasovnega dostopa" msgstr "Nastavitve mobilnega širokopasovnega dostopa"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:578 js/ui/status/network.js:1307 #: js/ui/status/network.js:578 js/ui/status/network.js:1320
#, javascript-format #, javascript-format
msgid "%s Hardware Disabled" msgid "%s Hardware Disabled"
msgstr "%s strojno onemogočeno" msgstr "%s strojno onemogočeno"
@ -1828,56 +1828,56 @@ msgstr "Ni zaznanih omrežij"
msgid "Use hardware switch to turn off" msgid "Use hardware switch to turn off"
msgstr "Uporabite strojni gumb za izklop" msgstr "Uporabite strojni gumb za izklop"
#: js/ui/status/network.js:1173 #: js/ui/status/network.js:1186
msgid "Select Network" msgid "Select Network"
msgstr "Izbor omrežja" msgstr "Izbor omrežja"
#: js/ui/status/network.js:1179 #: js/ui/status/network.js:1192
msgid "Wi-Fi Settings" msgid "Wi-Fi Settings"
msgstr "Nastavitve Wi-Fi" msgstr "Nastavitve Wi-Fi"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:1298 #: js/ui/status/network.js:1311
#, javascript-format #, javascript-format
msgid "%s Hotspot Active" msgid "%s Hotspot Active"
msgstr "%s vroča točka je dejavna" msgstr "%s vroča točka je dejavna"
#. Translators: %s is a network identifier #. Translators: %s is a network identifier
#: js/ui/status/network.js:1313 #: js/ui/status/network.js:1326
#, javascript-format #, javascript-format
msgid "%s Not Connected" msgid "%s Not Connected"
msgstr "%s brez povezave" msgstr "%s brez povezave"
#: js/ui/status/network.js:1413 #: js/ui/status/network.js:1426
msgid "connecting…" msgid "connecting…"
msgstr "vzpostavljanje povezave …" msgstr "vzpostavljanje povezave …"
#. Translators: this is for network connections that require some kind of key or password #. Translators: this is for network connections that require some kind of key or password
#: js/ui/status/network.js:1416 #: js/ui/status/network.js:1429
msgid "authentication required" msgid "authentication required"
msgstr "zahtevana je overitev" msgstr "zahtevana je overitev"
#: js/ui/status/network.js:1418 #: js/ui/status/network.js:1431
msgid "connection failed" msgid "connection failed"
msgstr "povezovanje je spodletelo" msgstr "povezovanje je spodletelo"
#: js/ui/status/network.js:1472 #: js/ui/status/network.js:1485
msgid "VPN Settings" msgid "VPN Settings"
msgstr "Nastavitve VPN" msgstr "Nastavitve VPN"
#: js/ui/status/network.js:1485 #: js/ui/status/network.js:1498
msgid "VPN" msgid "VPN"
msgstr "VPN" msgstr "VPN"
#: js/ui/status/network.js:1495 #: js/ui/status/network.js:1508
msgid "VPN Off" msgid "VPN Off"
msgstr "Onemogočen VPN" msgstr "Onemogočen VPN"
#: js/ui/status/network.js:1559 js/ui/status/rfkill.js:93 #: js/ui/status/network.js:1572 js/ui/status/rfkill.js:93
msgid "Network Settings" msgid "Network Settings"
msgstr "Omrežne nastavitve" msgstr "Omrežne nastavitve"
#: js/ui/status/network.js:1588 #: js/ui/status/network.js:1601
#, javascript-format #, javascript-format
msgid "%s Wired Connection" msgid "%s Wired Connection"
msgid_plural "%s Wired Connections" msgid_plural "%s Wired Connections"
@ -1886,7 +1886,7 @@ msgstr[1] "%s žična povezava"
msgstr[2] "%s žični povezavi" msgstr[2] "%s žični povezavi"
msgstr[3] "%s žične povezave" msgstr[3] "%s žične povezave"
#: js/ui/status/network.js:1592 #: js/ui/status/network.js:1605
#, javascript-format #, javascript-format
msgid "%s Wi-Fi Connection" msgid "%s Wi-Fi Connection"
msgid_plural "%s Wi-Fi Connections" msgid_plural "%s Wi-Fi Connections"
@ -1895,7 +1895,7 @@ msgstr[1] "%s povezava Wi-Fi"
msgstr[2] "%s povezavi Wi-Fi" msgstr[2] "%s povezavi Wi-Fi"
msgstr[3] "%s povezave Wi-Fi" msgstr[3] "%s povezave Wi-Fi"
#: js/ui/status/network.js:1596 #: js/ui/status/network.js:1609
#, javascript-format #, javascript-format
msgid "%s Modem Connection" msgid "%s Modem Connection"
msgid_plural "%s Modem Connections" msgid_plural "%s Modem Connections"
@ -1904,11 +1904,11 @@ msgstr[1] "%s modemska povezava"
msgstr[2] "%s modemski povezavi" msgstr[2] "%s modemski povezavi"
msgstr[3] "%s modemske povezave" msgstr[3] "%s modemske povezave"
#: js/ui/status/network.js:1728 #: js/ui/status/network.js:1741
msgid "Connection failed" msgid "Connection failed"
msgstr "Povezovanje je spodletelo" msgstr "Povezovanje je spodletelo"
#: js/ui/status/network.js:1729 #: js/ui/status/network.js:1742
msgid "Activation of network connection failed" msgid "Activation of network connection failed"
msgstr "Omogočanje omrežne povezave je spodletelo." msgstr "Omogočanje omrežne povezave je spodletelo."
@ -1959,6 +1959,14 @@ msgstr "%d%02d do polnosti (%d%%)"
msgid "%d%%" msgid "%d%%"
msgstr "%d%%" msgstr "%d%%"
#: js/ui/status/remoteAccess.js:46
msgid "Screen is Being Shared"
msgstr "Zaslon je v načinu souporabe"
#: js/ui/status/remoteAccess.js:48
msgid "Turn off"
msgstr "Izklopi"
#. The menu only appears when airplane mode is on, so just #. The menu only appears when airplane mode is on, so just
#. statically build it as if it was on, rather than dynamically #. statically build it as if it was on, rather than dynamically
#. changing the menu contents. #. changing the menu contents.
@ -1990,16 +1998,16 @@ msgstr "V pripravljenost"
msgid "Power Off" msgid "Power Off"
msgstr "Izklop" msgstr "Izklop"
#: js/ui/status/thunderbolt.js:294 #: js/ui/status/thunderbolt.js:298
msgid "Thunderbolt" msgid "Thunderbolt"
msgstr "Thunderbolt" msgstr "Thunderbolt"
#. we are done #. we are done
#: js/ui/status/thunderbolt.js:350 #: js/ui/status/thunderbolt.js:354
msgid "Unknown Thunderbolt device" msgid "Unknown Thunderbolt device"
msgstr "Neznana naprava Thunderbolt" msgstr "Neznana naprava Thunderbolt"
#: js/ui/status/thunderbolt.js:351 #: js/ui/status/thunderbolt.js:355
msgid "" msgid ""
"New device has been detected while you were away. Please disconnect and " "New device has been detected while you were away. Please disconnect and "
"reconnect the device to start using it." "reconnect the device to start using it."
@ -2007,11 +2015,11 @@ msgstr ""
"Med nedejavnostjo je bila zaznana nova. Odklopite napravo in jo znova " "Med nedejavnostjo je bila zaznana nova. Odklopite napravo in jo znova "
"priklopite za uporabo." "priklopite za uporabo."
#: js/ui/status/thunderbolt.js:356 #: js/ui/status/thunderbolt.js:360
msgid "Thunderbolt authorization error" msgid "Thunderbolt authorization error"
msgstr "Napaka overitve naprave Thunderbolt" msgstr "Napaka overitve naprave Thunderbolt"
#: js/ui/status/thunderbolt.js:357 #: js/ui/status/thunderbolt.js:361
#, javascript-format #, javascript-format
msgid "Could not authorize the Thunderbolt device: %s" msgid "Could not authorize the Thunderbolt device: %s"
msgstr "Naprave Thunderbolt ni mogoče overiti: %s" msgstr "Naprave Thunderbolt ni mogoče overiti: %s"
@ -2099,7 +2107,7 @@ msgstr[3] "Spremembe nastavitev bodo povrnjene v %d sekundah."
#. Translators: This represents the size of a window. The first number is #. Translators: This represents the size of a window. The first number is
#. * the width of the window and the second is the height. #. * the width of the window and the second is the height.
#: js/ui/windowManager.js:660 #: js/ui/windowManager.js:668
#, javascript-format #, javascript-format
msgid "%d × %d" msgid "%d × %d"
msgstr "%d × %d" msgstr "%d × %d"
@ -2152,19 +2160,19 @@ msgstr "Premakni na zgornjo delovno površino"
msgid "Move to Workspace Down" msgid "Move to Workspace Down"
msgstr "Premakni na spodnjo delovno površino" msgstr "Premakni na spodnjo delovno površino"
#: js/ui/windowMenu.js:140 #: js/ui/windowMenu.js:139
msgid "Move to Monitor Up" msgid "Move to Monitor Up"
msgstr "Premakni na zaslon zgoraj" msgstr "Premakni na zaslon zgoraj"
#: js/ui/windowMenu.js:149 #: js/ui/windowMenu.js:148
msgid "Move to Monitor Down" msgid "Move to Monitor Down"
msgstr "Premakni na zaslon spodaj" msgstr "Premakni na zaslon spodaj"
#: js/ui/windowMenu.js:158 #: js/ui/windowMenu.js:157
msgid "Move to Monitor Left" msgid "Move to Monitor Left"
msgstr "Premakni na zaslon levo" msgstr "Premakni na zaslon levo"
#: js/ui/windowMenu.js:167 #: js/ui/windowMenu.js:166
msgid "Move to Monitor Right" msgid "Move to Monitor Right"
msgstr "Premakni na zaslon desno" msgstr "Premakni na zaslon desno"
@ -2193,12 +2201,12 @@ msgstr "Uporabi poseben način, na primer »gdm« za prijavni zaslon"
msgid "List possible modes" msgid "List possible modes"
msgstr "Seznam mogočih načinov" msgstr "Seznam mogočih načinov"
#: src/shell-app.c:270 #: src/shell-app.c:272
msgctxt "program" msgctxt "program"
msgid "Unknown" msgid "Unknown"
msgstr "Neznano" msgstr "Neznano"
#: src/shell-app.c:511 #: src/shell-app.c:523
#, c-format #, c-format
msgid "Failed to launch “%s”" msgid "Failed to launch “%s”"
msgstr "Zaganjanje »%s« je spodletelo" msgstr "Zaganjanje »%s« je spodletelo"

View File

@ -31,8 +31,6 @@ extern GType gnome_shell_plugin_get_type (void);
#define SHELL_DBUS_SERVICE "org.gnome.Shell" #define SHELL_DBUS_SERVICE "org.gnome.Shell"
#define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier" #define MAGNIFIER_DBUS_SERVICE "org.gnome.Magnifier"
#define OVERRIDES_SCHEMA "org.gnome.shell.overrides"
#define WM_NAME "GNOME Shell" #define WM_NAME "GNOME Shell"
#define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell" #define GNOME_WM_KEYBINDINGS "Mutter,GNOME Shell"
@ -172,26 +170,6 @@ shell_dbus_init (gboolean replace)
g_object_unref (session); g_object_unref (session);
} }
static void
shell_prefs_init (void)
{
ShellGlobal *global = shell_global_get ();
GSettings *settings = shell_global_get_overrides_settings (global);
GSettingsSchema *schema;
char **keys, **k;
if (!settings)
return;
g_object_get (G_OBJECT (settings), "settings-schema", &schema, NULL);
for (keys = k = g_settings_schema_list_keys (schema); *k; k++)
meta_prefs_override_preference_schema (*k, g_settings_schema_get_id (schema));
g_strfreev (keys);
g_settings_schema_unref (schema);
}
static void static void
shell_introspection_init (void) shell_introspection_init (void)
{ {
@ -509,8 +487,6 @@ main (int argc, char **argv)
_shell_global_init ("session-mode", session_mode, NULL); _shell_global_init ("session-mode", session_mode, NULL);
shell_prefs_init ();
dump_gjs_stack_on_signal (SIGABRT); dump_gjs_stack_on_signal (SIGABRT);
dump_gjs_stack_on_signal (SIGFPE); dump_gjs_stack_on_signal (SIGFPE);
dump_gjs_stack_on_signal (SIGIOT); dump_gjs_stack_on_signal (SIGIOT);

View File

@ -551,15 +551,46 @@ void
shell_app_open_new_window (ShellApp *app, shell_app_open_new_window (ShellApp *app,
int workspace) int workspace)
{ {
GActionGroup *group = NULL;
const char * const *actions;
g_return_if_fail (app->info != NULL); g_return_if_fail (app->info != NULL);
/* Here we just always launch the application again, even if we know /* First check whether the application provides a "new-window" desktop
* action - it is a safe bet that it will open a new window, and activating
* it will trigger startup notification if necessary
*/
actions = g_desktop_app_info_list_actions (G_DESKTOP_APP_INFO (app->info));
if (g_strv_contains (actions, "new-window"))
{
shell_app_launch_action (app, "new-window", 0, workspace);
return;
}
/* Next, check whether the app exports an explicit "new-window" action
* that we can activate on the bus - the muxer will add startup notification
* information to the platform data, so this should work just as well as
* desktop actions.
*/
group = app->running_state ? G_ACTION_GROUP (app->running_state->muxer)
: NULL;
if (group &&
g_action_group_has_action (group, "app.new-window") &&
g_action_group_get_action_parameter_type (group, "app.new-window") == NULL)
{
g_action_group_activate_action (group, "app.new-window", NULL);
return;
}
/* Lastly, just always launch the application again, even if we know
* it was already running. For most applications this * it was already running. For most applications this
* should have the effect of creating a new window, whether that's * should have the effect of creating a new window, whether that's
* a second process (in the case of Calculator) or IPC to existing * a second process (in the case of Calculator) or IPC to existing
* instance (Firefox). There are a few less-sensical cases such * instance (Firefox). There are a few less-sensical cases such
* as say Pidgin. Ideally, we have the application express to us * as say Pidgin.
* that it supports an explicit new-window action.
*/ */
shell_app_launch (app, 0, workspace, FALSE, NULL); shell_app_launch (app, 0, workspace, FALSE, NULL);
} }
@ -586,10 +617,7 @@ shell_app_can_open_new_window (ShellApp *app)
state = app->running_state; state = app->running_state;
/* If the app has an explicit new-window action, then it can /* If the app has an explicit new-window action, then it can
(or it should be able to) ...
(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")) if (g_action_group_has_action (G_ACTION_GROUP (state->muxer), "app.new-window"))
return TRUE; return TRUE;
@ -1179,7 +1207,7 @@ shell_app_request_quit (ShellApp *app)
return TRUE; return TRUE;
} }
#ifdef HAVE_SYSTEMD #if !defined(HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS) && defined(HAVE_SYSTEMD)
/* This sets up the launched application to log to the journal /* This sets up the launched application to log to the journal
* using its own identifier, instead of just "gnome-session". * using its own identifier, instead of just "gnome-session".
*/ */
@ -1227,6 +1255,7 @@ shell_app_launch (ShellApp *app,
ShellGlobal *global; ShellGlobal *global;
GAppLaunchContext *context; GAppLaunchContext *context;
gboolean ret; gboolean ret;
GSpawnFlags flags;
if (app->info == NULL) if (app->info == NULL)
{ {
@ -1246,9 +1275,39 @@ shell_app_launch (ShellApp *app,
if (discrete_gpu) if (discrete_gpu)
g_app_launch_context_setenv (context, "DRI_PRIME", "1"); g_app_launch_context_setenv (context, "DRI_PRIME", "1");
/* Set LEAVE_DESCRIPTORS_OPEN in order to use an optimized gspawn
* codepath. The shell's open file descriptors should be marked CLOEXEC
* so that they are automatically closed even with this flag set.
*/
flags = G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD |
G_SPAWN_LEAVE_DESCRIPTORS_OPEN;
#ifdef HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS
/* Optimized spawn path, avoiding a child_setup function */
{
int journalfd = -1;
#ifdef HAVE_SYSTEMD
journalfd = sd_journal_stream_fd (shell_app_get_id (app), LOG_INFO, FALSE);
#endif /* HAVE_SYSTEMD */
ret = g_desktop_app_info_launch_uris_as_manager_with_fds (app->info, NULL,
context,
flags,
NULL, NULL,
wait_pid, NULL,
-1,
journalfd,
journalfd,
error);
if (journalfd >= 0)
(void) close (journalfd);
}
#else /* !HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS */
ret = g_desktop_app_info_launch_uris_as_manager (app->info, NULL, ret = g_desktop_app_info_launch_uris_as_manager (app->info, NULL,
context, context,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, flags,
#ifdef HAVE_SYSTEMD #ifdef HAVE_SYSTEMD
app_child_setup, (gpointer)shell_app_get_id (app), app_child_setup, (gpointer)shell_app_get_id (app),
#else #else
@ -1256,6 +1315,7 @@ shell_app_launch (ShellApp *app,
#endif #endif
wait_pid, NULL, wait_pid, NULL,
error); error);
#endif /* HAVE_GIO_DESKTOP_LAUNCH_URIS_WITH_FDS */
g_object_unref (context); g_object_unref (context);
return ret; return ret;

View File

@ -1338,37 +1338,6 @@ shell_global_get_settings (ShellGlobal *global)
return global->settings; return global->settings;
} }
/**
* shell_global_get_overrides_settings:
* @global: A #ShellGlobal
*
* Get the session overrides GSettings instance.
*
* Return value: (transfer none): The GSettings object
*/
GSettings *
shell_global_get_overrides_settings (ShellGlobal *global)
{
static GSettings *settings = NULL;
const char *schema;
g_return_val_if_fail (SHELL_IS_GLOBAL (global), NULL);
if (!settings)
{
if (strcmp (global->session_mode, "classic") == 0)
schema = "org.gnome.shell.extensions.classic-overrides";
else if (strcmp (global->session_mode, "user") == 0)
schema = "org.gnome.shell.overrides";
else
return NULL;
settings = g_settings_new (schema);
}
return settings;
}
/** /**
* shell_global_get_current_time: * shell_global_get_current_time:
* @global: A #ShellGlobal * @global: A #ShellGlobal

View File

@ -19,7 +19,6 @@ ClutterStage *shell_global_get_stage (ShellGlobal *global);
MetaDisplay *shell_global_get_display (ShellGlobal *global); MetaDisplay *shell_global_get_display (ShellGlobal *global);
GList *shell_global_get_window_actors (ShellGlobal *global); GList *shell_global_get_window_actors (ShellGlobal *global);
GSettings *shell_global_get_settings (ShellGlobal *global); GSettings *shell_global_get_settings (ShellGlobal *global);
GSettings *shell_global_get_overrides_settings (ShellGlobal *global);
guint32 shell_global_get_current_time (ShellGlobal *global); guint32 shell_global_get_current_time (ShellGlobal *global);

View File

@ -38,8 +38,6 @@ struct _ShellScreenshotPrivate
gboolean include_cursor; gboolean include_cursor;
gboolean include_frame; gboolean include_frame;
ShellScreenshotCallback callback;
}; };
G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT); G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
@ -59,17 +57,15 @@ shell_screenshot_init (ShellScreenshot *screenshot)
static void static void
on_screenshot_written (GObject *source, on_screenshot_written (GObject *source,
GAsyncResult *result, GAsyncResult *task,
gpointer user_data) gpointer user_data)
{ {
ShellScreenshot *screenshot = SHELL_SCREENSHOT (source); ShellScreenshot *screenshot = SHELL_SCREENSHOT (source);
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *result = user_data;
if (priv->callback) g_task_return_boolean (result, g_task_propagate_boolean (G_TASK (task), NULL));
priv->callback (screenshot, g_object_unref (result);
g_task_propagate_boolean (G_TASK (result), NULL),
&priv->screenshot_area,
priv->filename_used);
g_clear_pointer (&priv->image, cairo_surface_destroy); g_clear_pointer (&priv->image, cairo_surface_destroy);
g_clear_pointer (&priv->filename, g_free); g_clear_pointer (&priv->filename, g_free);
@ -313,14 +309,15 @@ _draw_cursor_image (MetaCursorTracker *tracker,
static void static void
grab_screenshot (ClutterActor *stage, grab_screenshot (ClutterActor *stage,
ShellScreenshot *screenshot) GTask *result)
{ {
MetaDisplay *display; MetaDisplay *display;
MetaCursorTracker *tracker; MetaCursorTracker *tracker;
int width, height; int width, height;
GTask *result;
GSettings *settings; GSettings *settings;
ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *task;
display = shell_global_get_display (priv->global); display = shell_global_get_display (priv->global);
meta_display_get_size (display, &width, &height); meta_display_get_size (display, &width, &height);
@ -380,19 +377,20 @@ grab_screenshot (ClutterActor *stage,
} }
g_object_unref (settings); g_object_unref (settings);
g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot); g_signal_handlers_disconnect_by_func (stage, grab_screenshot, result);
result = g_task_new (screenshot, NULL, on_screenshot_written, NULL); task = g_task_new (screenshot, NULL, on_screenshot_written, result);
g_task_run_in_thread (result, write_screenshot_thread); g_task_run_in_thread (task, write_screenshot_thread);
g_object_unref (result); g_object_unref (task);
} }
static void static void
grab_area_screenshot (ClutterActor *stage, grab_area_screenshot (ClutterActor *stage,
ShellScreenshot *screenshot) GTask *result)
{ {
GTask *result; ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *task;
do_grab_screenshot (screenshot, do_grab_screenshot (screenshot,
CLUTTER_STAGE (stage), CLUTTER_STAGE (stage),
@ -401,18 +399,19 @@ grab_area_screenshot (ClutterActor *stage,
priv->screenshot_area.width, priv->screenshot_area.width,
priv->screenshot_area.height); priv->screenshot_area.height);
g_signal_handlers_disconnect_by_func (stage, (void *)grab_area_screenshot, (gpointer)screenshot); g_signal_handlers_disconnect_by_func (stage, grab_area_screenshot, result);
result = g_task_new (screenshot, NULL, on_screenshot_written, NULL); task = g_task_new (screenshot, NULL, on_screenshot_written, result);
g_task_run_in_thread (result, write_screenshot_thread); g_task_run_in_thread (task, write_screenshot_thread);
g_object_unref (result); g_object_unref (task);
} }
static void static void
grab_window_screenshot (ClutterActor *stage, grab_window_screenshot (ClutterActor *stage,
ShellScreenshot *screenshot) GTask *result)
{ {
ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *result; GTask *task;
GSettings *settings; GSettings *settings;
MetaDisplay *display = shell_global_get_display (priv->global); MetaDisplay *display = shell_global_get_display (priv->global);
MetaCursorTracker *tracker; MetaCursorTracker *tracker;
@ -451,12 +450,54 @@ grab_window_screenshot (ClutterActor *stage,
} }
g_object_unref (settings); g_object_unref (settings);
g_signal_handlers_disconnect_by_func (stage, (void *)grab_window_screenshot, (gpointer)screenshot); g_signal_handlers_disconnect_by_func (stage, grab_window_screenshot, result);
result = g_task_new (screenshot, NULL, on_screenshot_written, NULL); task = g_task_new (screenshot, NULL, on_screenshot_written, result);
g_task_run_in_thread (result, write_screenshot_thread); g_task_run_in_thread (task, write_screenshot_thread);
g_object_unref (task);
}
static void
grab_pixel (ClutterActor *stage,
GTask *result)
{
ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv;
do_grab_screenshot (screenshot,
CLUTTER_STAGE (stage),
priv->screenshot_area.x,
priv->screenshot_area.y,
1,
1);
meta_enable_unredirect_for_display (shell_global_get_display (priv->global));
g_signal_handlers_disconnect_by_func (stage, grab_pixel, result);
g_task_return_boolean (result, TRUE);
g_object_unref (result); g_object_unref (result);
} }
static gboolean
finish_screenshot (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error)
{
ShellScreenshotPrivate *priv = screenshot->priv;
if (!g_task_propagate_boolean (G_TASK (result), error))
return FALSE;
if (area)
*area = &priv->screenshot_area;
if (filename_used)
*filename_used = priv->filename_used;
return TRUE;
}
/** /**
* shell_screenshot_screenshot: * shell_screenshot_screenshot:
* @screenshot: the #ShellScreenshot * @screenshot: the #ShellScreenshot
@ -464,39 +505,79 @@ grab_window_screenshot (ClutterActor *stage,
* @filename: The filename for the screenshot * @filename: The filename for the screenshot
* @callback: (scope async): function to call returning success or failure * @callback: (scope async): function to call returning success or failure
* of the async grabbing * of the async grabbing
* @user_data: the data to pass to callback function
* *
* Takes a screenshot of the whole screen * Takes a screenshot of the whole screen
* in @filename as png image. * in @filename as png image.
* *
*/ */
void void
shell_screenshot_screenshot (ShellScreenshot *screenshot, shell_screenshot_screenshot (ShellScreenshot *screenshot,
gboolean include_cursor, gboolean include_cursor,
const char *filename, const char *filename,
ShellScreenshotCallback callback) GAsyncReadyCallback callback,
gpointer user_data)
{ {
ClutterActor *stage; ClutterActor *stage;
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *result;
if (priv->filename != NULL) { if (priv->filename != NULL) {
if (callback) if (callback)
callback (screenshot, FALSE, NULL, ""); g_task_report_new_error (screenshot,
callback,
user_data,
shell_screenshot_screenshot,
G_IO_ERROR,
G_IO_ERROR_PENDING,
"Only one screenshot operation at a time "
"is permitted");
return; return;
} }
result = g_task_new (screenshot, NULL, callback, user_data);
g_task_set_source_tag (result, shell_screenshot_screenshot);
priv->filename = g_strdup (filename); priv->filename = g_strdup (filename);
priv->callback = callback;
priv->include_cursor = include_cursor; priv->include_cursor = include_cursor;
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global)); stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_display (shell_global_get_display (priv->global)); meta_disable_unredirect_for_display (shell_global_get_display (priv->global));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), (gpointer)screenshot); g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), result);
clutter_actor_queue_redraw (stage); clutter_actor_queue_redraw (stage);
} }
/**
* shell_screenshot_screenshot_finish:
* @screenshot: the #ShellScreenshot
* @result: the #GAsyncResult that was provided to the callback
* @area: (out) (transfer none): the area that was grabbed in screen coordinates
* @filename_used: (out) (transfer none): the name of the file the screenshot
* was written to
* @error: #GError for error reporting
*
* Finish the asynchronous operation started by shell_screenshot_screenshot()
* and obtain its result.
*
* Returns: whether the operation was successful
*
*/
gboolean
shell_screenshot_screenshot_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error)
{
g_return_val_if_fail (g_async_result_is_tagged (result,
shell_screenshot_screenshot),
FALSE);
return finish_screenshot (screenshot, result, area, filename_used, error);
}
/** /**
* shell_screenshot_screenshot_area: * shell_screenshot_screenshot_area:
* @screenshot: the #ShellScreenshot * @screenshot: the #ShellScreenshot
@ -507,45 +588,85 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
* @filename: The filename for the screenshot * @filename: The filename for the screenshot
* @callback: (scope async): function to call returning success or failure * @callback: (scope async): function to call returning success or failure
* of the async grabbing * of the async grabbing
* @user_data: the data to pass to callback function
* *
* Takes a screenshot of the passed in area and saves it * Takes a screenshot of the passed in area and saves it
* in @filename as png image. * in @filename as png image.
* *
*/ */
void void
shell_screenshot_screenshot_area (ShellScreenshot *screenshot, shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
int x, int x,
int y, int y,
int width, int width,
int height, int height,
const char *filename, const char *filename,
ShellScreenshotCallback callback) GAsyncReadyCallback callback,
gpointer user_data)
{ {
ClutterActor *stage; ClutterActor *stage;
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
GTask *result;
if (priv->filename != NULL) { if (priv->filename != NULL) {
if (callback) if (callback)
callback (screenshot, FALSE, NULL, ""); g_task_report_new_error (screenshot,
callback,
NULL,
shell_screenshot_screenshot_area,
G_IO_ERROR,
G_IO_ERROR_PENDING,
"Only one screenshot operation at a time "
"is permitted");
return; return;
} }
result = g_task_new (screenshot, NULL, callback, user_data);
g_task_set_source_tag (result, shell_screenshot_screenshot_area);
priv->filename = g_strdup (filename); priv->filename = g_strdup (filename);
priv->screenshot_area.x = x; priv->screenshot_area.x = x;
priv->screenshot_area.y = y; priv->screenshot_area.y = y;
priv->screenshot_area.width = width; priv->screenshot_area.width = width;
priv->screenshot_area.height = height; priv->screenshot_area.height = height;
priv->callback = callback;
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global)); stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ())); meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), (gpointer)screenshot); g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), result);
clutter_actor_queue_redraw (stage); clutter_actor_queue_redraw (stage);
} }
/**
* shell_screenshot_screenshot_area_finish:
* @screenshot: the #ShellScreenshot
* @result: the #GAsyncResult that was provided to the callback
* @area: (out) (transfer none): the area that was grabbed in screen coordinates
* @filename_used: (out) (transfer none): the name of the file the screenshot
* was written to
* @error: #GError for error reporting
*
* Finish the asynchronous operation started by shell_screenshot_screenshot_area()
* and obtain its result.
*
* Returns: whether the operation was successful
*
*/
gboolean
shell_screenshot_screenshot_area_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error)
{
g_return_val_if_fail (g_async_result_is_tagged (result,
shell_screenshot_screenshot_area),
FALSE);
return finish_screenshot (screenshot, result, area, filename_used, error);
}
/** /**
* shell_screenshot_screenshot_window: * shell_screenshot_screenshot_window:
* @screenshot: the #ShellScreenshot * @screenshot: the #ShellScreenshot
@ -554,31 +675,43 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
* @filename: The filename for the screenshot * @filename: The filename for the screenshot
* @callback: (scope async): function to call returning success or failure * @callback: (scope async): function to call returning success or failure
* of the async grabbing * of the async grabbing
* @user_data: the data to pass to callback function
* *
* Takes a screenshot of the focused window (optionally omitting the frame) * Takes a screenshot of the focused window (optionally omitting the frame)
* in @filename as png image. * in @filename as png image.
* *
*/ */
void void
shell_screenshot_screenshot_window (ShellScreenshot *screenshot, shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
gboolean include_frame, gboolean include_frame,
gboolean include_cursor, gboolean include_cursor,
const char *filename, const char *filename,
ShellScreenshotCallback callback) GAsyncReadyCallback callback,
gpointer user_data)
{ {
ShellScreenshotPrivate *priv = screenshot->priv; ShellScreenshotPrivate *priv = screenshot->priv;
MetaDisplay *display = shell_global_get_display (priv->global); MetaDisplay *display = shell_global_get_display (priv->global);
ClutterActor *stage; ClutterActor *stage;
MetaWindow *window = meta_display_get_focus_window (display); MetaWindow *window = meta_display_get_focus_window (display);
GTask *result;
if (priv->filename != NULL || !window) { if (priv->filename != NULL || !window) {
if (callback) if (callback)
callback (screenshot, FALSE, NULL, ""); g_task_report_new_error (screenshot,
callback,
NULL,
shell_screenshot_screenshot_window,
G_IO_ERROR,
G_IO_ERROR_PENDING,
"Only one screenshot operation at a time "
"is permitted");
return; return;
} }
result = g_task_new (screenshot, NULL, callback, user_data);
g_task_set_source_tag (result, shell_screenshot_screenshot_window);
priv->filename = g_strdup (filename); priv->filename = g_strdup (filename);
priv->callback = callback;
priv->include_frame = include_frame; priv->include_frame = include_frame;
priv->include_cursor = include_cursor; priv->include_cursor = include_cursor;
@ -586,11 +719,140 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ())); meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), (gpointer)screenshot); g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), result);
clutter_actor_queue_redraw (stage); clutter_actor_queue_redraw (stage);
} }
/**
* shell_screenshot_screenshot_window_finish:
* @screenshot: the #ShellScreenshot
* @result: the #GAsyncResult that was provided to the callback
* @area: (out) (transfer none): the area that was grabbed in screen coordinates
* @filename_used: (out) (transfer none): the name of the file the screenshot
* was written to
* @error: #GError for error reporting
*
* Finish the asynchronous operation started by shell_screenshot_screenshot_window()
* and obtain its result.
*
* Returns: whether the operation was successful
*
*/
gboolean
shell_screenshot_screenshot_window_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error)
{
g_return_val_if_fail (g_async_result_is_tagged (result,
shell_screenshot_screenshot_window),
FALSE);
return finish_screenshot (screenshot, result, area, filename_used, error);
}
/**
* shell_screenshot_pick_color:
* @screenshot: the #ShellScreenshot
* @x: The X coordinate to pick
* @y: The Y coordinate to pick
* @callback: (scope async): function to call returning success or failure
* of the async grabbing
*
* Picks the pixel at @x, @y and returns its color as #ClutterColor.
*
*/
void
shell_screenshot_pick_color (ShellScreenshot *screenshot,
int x,
int y,
GAsyncReadyCallback callback,
gpointer user_data)
{
ShellScreenshotPrivate *priv = screenshot->priv;
MetaDisplay *display = shell_global_get_display (priv->global);
ClutterActor *stage;
GTask *result;
result = g_task_new (screenshot, NULL, callback, user_data);
g_task_set_source_tag (result, shell_screenshot_pick_color);
priv->screenshot_area.x = x;
priv->screenshot_area.y = y;
priv->screenshot_area.width = 1;
priv->screenshot_area.height = 1;
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_display (display);
g_signal_connect_after (stage, "paint", G_CALLBACK (grab_pixel), result);
clutter_actor_queue_redraw (stage);
}
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define INDEX_A 3
#define INDEX_R 2
#define INDEX_G 1
#define INDEX_B 0
#else
#define INDEX_A 0
#define INDEX_R 1
#define INDEX_G 2
#define INDEX_B 3
#endif
/**
* shell_screenshot_pick_color_finish:
* @screenshot: the #ShellScreenshot
* @result: the #GAsyncResult that was provided to the callback
* @color: (out caller-allocates): the picked color
* @error: #GError for error reporting
*
* Finish the asynchronous operation started by shell_screenshot_pick_color()
* and obtain its result.
*
* Returns: whether the operation was successful
*
*/
gboolean
shell_screenshot_pick_color_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
ClutterColor *color,
GError **error)
{
ShellScreenshotPrivate *priv = screenshot->priv;
g_return_val_if_fail (g_async_result_is_tagged (result,
shell_screenshot_pick_color),
FALSE);
if (!g_task_propagate_boolean (G_TASK (result), error))
return FALSE;
/* protect against mutter changing the format used for stage captures */
g_assert (cairo_image_surface_get_format (priv->image) == CAIRO_FORMAT_ARGB32);
if (color)
{
uint8_t *data = cairo_image_surface_get_data (priv->image);
color->alpha = data[INDEX_A];
color->red = data[INDEX_R];
color->green = data[INDEX_G];
color->blue = data[INDEX_B];
}
return TRUE;
}
#undef INDEX_A
#undef INDEX_R
#undef INDEX_G
#undef INDEX_B
ShellScreenshot * ShellScreenshot *
shell_screenshot_new (void) shell_screenshot_new (void)
{ {

View File

@ -16,28 +16,51 @@ G_DECLARE_FINAL_TYPE (ShellScreenshot, shell_screenshot,
ShellScreenshot *shell_screenshot_new (void); ShellScreenshot *shell_screenshot_new (void);
typedef void (*ShellScreenshotCallback) (ShellScreenshot *screenshot, void shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
gboolean success, int x,
cairo_rectangle_int_t *screenshot_area, int y,
const gchar *filename_used); int width,
int height,
const char *filename,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean shell_screenshot_screenshot_area_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error);
void shell_screenshot_screenshot_area (ShellScreenshot *screenshot, void shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
int x, gboolean include_frame,
int y, gboolean include_cursor,
int width, const char *filename,
int height, GAsyncReadyCallback callback,
const char *filename, gpointer user_data);
ShellScreenshotCallback callback); gboolean shell_screenshot_screenshot_window_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error);
void shell_screenshot_screenshot_window (ShellScreenshot *screenshot, void shell_screenshot_screenshot (ShellScreenshot *screenshot,
gboolean include_frame, gboolean include_cursor,
gboolean include_cursor, const char *filename,
const char *filename, GAsyncReadyCallback callback,
ShellScreenshotCallback callback); gpointer user_data);
gboolean shell_screenshot_screenshot_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
cairo_rectangle_int_t **area,
const char **filename_used,
GError **error);
void shell_screenshot_screenshot (ShellScreenshot *screenshot, void shell_screenshot_pick_color (ShellScreenshot *screenshot,
gboolean include_cursor, int x,
const char *filename, int y,
ShellScreenshotCallback callback); GAsyncReadyCallback callback,
gpointer user_data);
gboolean shell_screenshot_pick_color_finish (ShellScreenshot *screenshot,
GAsyncResult *result,
ClutterColor *color,
GError **error);
#endif /* ___SHELL_SCREENSHOT_H__ */ #endif /* ___SHELL_SCREENSHOT_H__ */

View File

@ -2,8 +2,15 @@
#include "config.h" #include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#include <GL/gl.h> #include <GL/gl.h>
#include <cogl/cogl.h> #include <cogl/cogl.h>
@ -514,3 +521,108 @@ shell_util_composite_capture_images (ClutterCapture *captures,
return image; return image;
} }
#ifndef HAVE_FDWALK
static int
fdwalk (int (*cb)(void *data, int fd),
void *data)
{
gint open_max;
gint fd;
gint res = 0;
#ifdef HAVE_SYS_RESOURCE_H
struct rlimit rl;
#endif
#ifdef __linux__
DIR *d;
if ((d = opendir("/proc/self/fd")))
{
struct dirent *de;
while ((de = readdir(d)))
{
glong l;
gchar *e = NULL;
if (de->d_name[0] == '.')
continue;
errno = 0;
l = strtol(de->d_name, &e, 10);
if (errno != 0 || !e || *e)
continue;
fd = (gint) l;
if ((glong) fd != l)
continue;
if (fd == dirfd(d))
continue;
if ((res = cb (data, fd)) != 0)
break;
}
closedir(d);
return res;
}
/* If /proc is not mounted or not accessible we fall back to the old
* rlimit trick */
#endif
#ifdef HAVE_SYS_RESOURCE_H
if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY)
open_max = rl.rlim_max;
else
#endif
open_max = sysconf (_SC_OPEN_MAX);
for (fd = 0; fd < open_max; fd++)
if ((res = cb (data, fd)) != 0)
break;
return res;
}
#endif
static int
check_cloexec (void *data,
gint fd)
{
int r;
if (fd < 3)
return 0;
r = fcntl (fd, F_GETFD);
if (r < 0)
return 0;
if (!(r & FD_CLOEXEC))
g_warning ("fd %d is not CLOEXEC", fd);
return 0;
}
/**
* shell_util_check_cloexec_fds:
*
* Walk over all open file descriptors. Check them for the FD_CLOEXEC flag.
* If this flag is not set, log the offending file descriptor number.
*
* It is important that gnome-shell's file descriptors are all marked CLOEXEC,
* so that the shell's open file descriptors are not passed to child processes
* that we launch.
*/
void
shell_util_check_cloexec_fds (void)
{
fdwalk (check_cloexec, NULL);
g_info ("Open fd CLOEXEC check complete");
}

View File

@ -60,6 +60,8 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
int width, int width,
int height); int height);
void shell_util_check_cloexec_fds (void);
G_END_DECLS G_END_DECLS
#endif /* __SHELL_UTIL_H__ */ #endif /* __SHELL_UTIL_H__ */

View File

@ -0,0 +1,38 @@
#!/bin/sh
PKG_DATA_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/gnome-shell
MIGRATION_GUARD=$PKG_DATA_DIR/gnome-overrides-migrated
OVERRIDE_SCHEMA=
if [ -f $MIGRATION_GUARD ]; then
exit # already migrated
fi
# Find the right session
if echo $XDG_CURRENT_DESKTOP | grep -q -v GNOME; then
exit # not a GNOME session
fi
if echo $XDG_CURRENT_DESKTOP | grep -q Classic; then
OVERRIDE_SCHEMA=org.gnome.shell.extensions.classic-overrides
else
OVERRIDE_SCHEMA=org.gnome.shell.overrides
fi
mkdir -p $PKG_DATA_DIR
for k in `gsettings list-keys $OVERRIDE_SCHEMA`
do
if [ $k = button-layout ]; then
orig_schema=org.gnome.desktop.wm.preferences
else
orig_schema=org.gnome.mutter
fi
oldValue=`gsettings get $OVERRIDE_SCHEMA $k`
curValue=`gsettings get $orig_schema $k`
if [ $oldValue != $curValue ]; then
gsettings set $orig_schema $k $oldValue
fi
done && touch $MIGRATION_GUARD

4
tools/meson.build Normal file
View File

@ -0,0 +1,4 @@
install_data('gnome-shell-overrides-migration.sh',
install_dir: libexecdir,
install_mode: 'rwxr-xr-x'
)