Compare commits

..

2 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
47a2e58d45 Introduce updates indicator
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/466
2019-03-19 12:18:54 +00:00
Georges Basile Stavracas Neto
20d73be57d Introduce Automatic Updates component
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/466
2019-03-19 12:18:47 +00:00
53 changed files with 4038 additions and 4051 deletions

1
.gitignore vendored
View File

@@ -80,4 +80,3 @@ tests/run-test.sh
*~
*.patch
*.sw?
.vscode

View File

@@ -15,8 +15,10 @@ variables:
- merge_requests
check_commit_log:
image: registry.gitlab.gnome.org/gnome/mutter/master:v1
image: registry.fedoraproject.org/fedora:latest
stage: review
before_script:
- dnf install -y git
script:
- ./.gitlab-ci/check-commit-log.sh
only:

View File

@@ -9,6 +9,9 @@
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels">
<arg type="a{uv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels2">
<arg type="a{sv}" direction="in" name="params"/>
</method>

View File

@@ -1,6 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/theme">
<file>automatic-updates-off-symbolic.svg</file>
<file>automatic-updates-on-symbolic.svg</file>
<file>automatic-updates-scheduled-symbolic.svg</file>
<file>calendar-today.svg</file>
<file>checkbox-focused.svg</file>
<file>checkbox-off-focused.svg</file>

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1auto-updates_OFF</title><path d="M11.03,10.074a.125.125,0,0,0-.086.213l1.347,1.35a5.733,5.733,0,0,1-4.238,1.9,5.6,5.6,0,0,1-2.282-.484l-1.11,1.11a7.024,7.024,0,0,0,3.392.875,7.3,7.3,0,0,0,5.3-2.339l1.357,1.36a.125.125,0,0,0,.213-.086L15,10Z" style="fill:#999"/><path d="M12.921,5.9a6.354,6.354,0,0,1,.326,1.863.248.248,0,0,0,.244.244h1a.261.261,0,0,0,.257-.265,7.543,7.543,0,0,0-.677-2.991Z" style="fill:#999"/><path d="M6.286,9.707a.994.994,0,0,0,.715.3H9a1,1,0,0,0,1-1v-2A.994.994,0,0,0,9.7,6.3l2.175-2.175,0,0L12.93,3.067l0,0,1.4-1.4a.25.25,0,0,0,0-.354L13.617.608a.25.25,0,0,0-.354,0L11.772,2.1A6.97,6.97,0,0,0,7.948.961,7.3,7.3,0,0,0,2.651,3.3L1.293,1.94a.125.125,0,0,0-.214.086L1,6l3.971-.074a.125.125,0,0,0,.086-.213L3.71,4.363a5.733,5.733,0,0,1,4.238-1.9,5.523,5.523,0,0,1,2.723.739L7.86,6.011H7a1,1,0,0,0-1,1V7.87L3.291,10.58a6,6,0,0,1-.537-2.346.248.248,0,0,0-.244-.245h-1a.261.261,0,0,0-.257.265A7.329,7.329,0,0,0,2.172,11.7L.608,13.263a.25.25,0,0,0,0,.354l.707.707a.25.25,0,0,0,.354,0l1.4-1.4,0,0,1.056-1.056,0,0Z" style="fill:#999"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1auto-updates_ON</title><rect x="6.001" y="6.011" width="4" height="4" rx="1" ry="1" style="fill:#999"/><path d="M5.057,5.713,3.71,4.362a5.733,5.733,0,0,1,4.238-1.9,5.173,5.173,0,0,1,5.3,5.305.248.248,0,0,0,.244.244h1a.261.261,0,0,0,.257-.265A6.684,6.684,0,0,0,7.948.961,7.3,7.3,0,0,0,2.65,3.3L1.293,1.94a.125.125,0,0,0-.213.086L1,6l3.971-.074A.125.125,0,0,0,5.057,5.713Z" style="fill:#999"/><path d="M11.03,10.074a.125.125,0,0,0-.086.213l1.347,1.35a5.733,5.733,0,0,1-4.238,1.9,5.173,5.173,0,0,1-5.3-5.305.248.248,0,0,0-.244-.245h-1a.261.261,0,0,0-.257.265,6.684,6.684,0,0,0,6.8,6.785,7.3,7.3,0,0,0,5.3-2.339l1.357,1.36a.125.125,0,0,0,.214-.086L15,10Z" style="fill:#999"/></svg>

After

Width:  |  Height:  |  Size: 767 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><title>EOS_symbolic-icons_v0.1update-scheduled_OUTLINE</title><path d="M7.99,15.054A6.7,6.7,0,0,1,1.06,8,6.7,6.7,0,0,1,7.99.954,6.71,6.71,0,0,1,14.948,8,6.71,6.71,0,0,1,7.99,15.054Zm0-12.6A5.2,5.2,0,0,0,2.56,8a5.2,5.2,0,0,0,5.43,5.55A5.215,5.215,0,0,0,13.448,8,5.216,5.216,0,0,0,7.99,2.454Z" style="fill:#999"/><path d="M9.209,10.443,7.2,8.437a.25.25,0,0,1-.073-.177l0-4.01A.25.25,0,0,1,7.379,4h1.25a.25.25,0,0,1,.25.25l0,3.283a.25.25,0,0,0,.073.177l1.5,1.494a.25.25,0,0,1,0,.354l-.883.884A.25.25,0,0,1,9.209,10.443Z" style="fill:#999"/></svg>

After

Width:  |  Height:  |  Size: 603 B

View File

@@ -21,7 +21,7 @@ $success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
$osd_fg_color: #eeeeec;
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 15%),0.3);
$osd_bg_color: #2e3436;
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);

View File

@@ -29,7 +29,7 @@ $panel-corner-radius: 6px;
/* GLOBALS */
$font-size: 11;
$font-family: Cantarell, Sans-Serif;
$_bubble_bg_color: $osd_bg_color;
$_bubble_bg_color: opacify($osd_bg_color,0.25);
$_bubble_fg_color: $osd_fg_color;
$_bubble_borders_color: transparentize($osd_fg_color,0.8);
@@ -184,7 +184,7 @@ StScrollBar {
.modal-dialog {
border-radius: 9px;
color: $osd_fg_color;
background-color: $osd_bg_color;
background-color: transparentize(darken($osd_bg_color,10%),0.05);
border: 1px solid $_bubble_borders_color;
.modal-dialog-content-box {
padding: 24px;
@@ -1142,12 +1142,6 @@ StScrollBar {
.ripple-box:rtl { border-radius: 0 0 0 52px; } // just a simple change to the border radius position
// Rubberband for select-area screenshots
.select-area-rubberband {
background-color: transparentize($selected_bg_color,0.7);
border: 1px solid $selected_bg_color;
}
// not really top bar only
.popup-menu-arrow { icon-size: 1.09em; }
.popup-menu-icon { icon-size: 1.09em; }

View File

@@ -111,7 +111,7 @@
}
}
@mixin button($t, $c:opacify(lighten($osd_bg_color, 5%),1.0), $tc:$fg_color, $edge: $borders_edge) {
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
//
// Button drawing function
//
@@ -136,7 +136,8 @@
//
// normal button
//
$_bg: $c;
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $osd_fg_color;
background-color: $_bg;
@@ -149,7 +150,8 @@
//
// focused button
//
$_bg: lighten($c,3%);
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
color: $osd_fg_color;
text-shadow: 0 1px black;
@@ -161,7 +163,8 @@
//
// active osd button
//
$_bg: lighten($c,3%);
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
color: white;
border-color: $osd_borders_color;

View File

@@ -551,9 +551,9 @@ class ExtensionRow extends Gtk.ListBoxRow {
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.add(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
visible: true }));
button.get_style_context().add_class('circular');
hbox.add(button);

View File

@@ -9,6 +9,7 @@
<file>gdm/realmd.js</file>
<file>gdm/util.js</file>
<file>misc/updateManager.js</file>
<file>misc/config.js</file>
<file>misc/extensionUtils.js</file>
<file>misc/fileUtils.js</file>
@@ -116,9 +117,11 @@
<file>ui/components/networkAgent.js</file>
<file>ui/components/polkitAgent.js</file>
<file>ui/components/telepathyClient.js</file>
<file>ui/components/updates.js</file>
<file>ui/components/keyring.js</file>
<file>ui/status/accessibility.js</file>
<file>ui/status/automaticUpdates.js</file>
<file>ui/status/brightness.js</file>
<file>ui/status/location.js</file>
<file>ui/status/keyboard.js</file>

338
js/misc/updateManager.js Normal file
View File

@@ -0,0 +1,338 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// Copyright (C) 2019 Endless Mobile, Inc.
//
// This is a GNOME Shell component to wrap the interactions over
// D-Bus with the Mogwai system daemon.
//
// Licensed under the GNU General Public License Version 2
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Clutter, Gio, GLib,
GObject, Gtk, NM, Shell, St } = imports.gi;
const NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME = "connection.automatic-updates-notification-time";
const NM_SETTING_ALLOW_DOWNLOADS = 'connection.allow-downloads';
const NM_SETTING_TARIFF_ENABLED = "connection.tariff-enabled";
const SchedulerInterface = '\
<node> \
<interface name="com.endlessm.DownloadManager1.Scheduler"> \
<property name="ActiveEntryCount" type="u" access="read" /> \
<property name="EntryCount" type="u" access="read" /> \
</interface> \
</node>';
const SchedulerProxy = Gio.DBusProxy.makeProxyWrapper(SchedulerInterface);
let _updateManager = null;
function getUpdateManager() {
if (_updateManager == null)
_updateManager = new UpdateManager();
return _updateManager;
}
var State = {
UNKNOWN: 0,
DISCONNECTED: 1,
DISABLED: 2,
IDLE: 3,
SCHEDULED: 4,
DOWNLOADING: 5
};
function stateToIconName(state) {
switch (state) {
case State.UNKNOWN:
case State.DISCONNECTED:
return null;
case State.DISABLED:
return 'resource:///org/gnome/shell/theme/automatic-updates-off-symbolic.svg';
case State.IDLE:
case State.DOWNLOADING:
return 'resource:///org/gnome/shell/theme/automatic-updates-on-symbolic.svg';
case State.SCHEDULED:
return 'resource:///org/gnome/shell/theme/automatic-updates-scheduled-symbolic.svg';
}
return null;
}
var UpdateManager = GObject.registerClass ({
Properties: {
'last-notification-time': GObject.ParamSpec.int('last-notification-time',
'last-notification-time',
'last-notification-time',
GObject.ParamFlags.READWRITE,
null),
'icon': GObject.ParamSpec.object('icon', 'icon', 'icon',
GObject.ParamFlags.READABLE,
Gio.Icon.$gtype),
'state': GObject.ParamSpec.uint('state', 'state', 'state',
GObject.ParamFlags.READABLE,
null),
},
}, class UpdateManager extends GObject.Object {
_init() {
super._init();
this._activeConnection = null;
this._settingChangedSignalId = 0;
this._updateTimeoutId = 0;
this._state = State.UNKNOWN;
NM.Client.new_async(null, this._clientGot.bind(this));
}
_clientGot(obj, result) {
this._client = NM.Client.new_finish(result);
this._client.connect('notify::primary-connection', this._sync.bind(this));
this._client.connect('notify::state', this._sync.bind(this));
// Start retrieving the Mogwai proxy
this._proxy = new SchedulerProxy(Gio.DBus.system,
'com.endlessm.MogwaiSchedule1',
'/com/endlessm/DownloadManager1',
(proxy, error) => {
if (error) {
log(error.message);
return;
}
this._proxy.connect('g-properties-changed',
this._sync.bind(this));
this._updateStatus();
});
this._sync();
}
_sync() {
if (!this._client || !this._proxy)
return;
if (this._updateTimeoutId > 0) {
GLib.source_remove(this._updateTimeoutId);
this._updateTimeoutId = 0;
}
// Intermediate states (connecting or disconnecting) must not trigger
// any kind of state change.
if (this._client.state == NM.State.CONNECTING || this._client.state == NM.State.DISCONNECTING)
return;
// Use a timeout to avoid instantly throwing the notification at
// the user's face, and to avoid a series of unecessary updates
// that happen when NetworkManager is still figuring out details.
this._updateTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT,
2,
() => {
this._updateStatus();
this._updateTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._updateTimeoutId, '[update] updateStatus');
}
_updateStatus() {
// Update the current active connection. This will connect to the
// NM.SettingUser signal to sync every time someone updates the
// NM_SETTING_ALLOW_DOWNLOADS setting.
this._updateActiveConnection();
let state = this._getState();
if (state != this._state) {
this._state = state;
this.notify('state');
this._updateIcon();
}
}
_updateActiveConnection() {
let currentActiveConnection = this._getActiveConnection();
if (this._activeConnection == currentActiveConnection)
return;
// Disconnect from the previous active connection
if (this._settingChangedSignalId > 0) {
this._activeConnection.disconnect(this._settingChangedSignalId);
this._settingChangedSignalId = 0;
}
this._activeConnection = currentActiveConnection;
// Connect from the current active connection
if (currentActiveConnection)
this._settingChangedSignalId = currentActiveConnection.connect('changed', this._updateStatus.bind(this));
}
_ensureUserSetting(connection) {
let userSetting = connection.get_setting(NM.SettingUser.$gtype);
if (!userSetting) {
userSetting = new NM.SettingUser();
connection.add_setting(userSetting);
}
return userSetting;
}
_getState() {
if (!this._activeConnection)
return State.DISCONNECTED;
let userSetting = this._ensureUserSetting(this._activeConnection);
// We only return true when:
// * Automatic Updates are on
// * A schedule was set
// * Something is being downloaded
let allowDownloadsValue = userSetting.get_data(NM_SETTING_ALLOW_DOWNLOADS);
if (allowDownloadsValue) {
let allowDownloads = (allowDownloadsValue === '1');
if (!allowDownloads)
return State.DISABLED;
} else {
// Guess the default value from the metered state. Only return
// if it's disabled - if it's not, we want to follow the regular
// code paths and fetch the correct state
let connectionSetting = this._activeConnection.get_setting_connection();
if (!connectionSetting)
return State.DISABLED;
let metered = connectionSetting.get_metered();
if (metered == NM.Metered.YES || metered == NM.Metered.GUESS_YES)
return State.DISABLED;
}
// Without the proxy, we can't really know the state
if (!this._proxy)
return State.UNKNOWN;
let scheduleSet = userSetting.get_data(NM_SETTING_TARIFF_ENABLED) === '1';
if (!scheduleSet)
return State.IDLE;
let downloading = this._proxy.ActiveEntryCount > 0;
if (downloading)
return State.DOWNLOADING;
// At this point we're not downloading anything, but something
// might be queued
let downloadsQueued = this._proxy.EntryCount > 0;
if (downloadsQueued)
return State.SCHEDULED;
else
return State.IDLE;
}
_getActiveConnection() {
let activeConnection = this._client.get_primary_connection();
return activeConnection ? activeConnection.get_connection() : null;
}
_updateIcon() {
let state = this._state;
let iconName = stateToIconName(state);
if (iconName) {
let iconFile = Gio.File.new_for_uri(iconName);
this._icon = new Gio.FileIcon({ file: iconFile });
} else {
this._icon = null;
}
this.notify('icon');
}
get state() {
return this._state;
}
get lastNotificationTime() {
let connection = this._getActiveConnection();
if (!connection)
return -1;
let userSetting = connection.get_setting(NM.SettingUser.$gtype);
if (!userSetting)
return -1;
let time = userSetting.get_data(NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME);
return time ? parseInt(time) : -1;
}
set lastNotificationTime(time) {
if (!this._activeConnection)
return;
let userSetting = this._ensureUserSetting(this._activeConnection);
userSetting.set_data(NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME,
'%s'.format(time));
this._activeConnection.commit_changes(true, null);
}
get active() {
return this._active;
}
set active(_active) {
if (this._active == _active)
return;
this._active = _active;
this.notify('active');
}
get icon() {
return this._icon;
}
toggleAutomaticUpdates() {
if (!this._activeConnection)
return;
let userSetting = this._ensureUserSetting(this._activeConnection);
let state = this._getState();
let value;
if (state == State.IDLE ||
state == State.SCHEDULED ||
state == State.DOWNLOADING) {
value = '0';
} else {
value = '1';
}
userSetting.set_data(NM_SETTING_ALLOW_DOWNLOADS, value);
this._activeConnection.commit_changes_async(true, null, (con, res, data) => {
this._activeConnection.commit_changes_finish(res);
this._updateStatus();
});
}
});

View File

@@ -30,14 +30,6 @@ var WeatherClient = class {
return;
}
if (this._permStore.g_name_owner == null) {
// Failed to auto-start, likely because xdg-desktop-portal
// isn't installed; don't restrict access to location service
this._weatherAuthorized = true;
this._updateAutoLocation();
return;
}
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error)
log('Error looking up permission: ' + error.message);

View File

@@ -10,7 +10,7 @@ const Scripting = imports.ui.scripting;
// someone should be able to get an idea of how well the shell is performing
// on a particular system.
var METRICS = {
let METRICS = {
overviewLatencyFirst:
{ description: "Time to first frame after triggering overview, first time",
units: "us" },

View File

@@ -1,8 +1,8 @@
const { Clutter, Gio, Shell } = imports.gi;
const { Clutter, Gio, Gtk, Shell } = imports.gi;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
var METRICS = {
let METRICS = {
timeToDesktop:
{ description: "Time from starting graphical.target to desktop showing",
units: "us" },
@@ -104,10 +104,7 @@ function *run() {
yield Scripting.waitLeisure();
Scripting.scriptEvent('desktopShown');
let interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface'
});
interfaceSettings.set_boolean('enable-animations', false);
Gtk.Settings.get_default().gtk_enable_animations = false;
Scripting.scriptEvent('overviewShowStart');
Main.overview.show();
@@ -203,7 +200,7 @@ function *run() {
yield Scripting.sleep(1000);
interfaceSettings.set_boolean('enable-animations', true);
Gtk.Settings.get_default().gtk_enable_animations = true;
}
let overviewShowStart;

View File

@@ -619,8 +619,9 @@ class WindowSwitcherPopup extends SwitcherPopup.SwitcherPopup {
var WindowCyclerPopup = GObject.registerClass(
class WindowCyclerPopup extends CyclerPopup {
_init() {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
super._init();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell.window-switcher' });
}
_getWindows() {

View File

@@ -14,47 +14,39 @@ const RENAMED_DESKTOP_IDS = {
'epiphany.desktop': 'org.gnome.Epiphany.desktop',
'evolution.desktop': 'org.gnome.Evolution.desktop',
'file-roller.desktop': 'org.gnome.FileRoller.desktop',
'five-or-more.desktop': 'org.gnome.five-or-more.desktop',
'four-in-a-row.desktop': 'org.gnome.Four-in-a-row.desktop',
'gcalctool.desktop': 'org.gnome.Calculator.desktop',
'geary.desktop': 'org.gnome.Geary.desktop',
'gedit.desktop': 'org.gnome.gedit.desktop',
'glchess.desktop': 'org.gnome.Chess.desktop',
'glines.desktop': 'org.gnome.five-or-more.desktop',
'gnect.desktop': 'org.gnome.Four-in-a-row.desktop',
'glchess.desktop': 'gnome-chess.desktop',
'glines.desktop': 'five-or-more.desktop',
'gnect.desktop': 'four-in-a-row.desktop',
'gnibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnobots2.desktop': 'org.gnome.Robots.desktop',
'gnobots2.desktop': 'gnome-robots.desktop',
'gnome-boxes.desktop': 'org.gnome.Boxes.desktop',
'gnome-calculator.desktop': 'org.gnome.Calculator.desktop',
'gnome-chess.desktop': 'org.gnome.Chess.desktop',
'gnome-clocks.desktop': 'org.gnome.clocks.desktop',
'gnome-contacts.desktop': 'org.gnome.Contacts.desktop',
'gnome-documents.desktop': 'org.gnome.Documents.desktop',
'gnome-font-viewer.desktop': 'org.gnome.font-viewer.desktop',
'gnome-klotski.desktop': 'org.gnome.Klotski.desktop',
'gnome-nibbles.desktop': 'org.gnome.Nibbles.desktop',
'gnome-mahjongg.desktop': 'org.gnome.Mahjongg.desktop',
'gnome-mines.desktop': 'org.gnome.Mines.desktop',
'gnome-music.desktop': 'org.gnome.Music.desktop',
'gnome-photos.desktop': 'org.gnome.Photos.desktop',
'gnome-robots.desktop': 'org.gnome.Robots.desktop',
'gnome-screenshot.desktop': 'org.gnome.Screenshot.desktop',
'gnome-software.desktop': 'org.gnome.Software.desktop',
'gnome-terminal.desktop': 'org.gnome.Terminal.desktop',
'gnome-tetravex.desktop': 'org.gnome.Tetravex.desktop',
'gnome-tweaks.desktop': 'org.gnome.tweaks.desktop',
'gnome-weather.desktop': 'org.gnome.Weather.desktop',
'gnomine.desktop': 'org.gnome.Mines.desktop',
'gnotravex.desktop': 'org.gnome.Tetravex.desktop',
'gnotski.desktop': 'org.gnome.Klotski.desktop',
'gtali.desktop': 'org.gnome.Tali.desktop',
'gnomine.desktop': 'gnome-mines.desktop',
'gnotravex.desktop': 'gnome-tetravex.desktop',
'gnotski.desktop': 'gnome-klotski.desktop',
'gtali.desktop': 'tali.desktop',
'iagno.desktop': 'org.gnome.Reversi.desktop',
'nautilus.desktop': 'org.gnome.Nautilus.desktop',
'org.gnome.gnome-2048.desktop': 'org.gnome.TwentyFortyEight.desktop',
'org.gnome.taquin.desktop': 'org.gnome.Taquin.desktop',
'org.gnome.Weather.Application.desktop': 'org.gnome.Weather.desktop',
'polari.desktop': 'org.gnome.Polari.desktop',
'tali.desktop': 'org.gnome.Tali.desktop',
'totem.desktop': 'org.gnome.Totem.desktop',
'evince.desktop': 'org.gnome.Evince.desktop',
};

View File

@@ -24,7 +24,7 @@ var POPUP_ANIMATION_TIME = 0.15;
* placed. The arrow position may be controlled via
* setArrowOrigin(). The arrow side might be temporarily flipped
* depending on the box size and source position to keep the box
* totally inside the monitor workarea if possible.
* totally inside the monitor if possible.
*
*/
var BoxPointer = GObject.registerClass({
@@ -47,6 +47,10 @@ var BoxPointer = GObject.registerClass({
this._border.connect('repaint', this._drawBorder.bind(this));
this.add_actor(this._border);
this.bin.raise(this._border);
this._xOffset = 0;
this._yOffset = 0;
this._xPosition = 0;
this._yPosition = 0;
this._sourceAlignment = 0.5;
this._capturedEventId = 0;
this._muteInput();
@@ -114,23 +118,23 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
this.translation_y = -rise;
this.yOffset = -rise;
break;
case St.Side.BOTTOM:
this.translation_y = rise;
this.yOffset = rise;
break;
case St.Side.LEFT:
this.translation_x = -rise;
this.xOffset = -rise;
break;
case St.Side.RIGHT:
this.translation_x = rise;
this.xOffset = rise;
break;
}
}
Tweener.addTween(this, { opacity: 255,
translation_x: 0,
translation_y: 0,
xOffset: 0,
yOffset: 0,
transition: 'linear',
onComplete: () => {
this._unmuteInput();
@@ -144,8 +148,8 @@ var BoxPointer = GObject.registerClass({
if (!this.visible)
return;
let translationX = 0;
let translationY = 0;
let xOffset = 0;
let yOffset = 0;
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
let fade = (animate & PopupAnimation.FADE);
@@ -154,16 +158,16 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
translationY = rise;
yOffset = rise;
break;
case St.Side.BOTTOM:
translationY = -rise;
yOffset = -rise;
break;
case St.Side.LEFT:
translationX = rise;
xOffset = rise;
break;
case St.Side.RIGHT:
translationX = -rise;
xOffset = -rise;
break;
}
}
@@ -172,15 +176,15 @@ var BoxPointer = GObject.registerClass({
Tweener.removeTweens(this);
Tweener.addTween(this, { opacity: fade ? 0 : 255,
translation_x: translationX,
translation_y: translationY,
xOffset: xOffset,
yOffset: yOffset,
transition: 'linear',
time: animationTime,
onComplete: () => {
this.hide();
this.opacity = 0;
this.translation_x = 0;
this.translation_y = 0;
this.xOffset = 0;
this.yOffset = 0;
if (onComplete)
onComplete();
}
@@ -473,15 +477,11 @@ var BoxPointer = GObject.registerClass({
_reposition() {
let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment;
let monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
this._sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
this._workArea = Main.layoutManager.getWorkAreaForMonitor(monitorIndex);
// Position correctly relative to the sourceActor
let sourceNode = sourceActor.get_theme_node();
let sourceContentBox = sourceNode.get_content_box(sourceActor.get_allocation_box());
let sourceAllocation = this._sourceAllocation;
let sourceAllocation = Shell.util_get_transformed_allocation(sourceActor);
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
@@ -489,7 +489,7 @@ var BoxPointer = GObject.registerClass({
// We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is
// separated from its sourceActor
let workarea = this._workArea;
let monitor = Main.layoutManager.findMonitorForActor(sourceActor);
let themeNode = this.get_theme_node();
let borderWidth = themeNode.get_length('-arrow-border-width');
let arrowBase = themeNode.get_length('-arrow-base');
@@ -539,8 +539,8 @@ var BoxPointer = GObject.registerClass({
case St.Side.BOTTOM:
resX = sourceCenterX - (halfMargin + (natWidth - margin) * alignment);
resX = Math.max(resX, workarea.x + padding);
resX = Math.min(resX, workarea.x + workarea.width - (padding + natWidth));
resX = Math.max(resX, monitor.x + padding);
resX = Math.min(resX, monitor.x + monitor.width - (padding + natWidth));
arrowOrigin = sourceCenterX - resX;
if (arrowOrigin <= (x1 + (borderRadius + halfBase))) {
@@ -558,8 +558,8 @@ var BoxPointer = GObject.registerClass({
case St.Side.RIGHT:
resY = sourceCenterY - (halfMargin + (natHeight - margin) * alignment);
resY = Math.max(resY, workarea.y + padding);
resY = Math.min(resY, workarea.y + workarea.height - (padding + natHeight));
resY = Math.max(resY, monitor.y + padding);
resY = Math.min(resY, monitor.y + monitor.height - (padding + natHeight));
arrowOrigin = sourceCenterY - resY;
if (arrowOrigin <= (y1 + (borderRadius + halfBase))) {
@@ -583,9 +583,9 @@ var BoxPointer = GObject.registerClass({
parent = parent.get_parent();
}
// Actually set the position
this.x = Math.floor(x);
this.y = Math.floor(y);
this._xPosition = Math.floor(x);
this._yPosition = Math.floor(y);
this._shiftActor();
}
// @origin: Coordinate specifying middle of the arrow, along
@@ -608,30 +608,44 @@ var BoxPointer = GObject.registerClass({
}
}
_shiftActor() {
// Since the position of the BoxPointer depends on the allocated size
// of the BoxPointer and the position of the source actor, trying
// to position the BoxPointer via the x/y properties will result in
// allocation loops and warnings. Instead we do the positioning via
// the anchor point, which is independent of allocation, and leave
// x == y == 0.
this.set_anchor_point(-(this._xPosition + this._xOffset),
-(this._yPosition + this._yOffset));
}
_calculateArrowSide(arrowSide) {
let sourceAllocation = this._sourceAllocation;
let sourceAllocation = Shell.util_get_transformed_allocation(this._sourceActor);
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let workarea = this._workArea;
let monitorActor = this.sourceActor;
if (!monitorActor)
monitorActor = this;
let monitor = Main.layoutManager.findMonitorForActor(monitorActor);
switch (arrowSide) {
case St.Side.TOP:
if (sourceAllocation.y2 + boxHeight > workarea.y + workarea.height &&
boxHeight < sourceAllocation.y1 - workarea.y)
if (sourceAllocation.y2 + boxHeight > monitor.y + monitor.height &&
boxHeight < sourceAllocation.y1 - monitor.y)
return St.Side.BOTTOM;
break;
case St.Side.BOTTOM:
if (sourceAllocation.y1 - boxHeight < workarea.y &&
boxHeight < workarea.y + workarea.height - sourceAllocation.y2)
if (sourceAllocation.y1 - boxHeight < monitor.y &&
boxHeight < monitor.y + monitor.height - sourceAllocation.y2)
return St.Side.TOP;
break;
case St.Side.LEFT:
if (sourceAllocation.x2 + boxWidth > workarea.x + workarea.width &&
boxWidth < sourceAllocation.x1 - workarea.x)
if (sourceAllocation.x2 + boxWidth > monitor.x + monitor.width &&
boxWidth < sourceAllocation.x1 - monitor.x)
return St.Side.RIGHT;
break;
case St.Side.RIGHT:
if (sourceAllocation.x1 - boxWidth < workarea.x &&
boxWidth < workarea.x + workarea.width - sourceAllocation.x2)
if (sourceAllocation.x1 - boxWidth < monitor.x &&
boxWidth < monitor.x + monitor.width - sourceAllocation.x2)
return St.Side.LEFT;
break;
}
@@ -653,6 +667,24 @@ var BoxPointer = GObject.registerClass({
}
}
set xOffset(offset) {
this._xOffset = offset;
this._shiftActor();
}
get xOffset() {
return this._xOffset;
}
set yOffset(offset) {
this._yOffset = offset;
this._shiftActor();
}
get yOffset() {
return this._yOffset;
}
updateArrowSide(side) {
this._arrowSide = side;
this._border.queue_repaint();

135
js/ui/components/updates.js Normal file
View File

@@ -0,0 +1,135 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// Copyright (C) 2018 Endless Mobile, Inc.
//
// This is a GNOME Shell component to wrap the interactions over
// D-Bus with the Mogwai system daemon.
//
// Licensed under the GNU General Public License Version 2
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Gio, GLib, Shell } = imports.gi;
const UpdateManager = imports.misc.updateManager;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
var UpdateComponent = class {
constructor() {
this._notification = null;
this._state = UpdateManager.State.UNKNOWN;
this._manager = UpdateManager.getUpdateManager();
this._manager.connect('notify::state', this._updateState.bind(this));
this._updateState();
}
enable() {
}
disable() {
}
_updateState() {
let newState = this._manager.state;
if (this._state == newState)
return;
this._updateNotification(newState);
this._state = newState;
}
_updateNotification(newState) {
// Don't notify when starting up
if (this._manager.state == UpdateManager.State.UNKNOWN)
return;
let alreadySentNotification = this._manager.lastNotificationTime != -1;
let wasDisconnected = this._state == UpdateManager.State.DISCONNECTED;
let wasActive = this._state >= UpdateManager.State.IDLE;
let isActive = newState >= UpdateManager.State.IDLE;
// The criteria to notify about the Automatic Updates setting is:
// 1. If the user was disconnected and connects to a new network; or
// 2. If the user was connected and connects to a network with different status;
if ((wasDisconnected && alreadySentNotification) || (!wasDisconnected && isActive == wasActive))
return;
if (this._notification)
this._notification.destroy();
if (newState == UpdateManager.State.DISCONNECTED)
return;
let source = new MessageTray.SystemNotificationSource();
Main.messageTray.add(source);
// Figure out the title, subtitle and icon
let title, subtitle, iconFile;
if (isActive) {
title = _("Automatic updates on");
subtitle = _("Your connection has unlimited data so automatic updates have been turned on.");
iconFile = UpdateManager.stateToIconName(UpdateManager.State.IDLE);
} else {
title = _("Automatic updates are turned off to save your data");
subtitle = _("You will need to choose which updates to apply when on this connection.");
iconFile = UpdateManager.stateToIconName(UpdateManager.State.DISABLED);
}
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(iconFile) });
// Create the notification.
// The first time we notify the user for a given connection,
// we set the urgency to critical so that we make sure the
// user understands how we may be changing their settings.
// On subsequent notifications for the given connection,
// for instance if the user regularly switches between
// metered and unmetered connections, we set the urgency
// to normal so as not to be too obtrusive.
this._notification = new MessageTray.Notification(source, title, subtitle, { gicon: gicon });
this._notification.setUrgency(alreadySentNotification ?
MessageTray.Urgency.NORMAL : MessageTray.Urgency.CRITICAL);
this._notification.setTransient(false);
this._notification.addAction(_("Close"), () => {
this._notification.destroy();
});
this._notification.addAction(_("Change Settings…"), () => {
// FIXME: this requires the Automatic Updates panel in GNOME
// Settings. Going with the Network panel for now…
let app = Shell.AppSystem.get_default().lookup_app('gnome-network-panel.desktop');
Main.overview.hide();
app.activate();
});
source.notify(this._notification);
this._notification.connect('destroy', () => {
this._notification = null;
});
// Now that we first detected this connection, mark it as such
this._manager.lastNotificationTime = GLib.get_real_time();
}
};
var Component = UpdateComponent;

View File

@@ -584,18 +584,22 @@ var Dash = class Dash {
let firstButton = iconChildren[0].child;
let firstIcon = firstButton._delegate.icon;
// Enforce valid spacings during the size request
let minHeight, natHeight;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
// Enforce the current icon size during the size request
firstIcon.icon.ensure_style();
let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
let [, buttonHeight] = firstButton.get_preferred_height(-1);
let [, currentHeight] = firstIcon.icon.get_size();
firstIcon.icon.set_height(this.iconSize * scaleFactor);
[minHeight, natHeight] = firstButton.get_preferred_height(-1);
firstIcon.icon.set_height(currentHeight);
// Subtract icon padding and box spacing from the available height
availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
availHeight -= iconChildren.length * (natHeight - this.iconSize * scaleFactor) +
(iconChildren.length - 1) * spacing;
let availSize = availHeight / iconChildren.length;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let iconSizes = baseIconSizes.map(s => s * scaleFactor);
let newIconSize = baseIconSizes[0];

View File

@@ -136,12 +136,11 @@ var WorldClocksSection = class WorldClocksSection {
layout.attach(header, 0, 0, 2, 1);
this.actor.label_actor = header;
let localOffset = GLib.DateTime.new_now_local().get_utc_offset();
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i].location;
let name = l.get_city_name() || l.get_name();
let name = l.get_level() == GWeather.LocationLevel.NAMED_TIMEZONE ? l.get_name()
: l.get_city_name();
let label = new St.Label({ style_class: 'world-clocks-city',
text: name,
x_align: Clutter.ActorAlign.START,
@@ -150,8 +149,7 @@ var WorldClocksSection = class WorldClocksSection {
let time = new St.Label({ style_class: 'world-clocks-time' });
let otherOffset = this._getTimeAtLocation(l).get_utc_offset();
let offset = (otherOffset - localOffset) / GLib.TIME_SPAN_HOUR;
let offset = l.get_timezone().get_offset() / 60.;
let fmt = (Math.trunc(offset) == offset) ? '%s%.0f' : '%s%.1f';
let prefix = (offset >= 0) ? '+' : '-';
let tz = new St.Label({ style_class: 'world-clocks-timezone',
@@ -184,15 +182,11 @@ var WorldClocksSection = class WorldClocksSection {
}
}
_getTimeAtLocation(location) {
let tz = GLib.TimeZone.new(location.get_timezone().get_tzid());
return GLib.DateTime.new_now(tz);
}
_updateLabels() {
for (let i = 0; i < this._locations.length; i++) {
let l = this._locations[i];
let now = this._getTimeAtLocation(l.location);
let tz = GLib.TimeZone.new(l.location.get_timezone().get_tzid());
let now = GLib.DateTime.new_now(tz);
l.actor.text = Util.formatTime(now, { timeOnly: true });
}
}

View File

@@ -104,7 +104,6 @@ class BaseIcon extends St.Bin {
}
vfunc_style_changed() {
super.vfunc_style_changed();
let node = this.get_theme_node();
let size;

View File

@@ -252,7 +252,7 @@ var LayoutManager = GObject.registerClass({
// A dummy actor that tracks the mouse or text cursor, based on the
// position and size set in setDummyCursorGeometry.
this.dummyCursor = new St.Widget({ width: 0, height: 0, opacity: 0 });
this.dummyCursor = new St.Widget({ width: 0, height: 0, visible: false });
this.uiGroup.add_actor(this.dummyCursor);
global.stage.remove_actor(global.top_window_group);

View File

@@ -18,6 +18,9 @@ var NO_CHANGE = 0.0;
var POINTER_REST_TIME = 1000; // milliseconds
// Settings
const APPLICATIONS_SCHEMA = 'org.gnome.desktop.a11y.applications';
const SHOW_KEY = 'screen-magnifier-enabled';
const MAGNIFIER_SCHEMA = 'org.gnome.desktop.a11y.magnifier';
const SCREEN_POSITION_KEY = 'screen-position';
const MAG_FACTOR_KEY = 'mag-factor';
@@ -53,19 +56,20 @@ var MouseSpriteContent = GObject.registerClass({
vfunc_get_preferred_size() {
if (!this._texture)
return [false, 0, 0];
return [0, 0];
return [true, this._texture.get_width(), this._texture.get_height()];
return [this._texture.get_width(), this._texture.get_height()];
}
vfunc_paint_content(actor, node) {
if (!this._texture)
return;
let color = Clutter.Color.get_static(Clutter.StaticColor.WHITE);
let [minFilter, magFilter] = actor.get_content_scaling_filters();
let color = new Clutter.Color();
let textureNode = new Clutter.TextureNode(this._texture,
color, minFilter, magFilter);
color,
Clutter.ScalingFilter.NEAREST,
Clutter.ScalingFilter.NEAREST);
textureNode.set_name('MouseSpriteContent');
node.add_child(textureNode);
@@ -80,14 +84,8 @@ var MouseSpriteContent = GObject.registerClass({
if (this._texture == coglTexture)
return;
let oldTexture = this._texture;
this._texture = coglTexture;
this.invalidate();
if (!oldTexture || !coglTexture ||
oldTexture.get_width() != coglTexture.get_width() ||
oldTexture.get_height() != coglTexture.get_height())
this.invalidate_size();
}
});
@@ -102,6 +100,7 @@ var Magnifier = class Magnifier {
this._mouseSprite = new Clutter.Actor({ request_mode: Clutter.RequestMode.CONTENT_SIZE });
this._mouseSprite.content = new MouseSpriteContent();
this._updateSpriteTexture();
this._cursorRoot = new Clutter.Actor();
this._cursorRoot.add_actor(this._mouseSprite);
@@ -114,16 +113,14 @@ var Magnifier = class Magnifier {
let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
this._zoomRegions.push(aZoomRegion);
this._settingsInit(aZoomRegion);
let showAtLaunch = this._settingsInit(aZoomRegion);
aZoomRegion.scrollContentsTo(this.xMouse, this.yMouse);
St.Settings.get().connect('notify::magnifier-active', () => {
this.setActive(St.Settings.get().magnifier_active);
});
cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this));
// Export to dbus.
magDBusService = new MagnifierDBus.ShellMagnifier();
this.setActive(St.Settings.get().magnifier_active);
this.setActive(showAtLaunch);
}
/**
@@ -156,15 +153,9 @@ var Magnifier = class Magnifier {
if (isActive != activate) {
if (activate) {
this._updateMouseSprite();
this._cursorSpriteChangedId =
this._cursorTracker.connect('cursor-changed',
this._updateMouseSprite.bind(this));
Meta.disable_unredirect_for_display(global.display);
this.startTrackingMouse();
} else {
this._cursorTracker.disconnect(this._cursorSpriteChangedId);
this._mouseSprite.content.texture = null;
Meta.enable_unredirect_for_display(global.display);
this.stopTrackingMouse();
}
@@ -502,8 +493,13 @@ var Magnifier = class Magnifier {
}
_settingsInit(zoomRegion) {
this._appSettings = new Gio.Settings({ schema_id: APPLICATIONS_SCHEMA });
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
this._appSettings.connect('changed::' + SHOW_KEY, () => {
this.setActive(this._appSettings.get_boolean(SHOW_KEY));
});
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
this._updateScreenPosition.bind(this));
this._settings.connect('changed::' + MAG_FACTOR_KEY,
@@ -610,6 +606,8 @@ var Magnifier = class Magnifier {
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
this.addCrosshairs();
this.setCrosshairsVisible(showCrosshairs);
return this._appSettings.get_boolean(SHOW_KEY);
}
_updateScreenPosition() {
@@ -756,41 +754,13 @@ var ZoomRegion = class ZoomRegion {
this._pointerIdleMonitor = Meta.IdleMonitor.get_for_device(Meta.VIRTUAL_CORE_POINTER_ID);
this._scrollContentsTimerId = 0;
}
_connectSignals() {
if (this._signalConnections)
return;
this._signalConnections = [];
let id = Main.layoutManager.connect('monitors-changed',
this._monitorsChanged.bind(this));
this._signalConnections.push([Main.layoutManager, id]);
id = this._focusCaretTracker.connect('caret-moved', this._updateCaret.bind(this));
this._signalConnections.push([this._focusCaretTracker, id]);
id = this._focusCaretTracker.connect('focus-changed', this._updateFocus.bind(this));
this._signalConnections.push([this._focusCaretTracker, id]);
}
_disconnectSignals() {
for (let [obj, id] of this._signalConnections)
obj.disconnect(id);
delete this._signalConnections;
}
_updateScreenPosition() {
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
this._setViewPort({
x: this._viewPortX,
y: this._viewPortY,
width: this._viewPortWidth,
height: this._viewPortHeight
});
else
this.setScreenPosition(this._screenPosition);
Main.layoutManager.connect('monitors-changed',
this._monitorsChanged.bind(this));
this._focusCaretTracker.connect('caret-moved',
this._updateCaret.bind(this));
this._focusCaretTracker.connect('focus-changed',
this._updateFocus.bind(this));
}
_updateFocus(caller, event) {
@@ -838,13 +808,10 @@ var ZoomRegion = class ZoomRegion {
this._createActors();
if (this._isMouseOverRegion())
this._magnifier.hideSystemCursor();
this._updateScreenPosition();
this._updateMagViewGeometry();
this._updateCloneGeometry();
this._updateMousePosition();
this._connectSignals();
} else {
this._disconnectSignals();
this._destroyActors();
}
@@ -1594,8 +1561,18 @@ var ZoomRegion = class ZoomRegion {
}
_monitorsChanged() {
if (!this.isActive())
return;
this._background.set_size(global.screen_width, global.screen_height);
this._updateScreenPosition();
if (this._screenPosition == GDesktopEnums.MagnifierScreenPosition.NONE)
this._setViewPort({ x: this._viewPortX,
y: this._viewPortY,
width: this._viewPortWidth,
height: this._viewPortHeight });
else
this.setScreenPosition(this._screenPosition);
}
};

View File

@@ -211,6 +211,13 @@ function _initializeUI() {
_startDate = new Date();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
ExtensionDownloader.init();
ExtensionSystem.init();
@@ -232,13 +239,6 @@ function _initializeUI() {
Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
}
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
Scripting.runPerfScript(module, perfOutput);
}
});
}

View File

@@ -95,6 +95,28 @@ var OsdMonitorLabeler = class {
this._reset();
for (let id in params) {
let monitor = this._monitorManager.get_monitor_for_output(id);
if (monitor == -1)
continue;
this._monitorLabels.get(monitor).push(params[id].deep_unpack());
}
// In mirrored display setups, more than one physical outputs
// might be showing the same logical monitor. In that case, we
// join each output's labels on the same OSD widget.
for (let [monitor, labels] of this._monitorLabels.entries()) {
labels.sort();
this._osdLabels.push(new OsdMonitorLabel(monitor, labels.join(' ')));
}
}
show2(client, params) {
if (!this._trackClient(client))
return;
this._reset();
for (let connector in params) {
let monitor = this._monitorManager.get_monitor_for_connector(connector);
if (monitor == -1)

View File

@@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Atk, Clutter, Gio, GLib, GObject, Gtk, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Mainloop = imports.mainloop;
@@ -201,6 +201,7 @@ var AppMenuButton = GObject.registerClass({
this._startingApps = [];
this._menuManager = panel.menuManager;
this._gtkSettings = Gtk.Settings.get_default();
this._targetApp = null;
this._busyNotifyId = 0;
@@ -773,10 +774,17 @@ class AggregateMenu extends PanelMenu.Button {
this._nightLight = new imports.ui.status.nightLight.Indicator();
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
if (Main.sessionMode.components.includes('updates'))
this._automaticUpdates = new imports.ui.status.automaticUpdates.Indicator();
else
this._automaticUpdates = null;
this._indicators.add_child(this._thunderbolt.indicators);
this._indicators.add_child(this._screencast.indicators);
this._indicators.add_child(this._location.indicators);
this._indicators.add_child(this._nightLight.indicators);
if (this._automaticUpdates)
this._indicators.add_child(this._automaticUpdates.indicators);
if (this._network) {
this._indicators.add_child(this._network.indicators);
}
@@ -795,6 +803,8 @@ class AggregateMenu extends PanelMenu.Button {
if (this._network) {
this.menu.addMenuItem(this._network.menu);
}
if (this._automaticUpdates)
this.menu.addMenuItem(this._automaticUpdates.menu);
if (this._bluetooth) {
this.menu.addMenuItem(this._bluetooth.menu);
}
@@ -808,7 +818,6 @@ class AggregateMenu extends PanelMenu.Button {
menuLayout.addSizeChild(this._location.menu.actor);
menuLayout.addSizeChild(this._rfkill.menu.actor);
menuLayout.addSizeChild(this._power.menu.actor);
menuLayout.addSizeChild(this._system.buttonGroup);
}
});

View File

@@ -810,8 +810,16 @@ var ScreenShield = class {
this._maybeCancelDialog();
if (this._longLightbox.actor.visible) {
// We're in the process of showing.
if (this._longLightbox.actor.visible ||
this._isActive) {
// We're either shown and active, or in the process of
// showing.
// The latter is a very unlikely condition (it requires
// idle-delay < 20), but in any case we have nothing
// to do at this point: either isActive is true, or
// it will soon be.
// isActive can also be true if the lightbox is hidden,
// in case the shield is down and the user hasn't unlocked yet
return;
}

View File

@@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, Gtk, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const GrabHelper = imports.ui.grabHelper;
@@ -227,6 +227,8 @@ var SelectArea = class {
this._lastY = 0;
this._result = null;
this._initRubberbandColors();
this._group = new St.Widget({ visible: false,
reactive: true,
x: 0,
@@ -246,10 +248,10 @@ var SelectArea = class {
coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint);
this._rubberband = new St.Widget({
style_class: 'select-area-rubberband',
visible: false
});
this._rubberband = new Clutter.Rectangle({ color: this._background,
has_border: true,
border_width: 1,
border_color: this._border });
this._group.add_actor(this._rubberband);
}
@@ -263,6 +265,25 @@ var SelectArea = class {
this._group.visible = true;
}
_initRubberbandColors() {
function colorFromRGBA(rgba) {
return new Clutter.Color({ red: rgba.red * 255,
green: rgba.green * 255,
blue: rgba.blue * 255,
alpha: rgba.alpha * 255 });
}
let path = new Gtk.WidgetPath();
path.append_type(Gtk.IconView);
let context = new Gtk.StyleContext();
context.set_path(path);
context.add_class('rubberband');
this._background = colorFromRGBA(context.get_background_color(Gtk.StateFlags.NORMAL));
this._border = colorFromRGBA(context.get_border_color(Gtk.StateFlags.NORMAL));
}
_getGeometry() {
return { x: Math.min(this._startX, this._lastX),
y: Math.min(this._startY, this._lastY),
@@ -281,7 +302,6 @@ var SelectArea = class {
this._rubberband.set_position(geometry.x, geometry.y);
this._rubberband.set_size(geometry.width, geometry.height);
this._rubberband.show();
return Clutter.EVENT_PROPAGATE;
}

View File

@@ -37,13 +37,16 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
* 'yield Scripting.sleep(500);'
*/
function sleep(milliseconds) {
return new Promise(resolve => {
let id = Mainloop.timeout_add(milliseconds, () => {
resolve();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] sleep');
let cb;
let id = Mainloop.timeout_add(milliseconds, () => {
if (cb)
cb();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(id, '[gnome-shell] sleep');
return callback => { cb = callback; };
}
/**
@@ -54,9 +57,14 @@ function sleep(milliseconds) {
* 'yield Scripting.waitLeisure();'
*/
function waitLeisure() {
return new Promise(resolve => {
global.run_at_leisure(resolve);
let cb;
global.run_at_leisure(() => {
if (cb)
cb();
});
return callback => { cb = callback; };
}
const PerfHelperIface = loadInterfaceXML('org.gnome.Shell.PerfHelper');
@@ -74,16 +82,25 @@ function _getPerfHelper() {
}
function _callRemote(obj, method, ...args) {
return new Promise((resolve, reject) => {
args.push((result, excp) => {
if (excp)
reject(excp);
else
resolve();
});
let cb;
let errcb;
method.apply(obj, args);
args.push((result, excp) => {
if (excp) {
if (errcb)
errcb(excp);
} else {
if (cb)
cb();
}
});
method.apply(obj, args);
return (callback, error_callback) => {
cb = callback;
errcb = error_callback;
};
}
/**
@@ -175,6 +192,27 @@ function collectStatistics() {
Shell.PerfLog.get_default().collect_statistics();
}
function _step(g, finish, onError) {
try {
let waitFunction = g.next();
waitFunction(() => {
_step(g, finish, onError);
},
err => {
if (onError)
onError(err);
});
} catch (err) {
if (err instanceof StopIteration) {
if (finish)
finish();
} else {
if (onError)
onError(err);
}
}
}
function _collect(scriptModule, outputFile) {
let eventHandlers = {};
@@ -310,23 +348,23 @@ function _collect(scriptModule, outputFile) {
* After running the script and collecting statistics from the
* event log, GNOME Shell will exit.
**/
async function runPerfScript(scriptModule, outputFile) {
function runPerfScript(scriptModule, outputFile) {
Shell.PerfLog.get_default().set_enabled(true);
for (let step of scriptModule.run()) {
try {
await step;
} catch (err) {
log(`Script failed: ${err}\n${err.stack}`);
Meta.exit(Meta.ExitCode.ERROR);
}
}
let g = scriptModule.run();
try {
_collect(scriptModule, outputFile);
} catch (err) {
log(`Script failed: ${err}\n${err.stack}`);
Meta.exit(Meta.ExitCode.ERROR);
}
Meta.exit(Meta.ExitCode.SUCCESS);
_step(g,
() => {
try {
_collect(scriptModule, outputFile);
} catch (err) {
log("Script failed: " + err + "\n" + err.stack);
Meta.exit(Meta.ExitCode.ERROR);
}
Meta.exit(Meta.ExitCode.SUCCESS);
},
err => {
log("Script failed: " + err + "\n" + err.stack);
Meta.exit(Meta.ExitCode.ERROR);
});
}

View File

@@ -92,9 +92,11 @@ const _modes = {
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: Config.HAVE_NETWORKMANAGER ?
['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'] :
'keyring', 'autorunManager', 'automountManager',
'updates'] :
['polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'],
'keyring', 'autorunManager', 'automountManager',
'updates'],
panel: {
left: ['activities', 'appMenu'],

View File

@@ -79,17 +79,14 @@ var GnomeShell = class {
for (let param in params)
params[param] = params[param].deep_unpack();
let { connector,
let { monitor: monitorIndex,
label,
level,
max_level: maxLevel,
icon: serializedIcon } = params;
let monitorIndex = -1;
if (connector) {
let monitorManager = Meta.MonitorManager.get();
monitorIndex = monitorManager.get_monitor_for_connector(connector);
}
if (monitorIndex === undefined)
monitorIndex = -1;
let icon = null;
if (serializedIcon)
@@ -206,12 +203,18 @@ var GnomeShell = class {
this._grabbers.delete(name);
}
ShowMonitorLabels2Async(params, invocation) {
ShowMonitorLabelsAsync(params, invocation) {
let sender = invocation.get_sender();
let [dict] = params;
Main.osdMonitorLabeler.show(sender, dict);
}
ShowMonitorLabels2Async(params, invocation) {
let sender = invocation.get_sender();
let [dict] = params;
Main.osdMonitorLabeler.show2(sender, dict);
}
HideMonitorLabelsAsync(params, invocation) {
let sender = invocation.get_sender();
Main.osdMonitorLabeler.hide(sender);

View File

@@ -0,0 +1,144 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
//
// Copyright (C) 2018 Endless Mobile, Inc.
//
// This is a GNOME Shell component to wrap the interactions over
// D-Bus with the Mogwai system daemon.
//
// Licensed under the GNU General Public License Version 2
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
const { Gio, GLib, Shell, St } = imports.gi;
const UpdateManager = imports.misc.updateManager;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const NM_SETTING_AUTOMATIC_UPDATES_NOTIFICATION_TIME = "connection.automatic-updates-notification-time";
const NM_SETTING_ALLOW_DOWNLOADS = 'connection.allow-downloads';
const NM_SETTING_TARIFF_ENABLED = "connection.tariff-enabled";
const SchedulerInterface = '\
<node> \
<interface name="com.endlessm.DownloadManager1.Scheduler"> \
<property name="ActiveEntryCount" type="u" access="read" /> \
<property name="EntryCount" type="u" access="read" /> \
</interface> \
</node>';
const SchedulerProxy = Gio.DBusProxy.makeProxyWrapper(SchedulerInterface);
var Indicator = class extends PanelMenu.SystemIndicator {
constructor() {
super();
this._indicator = this._addIndicator();
this._indicator.visible = false;
this._item = new PopupMenu.PopupSubMenuMenuItem("", true);
this._toggleItem = this._item.menu.addAction("", this._toggleAutomaticUpdates.bind(this));
this._item.menu.addAction(_("Updates Queue"), () => {
let params = new GLib.Variant('(sava{sv})', [ 'set-mode', [ new GLib.Variant('s', 'updates') ], {} ]);
Gio.DBus.session.call('org.gnome.Software',
'/org/gnome/Software',
'org.gtk.Actions',
'Activate',
params,
null,
Gio.DBusCallFlags.NONE,
5000,
null,
(conn, result) => {
try {
conn.call_finish(result);
} catch (e) {
logError(e, 'Failed to start gnome-software');
}
});
});
this._item.menu.addSettingsAction(_("Set a Schedule"), 'gnome-updates-panel.desktop');
this.menu.addMenuItem(this._item);
this._manager = UpdateManager.getUpdateManager();
this._manager.connect('notify::state', this._updateState.bind(this));
this._updateState();
}
_updateState() {
this._updateStatus();
}
_sessionUpdated() {
let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
this.menu.setSensitive(sensitive);
}
_updateStatus() {
// Toggle item name
this._updateItem();
// Icons
let icon = this._getIcon()
this._item.icon.gicon = icon;
this._indicator.gicon = icon;
// Only show the Automatic Updates icon at the bottom bar when it is
// both enabled, and there are updates being downloaded or installed.
this._updateVisibility();
// The status label
this._item.label.text = _("Automatic Updates");
}
_updateItem() {
let state = this._manager.state;
if (state == UpdateManager.State.DISABLED)
this._toggleItem.label.text = _("Turn On");
else
this._toggleItem.label.text = _("Turn Off");
}
_toggleAutomaticUpdates() {
this._manager.toggleAutomaticUpdates();
}
_getIcon() {
let state = this._manager.state;
let iconName = UpdateManager.stateToIconName(state);
if (!iconName)
return null;
let iconFile = Gio.File.new_for_uri(iconName);
let gicon = new Gio.FileIcon({ file: iconFile });
return gicon;
}
_updateVisibility() {
let state = this._manager.state;
this._item.actor.visible = (state != UpdateManager.State.DISCONNECTED);
this._indicator.visible = (state == UpdateManager.State.DOWNLOADING);
}
};

View File

@@ -1673,11 +1673,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
_readDevices() {
let devices = this._client.get_devices() || [ ];
for (let i = 0; i < devices.length; ++i) {
try {
this._deviceAdded(this._client, devices[i], true);
} catch (e) {
log(`Failed to add device ${devices[i]}: ${e}`);
}
this._deviceAdded(this._client, devices[i], true);
}
this._syncDeviceNames();
}

View File

@@ -236,7 +236,6 @@ var Indicator = class extends PanelMenu.SystemIndicator {
item = new PopupMenu.PopupBaseMenuItem({ reactive: false,
can_focus: false });
this.buttonGroup = item.actor;
let app = this._settingsApp = Shell.AppSystem.get_default().lookup_app(
'gnome-control-center.desktop'

View File

@@ -456,28 +456,13 @@ var TilePreview = class {
};
var TouchpadWorkspaceSwitchAction = class {
constructor(actor, allowedModes) {
this._allowedModes = allowedModes;
constructor(actor) {
this._dx = 0;
this._dy = 0;
this._enabled = true;
actor.connect('captured-event', this._handleEvent.bind(this));
this._touchpadSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.peripherals.touchpad'});
}
get enabled() {
return this._enabled;
}
set enabled(enabled) {
if (this._enabled == enabled)
return;
this._enabled = enabled;
if (!enabled)
this.emit('cancel');
}
_checkActivated() {
let dir;
@@ -497,16 +482,15 @@ var TouchpadWorkspaceSwitchAction = class {
}
_handleEvent(actor, event) {
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
if (event.type() != Clutter.EventType.TOUCHPAD_SWIPE)
return Clutter.EVENT_PROPAGATE;
if (event.get_touchpad_gesture_finger_count() != 4)
return Clutter.EVENT_PROPAGATE;
if ((this._allowedModes & Main.actionMode) == 0)
return Clutter.EVENT_PROPAGATE;
if (!this._enabled)
if ((allowedModes & Main.actionMode) == 0)
return Clutter.EVENT_PROPAGATE;
if (event.get_gesture_phase() == Clutter.TouchpadGesturePhase.UPDATE) {
@@ -539,11 +523,10 @@ var WorkspaceSwitchAction = GObject.registerClass({
'motion': { param_types: [GObject.TYPE_DOUBLE, GObject.TYPE_DOUBLE] },
'cancel': { param_types: [] }},
}, class WorkspaceSwitchAction extends Clutter.SwipeAction {
_init(allowedModes) {
_init() {
super._init();
this.set_n_touch_points(4);
this._swept = false;
this._allowedModes = allowedModes;
global.display.connect('grab-op-begin', () => {
this.cancel();
@@ -551,12 +534,14 @@ var WorkspaceSwitchAction = GObject.registerClass({
}
vfunc_gesture_prepare(actor) {
let allowedModes = Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW;
this._swept = false;
if (!super.vfunc_gesture_prepare(actor))
return false;
return (this._allowedModes & Main.actionMode);
return (allowedModes & Main.actionMode);
}
vfunc_gesture_progress(actor) {
@@ -1058,15 +1043,14 @@ var WindowManager = class {
global.workspace_manager.override_workspace_layout(Meta.DisplayCorner.TOPLEFT,
false, -1, 1);
let allowedModes = Shell.ActionMode.NORMAL;
let gesture = new WorkspaceSwitchAction(allowedModes);
let gesture = new WorkspaceSwitchAction();
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
global.stage.add_action(gesture);
// This is not a normal Clutter.GestureAction, doesn't need add_action()
gesture = new TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
gesture = new TouchpadWorkspaceSwitchAction(global.stage);
gesture.connect('motion', this._switchWorkspaceMotion.bind(this));
gesture.connect('activated', this._actionSwitchWorkspace.bind(this));
gesture.connect('cancel', this._switchWorkspaceCancel.bind(this));
@@ -1218,10 +1202,6 @@ var WindowManager = class {
// Same for OR windows
if (window.is_override_redirect())
return;
// Sticky windows don't need moving, in fact moving would
// unstick them
if (window.on_all_workspaces)
return;
// Windows on workspaces below pos don't need moving
let index = window.get_workspace().index();
if (index < pos)

View File

@@ -1,11 +1,10 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GObject, Meta, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
const WindowManager = imports.ui.windowManager;
const Workspace = imports.ui.workspace;
var WORKSPACE_SWITCH_TIME = 0.25;
@@ -83,7 +82,6 @@ var WorkspacesView = class extends WorkspacesViewBase {
this._animating = false; // tweening
this._scrolling = false; // swipe-scrolling
this._gestureActive = false; // touch(pad) gestures
this._animatingScroll = false; // programatically updating the adjustment
let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
@@ -213,7 +211,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
for (let w = 0; w < this._workspaces.length; w++) {
let workspace = this._workspaces[w];
if (this._animating || this._scrolling || this._gestureActive) {
if (this._animating || this._scrolling) {
workspace.actor.show();
} else {
if (this._inDrag)
@@ -225,7 +223,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
}
_updateScrollAdjustment(index) {
if (this._scrolling || this._gestureActive)
if (this._scrolling)
return;
this._animatingScroll = true;
@@ -302,18 +300,6 @@ var WorkspacesView = class extends WorkspacesViewBase {
this._updateVisibility();
}
startTouchGesture() {
this._gestureActive = true;
}
endTouchGesture() {
this._gestureActive = false;
// Make sure title captions etc are shown as necessary
this._scrollToActive();
this._updateVisibility();
}
// sync the workspaces' positions to the value of the scroll adjustment
// and change the active workspace if appropriate
_onScroll(adj) {
@@ -324,7 +310,7 @@ var WorkspacesView = class extends WorkspacesViewBase {
let active = workspaceManager.get_active_workspace_index();
let current = Math.round(adj.value);
if (active != current && !this._gestureActive) {
if (active != current) {
if (!this._workspaces[current]) {
// The current workspace was destroyed. This could happen
// when you are on the last empty workspace, and consolidate
@@ -405,12 +391,6 @@ var ExtraWorkspaceView = class extends WorkspacesViewBase {
endSwipeScroll() {
}
startTouchGesture() {
}
endTouchGesture() {
}
};
var DelegateFocusNavigator = GObject.registerClass(
@@ -450,37 +430,23 @@ var WorkspacesDisplay = class {
return false;
}
this._startSwipeScroll();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
return true;
});
panAction.connect('gesture-cancel', () => {
clickAction.release();
this._endSwipeScroll();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll();
});
panAction.connect('gesture-end', () => {
clickAction.release();
this._endSwipeScroll();
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll();
});
Main.overview.addAction(panAction);
this.actor.bind_property('mapped', panAction, 'enabled', GObject.BindingFlags.SYNC_CREATE);
let allowedModes = Shell.ActionMode.OVERVIEW;
let switchGesture = new WindowManager.WorkspaceSwitchAction(allowedModes);
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
Main.overview.addAction(switchGesture);
this.actor.bind_property('mapped', switchGesture, 'enabled', GObject.BindingFlags.SYNC_CREATE);
switchGesture = new WindowManager.TouchpadWorkspaceSwitchAction(global.stage, allowedModes);
switchGesture.connect('motion', this._onSwitchWorkspaceMotion.bind(this));
switchGesture.connect('activated', this._onSwitchWorkspaceActivated.bind(this));
switchGesture.connect('cancel', this._endTouchGesture.bind(this));
this.actor.connect('notify::mapped', () => {
switchGesture.enabled = this.actor.mapped;
});
switchGesture.enabled = this.actor.mapped;
this._primaryIndex = Main.layoutManager.primaryIndex;
this._workspacesViews = [];
@@ -508,47 +474,6 @@ var WorkspacesDisplay = class {
return false;
}
_startSwipeScroll() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startSwipeScroll();
}
_endSwipeScroll() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endSwipeScroll();
}
_startTouchGesture() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].startTouchGesture();
}
_endTouchGesture() {
for (let i = 0; i < this._workspacesViews.length; i++)
this._workspacesViews[i].endTouchGesture();
}
_onSwitchWorkspaceMotion(action, xRel, yRel) {
// We don't have a way to hook into start of touchpad actions,
// luckily this is safe to call repeatedly.
this._startTouchGesture();
let workspaceManager = global.workspace_manager;
let active = workspaceManager.get_active_workspace_index();
let adjustment = this._scrollAdjustment;
adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size;
}
_onSwitchWorkspaceActivated(action, direction) {
let workspaceManager = global.workspace_manager;
let activeWorkspace = workspaceManager.get_active_workspace();
let newWs = activeWorkspace.get_neighbor(direction);
if (newWs != activeWorkspace)
newWs.activate(global.get_current_time());
this._endTouchGesture();
}
navigateFocus(from, direction) {
return this._getPrimaryView().actor.navigate_focus(from, direction, false);
}

View File

@@ -52,6 +52,7 @@ js/ui/search.js
js/ui/shellEntry.js
js/ui/shellMountOperation.js
js/ui/status/accessibility.js
js/ui/status/automaticUpdates.js
js/ui/status/bluetooth.js
js/ui/status/brightness.js
js/ui/status/keyboard.js

1038
po/ar.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

143
po/eo.po
View File

@@ -12,9 +12,9 @@ msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2019-03-24 17:37+0000\n"
"PO-Revision-Date: 2019-03-31 00:14+0100\n"
"Last-Translator: Carmen Bianca Bakker <carmen@carmenbianca.eu>\n"
"POT-Creation-Date: 2019-02-21 18:43+0000\n"
"PO-Revision-Date: 2019-02-22 13:19+0100\n"
"Last-Translator: Carmen Bianca BAKKER <carmen@carmenbianca.eu>\n"
"Language-Team: Esperanto <gnome-eo-list@gnome.org>\n"
"Language: eo\n"
"MIME-Version: 1.0\n"
@@ -185,8 +185,8 @@ msgstr "Klavkombino por malfermi la “Montri aplikaĵojn”-vidon"
msgid ""
"Keybinding to open the “Show Applications” view of the Activities Overview."
msgstr ""
"Klavkombino por malfermi la “Montri aplikaĵojn” vidon de la Aktivecoj-"
"Superrigardo."
"Klavkombino por malfermi la “Montri aplikaĵojn” vidon de la aktivecoj "
"superrigardo."
#: data/org.gnome.shell.gschema.xml.in:124
msgid "Keybinding to open the overview"
@@ -194,7 +194,7 @@ msgstr "Klavkombino por malfermi la superrigardon"
#: data/org.gnome.shell.gschema.xml.in:125
msgid "Keybinding to open the Activities Overview."
msgstr "Klavkombino por malfermi la Aktivecoj-Superrigardon."
msgstr "Klavkombino por malfermi la aktivecoj superrigardon."
#: data/org.gnome.shell.gschema.xml.in:131
msgid "Keybinding to toggle the visibility of the notification list"
@@ -334,6 +334,11 @@ msgstr "En musa reĝimo, prokrasti ŝanĝi fokuson ĝis la musmontrilo haltas"
msgid "Network Login"
msgstr "Reta saluto"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: data/org.gnome.Shell.PortalHelper.desktop.in.in:9
msgid "network-workgroup"
msgstr "network-workgroup"
#: js/extensionPrefs/main.js:116
msgid "Somethings gone wrong"
msgstr "Io fiaskis"
@@ -414,7 +419,7 @@ msgstr "Ĉu ne en listo?"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:884
#: js/gdm/loginDialog.js:880
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(ekzemple, uzanto aŭ %s)"
@@ -422,12 +427,12 @@ msgstr "(ekzemple, uzanto aŭ %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:889 js/ui/components/networkAgent.js:243
#: js/gdm/loginDialog.js:885 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281
msgid "Username: "
msgstr "Uzantonomo: "
#: js/gdm/loginDialog.js:1227
#: js/gdm/loginDialog.js:1223
msgid "Login Window"
msgstr "Salutfenestro"
@@ -988,7 +993,7 @@ msgstr "Portebla larĝkapacita retopasvorto"
msgid "A password is required to connect to “%s”."
msgstr "Pasvorto estas bezonata por konekti al “%s”."
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1664
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1665
msgid "Network Manager"
msgstr "Retadministrilo"
@@ -1235,26 +1240,26 @@ msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Ĉu elŝuti kaj instali “%s” de extensions.gnome.org?"
#. Translators: %s is an application name like "Settings"
#: js/ui/inhibitShortcutsDialog.js:78
#: js/ui/inhibitShortcutsDialog.js:50
#, javascript-format
msgid "%s wants to inhibit shortcuts"
msgstr "%s volas malebligi klavkombinojn"
#: js/ui/inhibitShortcutsDialog.js:79
#: js/ui/inhibitShortcutsDialog.js:51
msgid "Application wants to inhibit shortcuts"
msgstr "Aplikaĵo volas malebligi klavkombinojn"
#. Translators: %s is a keyboard shortcut like "Super+x"
#: js/ui/inhibitShortcutsDialog.js:88
#: js/ui/inhibitShortcutsDialog.js:60
#, javascript-format
msgid "You can restore shortcuts by pressing %s."
msgstr "Vi povas restaŭri klavkombinojn per premi %s."
#: js/ui/inhibitShortcutsDialog.js:93
#: js/ui/inhibitShortcutsDialog.js:65
msgid "Deny"
msgstr "Rifuzi"
#: js/ui/inhibitShortcutsDialog.js:100
#: js/ui/inhibitShortcutsDialog.js:71
msgid "Allow"
msgstr "Akcepti"
@@ -1305,13 +1310,13 @@ msgid "Leave On"
msgstr "Lasi ŝaltita"
#: js/ui/kbdA11yDialog.js:57 js/ui/status/bluetooth.js:133
#: js/ui/status/network.js:1263
#: js/ui/status/network.js:1264
msgid "Turn On"
msgstr "Ŝalti"
#: js/ui/kbdA11yDialog.js:65 js/ui/status/bluetooth.js:133
#: js/ui/status/network.js:128 js/ui/status/network.js:310
#: js/ui/status/network.js:1263 js/ui/status/network.js:1375
#: js/ui/status/network.js:1264 js/ui/status/network.js:1376
#: js/ui/status/nightLight.js:39 js/ui/status/rfkill.js:79
#: js/ui/status/rfkill.js:106
msgid "Turn Off"
@@ -1321,59 +1326,59 @@ msgstr "Malŝalti"
msgid "Leave Off"
msgstr "Lasi malŝaltita"
#: js/ui/keyboard.js:200
#: js/ui/keyboard.js:203
msgid "Region & Language Settings"
msgstr "Regiono & lingvo agordoj"
#: js/ui/lookingGlass.js:615
#: js/ui/lookingGlass.js:614
msgid "No extensions installed"
msgstr "Neniu kromprogramo instalita"
#. Translators: argument is an extension UUID.
#: js/ui/lookingGlass.js:669
#: js/ui/lookingGlass.js:668
#, javascript-format
msgid "%s has not emitted any errors."
msgstr "%s ne eligintaj ajnaj eraroj."
#: js/ui/lookingGlass.js:675
#: js/ui/lookingGlass.js:674
msgid "Hide Errors"
msgstr "Kaŝi erarojn"
#: js/ui/lookingGlass.js:679 js/ui/lookingGlass.js:739
#: js/ui/lookingGlass.js:678 js/ui/lookingGlass.js:738
msgid "Show Errors"
msgstr "Montri erarojn"
#: js/ui/lookingGlass.js:688
#: js/ui/lookingGlass.js:687
msgid "Enabled"
msgstr "Enŝaltita"
#. translators:
#. * The device has been disabled
#: js/ui/lookingGlass.js:691 subprojects/gvc/gvc-mixer-control.c:1864
#: js/ui/lookingGlass.js:690 subprojects/gvc/gvc-mixer-control.c:1866
msgid "Disabled"
msgstr "Elŝaltita"
#: js/ui/lookingGlass.js:693
#: js/ui/lookingGlass.js:692
msgid "Error"
msgstr "Eraro"
#: js/ui/lookingGlass.js:695
#: js/ui/lookingGlass.js:694
msgid "Out of date"
msgstr "Neaktuala"
#: js/ui/lookingGlass.js:697
#: js/ui/lookingGlass.js:696
msgid "Downloading"
msgstr "Elŝutante"
#: js/ui/lookingGlass.js:721
#: js/ui/lookingGlass.js:720
msgid "View Source"
msgstr "Montri fonton"
#: js/ui/lookingGlass.js:730
#: js/ui/lookingGlass.js:729
msgid "Web Page"
msgstr "Retpaĝo"
#: js/ui/messageTray.js:1480
#: js/ui/messageTray.js:1474
msgid "System Information"
msgstr "Sisteminformoj"
@@ -1399,14 +1404,13 @@ msgstr "Malfari"
msgid "Overview"
msgstr "Superrigardo"
# Imperativo
#. Translators: this is the text displayed
#. in the search entry when no search is
#. active; it should not exceed ~30
#. characters.
#: js/ui/overview.js:226
msgid "Type to search…"
msgstr "Tajpu por serĉi…"
msgstr "Tajpi por serĉi…"
#: js/ui/padOsd.js:92
msgid "New shortcut…"
@@ -1458,16 +1462,16 @@ msgstr "Ĉesi"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:471
#: js/ui/panel.js:466
msgid "Activities"
msgstr "Aktivecoj"
#: js/ui/panel.js:746
#: js/ui/panel.js:741
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Sistemo"
#: js/ui/panel.js:867
#: js/ui/panel.js:861
msgid "Top Bar"
msgstr "Supra breto"
@@ -1516,7 +1520,7 @@ msgid_plural "%d new notifications"
msgstr[0] "%d nova sciigo"
msgstr[1] "%d novaj sciigoj"
#: js/ui/screenShield.js:449 js/ui/status/system.js:271
#: js/ui/screenShield.js:449 js/ui/status/system.js:270
msgid "Lock"
msgstr "Ŝlosi"
@@ -1531,11 +1535,11 @@ msgstr "GNOME bezonas ŝlosi la ekranon"
#.
#. XXX: another option is to kick the user into the gdm login
#. screen, where we're not affected by grabs
#: js/ui/screenShield.js:826 js/ui/screenShield.js:1299
#: js/ui/screenShield.js:834 js/ui/screenShield.js:1307
msgid "Unable to lock"
msgstr "Ne eblas ŝlosi"
#: js/ui/screenShield.js:827 js/ui/screenShield.js:1300
#: js/ui/screenShield.js:835 js/ui/screenShield.js:1308
msgid "Lock was blocked by an application"
msgstr "Ŝloso estis blokita de aplikaĵo"
@@ -1697,7 +1701,7 @@ msgid "<unknown>"
msgstr "<nekonata>"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:416 js/ui/status/network.js:1292
#: js/ui/status/network.js:416 js/ui/status/network.js:1293
#, javascript-format
msgid "%s Off"
msgstr "%s malŝaltita"
@@ -1723,7 +1727,7 @@ msgid "%s Disconnecting"
msgstr "%s malkonektante"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:434 js/ui/status/network.js:1284
#: js/ui/status/network.js:434 js/ui/status/network.js:1285
#, javascript-format
msgid "%s Connecting"
msgstr "%s konektante"
@@ -1763,7 +1767,7 @@ msgid "Mobile Broadband Settings"
msgstr "Porteblaj larĝkapacitaj agordoj"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:553 js/ui/status/network.js:1289
#: js/ui/status/network.js:553 js/ui/status/network.js:1290
#, javascript-format
msgid "%s Hardware Disabled"
msgstr "%s aparataro malŝaltita"
@@ -1828,72 +1832,72 @@ msgid "Wi-Fi Settings"
msgstr "Vifio-agordoj"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1280
#: js/ui/status/network.js:1281
#, javascript-format
msgid "%s Hotspot Active"
msgstr "%s retkaptejo aktiva"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1295
#: js/ui/status/network.js:1296
#, javascript-format
msgid "%s Not Connected"
msgstr "%s ne konektita"
msgstr "%s nekonektita"
#: js/ui/status/network.js:1392
#: js/ui/status/network.js:1393
msgid "connecting…"
msgstr "konektante…"
#. Translators: this is for network connections that require some kind of key or password
#: js/ui/status/network.js:1395
#: js/ui/status/network.js:1396
msgid "authentication required"
msgstr "aŭtentigo necesas"
#: js/ui/status/network.js:1397
#: js/ui/status/network.js:1398
msgid "connection failed"
msgstr "konekto malsukcesis"
#: js/ui/status/network.js:1447
#: js/ui/status/network.js:1448
msgid "VPN Settings"
msgstr "VPR-agordoj"
#: js/ui/status/network.js:1464
#: js/ui/status/network.js:1465
msgid "VPN"
msgstr "VPR"
#: js/ui/status/network.js:1474
#: js/ui/status/network.js:1475
msgid "VPN Off"
msgstr "VPR malŝaltita"
#: js/ui/status/network.js:1535 js/ui/status/rfkill.js:82
#: js/ui/status/network.js:1536 js/ui/status/rfkill.js:82
msgid "Network Settings"
msgstr "Ret-agordoj"
#: js/ui/status/network.js:1564
#: js/ui/status/network.js:1565
#, javascript-format
msgid "%s Wired Connection"
msgid_plural "%s Wired Connections"
msgstr[0] "%s drata konekto"
msgstr[1] "%s drataj konektoj"
#: js/ui/status/network.js:1568
#: js/ui/status/network.js:1569
#, javascript-format
msgid "%s Wi-Fi Connection"
msgid_plural "%s Wi-Fi Connections"
msgstr[0] "%s vifia konekto"
msgstr[1] "%s vifiaj konektoj"
#: js/ui/status/network.js:1572
#: js/ui/status/network.js:1573
#, javascript-format
msgid "%s Modem Connection"
msgid_plural "%s Modem Connections"
msgstr[0] "%s modema konekto"
msgstr[1] "%s modemaj konektoj"
#: js/ui/status/network.js:1701
#: js/ui/status/network.js:1702
msgid "Connection failed"
msgstr "Konekto malsukcesis"
#: js/ui/status/network.js:1702
#: js/ui/status/network.js:1703
msgid "Activation of network connection failed"
msgstr "Aktivigo de reto-konekto malsukcesis"
@@ -1975,15 +1979,15 @@ msgstr "Adiaŭi"
msgid "Account Settings"
msgstr "Kontoagordoj"
#: js/ui/status/system.js:256
#: js/ui/status/system.js:255
msgid "Orientation Lock"
msgstr "Orientiĝa ŝloso"
#: js/ui/status/system.js:282
#: js/ui/status/system.js:281
msgid "Suspend"
msgstr "Dormeti"
#: js/ui/status/system.js:292
#: js/ui/status/system.js:291
msgid "Power Off"
msgstr "Malŝalti"
@@ -2171,6 +2175,11 @@ msgstr "Movi al dekstra ekrano"
msgid "Evolution Calendar"
msgstr "Evolucio-kalendaro"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: src/calendar-server/evolution-calendar.desktop.in:6
msgid "evolution"
msgstr "evolution"
#: src/main.c:408
msgid "Print version"
msgstr "Presi version"
@@ -2187,12 +2196,12 @@ msgstr "Uzi specifan reĝimon, ekz. “gdm” por la salut-ekrano"
msgid "List possible modes"
msgstr "Listigi eblajn reĝimojn"
#: src/shell-app.c:264
#: src/shell-app.c:260
msgctxt "program"
msgid "Unknown"
msgstr "Nekonata"
#: src/shell-app.c:515
#: src/shell-app.c:511
#, c-format
msgid "Failed to launch “%s”"
msgstr "Malsukcesis lanĉi “%s”"
@@ -2211,7 +2220,7 @@ msgstr "La uzanto malakceptis la aŭtentigan dialogon"
#. translators:
#. * The number of sound outputs on a particular device
#: subprojects/gvc/gvc-mixer-control.c:1871
#: subprojects/gvc/gvc-mixer-control.c:1873
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
@@ -2220,23 +2229,17 @@ msgstr[1] "%u eligoj"
#. translators:
#. * The number of sound inputs on a particular device
#: subprojects/gvc/gvc-mixer-control.c:1881
#: subprojects/gvc/gvc-mixer-control.c:1883
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u enigo"
msgstr[1] "%u enigoj"
#: subprojects/gvc/gvc-mixer-control.c:2736
#: subprojects/gvc/gvc-mixer-control.c:2738
msgid "System Sounds"
msgstr "Sistemsonoj"
#~ msgid "network-workgroup"
#~ msgstr "network-workgroup"
#~ msgid "evolution"
#~ msgstr "evolution"
#~ msgid "There was an error loading the preferences dialog for %s:"
#~ msgstr "Eraro okazis dum ŝarĝado de la agorda dialogo de %s:"

780
po/es.po

File diff suppressed because it is too large Load Diff

114
po/fr.po
View File

@@ -14,23 +14,23 @@
# Alain Lojewski <allomervan@gmail.com>, 2014-2018.
# Erwan Georget <egeorget@opmbx.org>, 2016.
# Claude Paroz <claude@2xlibre.net>, 2010-2011, 2016.
# Charles Monzat <charles.monzat@numericable.fr>, 2016-2018.
# Julien Humbert <julroy67@gmail.com>, 2019.
# Charles Monzat <charles.monzat@free.fr>, 2016-2019.
#
msgid ""
msgstr ""
"Project-Id-Version: gnome-shell master fr\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/gnome-shell/issues\n"
"POT-Creation-Date: 2019-03-13 20:47+0000\n"
"PO-Revision-Date: 2019-03-17 19:15+0100\n"
"Last-Translator: Charles Monzat <charles.monzat@free.fr>\n"
"Language-Team: GNOME French Team <gnomefr@traduc.org>\n"
"POT-Creation-Date: 2019-02-28 03:16+0000\n"
"PO-Revision-Date: 2019-02-28 08:29+0100\n"
"Last-Translator: Julien Humbert <julroy67@gmail.com>\n"
"Language-Team: français <gnomefr@traduc.org>\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"X-Generator: Gtranslator 3.32.0\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 2.2.1\n"
#: data/50-gnome-shell-system.xml:6
msgid "System"
@@ -482,7 +482,7 @@ msgstr "Absent de la liste ?"
#. Translators: this message is shown below the username entry field
#. to clue the user in on how to login to the local network realm
#: js/gdm/loginDialog.js:884
#: js/gdm/loginDialog.js:880
#, javascript-format
msgid "(e.g., user or %s)"
msgstr "(par ex. utilisateur ou %s)"
@@ -490,12 +490,12 @@ msgstr "(par ex. utilisateur ou %s)"
#. TTLS and PEAP are actually much more complicated, but this complication
#. is not visible here since we only care about phase2 authentication
#. (and don't even care of which one)
#: js/gdm/loginDialog.js:889 js/ui/components/networkAgent.js:243
#: js/gdm/loginDialog.js:885 js/ui/components/networkAgent.js:243
#: js/ui/components/networkAgent.js:263 js/ui/components/networkAgent.js:281
msgid "Username: "
msgstr "Nom dutilisateur : "
#: js/gdm/loginDialog.js:1227
#: js/gdm/loginDialog.js:1223
msgid "Login Window"
msgstr "Fenêtre de connexion"
@@ -1075,7 +1075,7 @@ msgstr "Mot de passe de la connexion mobile"
msgid "A password is required to connect to “%s”."
msgstr "Un mot de passe est requis pour se connecter à « %s »."
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1664
#: js/ui/components/networkAgent.js:674 js/ui/status/network.js:1665
msgid "Network Manager"
msgstr "Gestionnaire de réseau"
@@ -1335,26 +1335,26 @@ msgid "Download and install “%s” from extensions.gnome.org?"
msgstr "Télécharger et installer « %s » à partir de extensions.gnome.org ?"
#. Translators: %s is an application name like "Settings"
#: js/ui/inhibitShortcutsDialog.js:78
#: js/ui/inhibitShortcutsDialog.js:50
#, javascript-format
msgid "%s wants to inhibit shortcuts"
msgstr "%s veut neutraliser les raccourcis"
#: js/ui/inhibitShortcutsDialog.js:79
#: js/ui/inhibitShortcutsDialog.js:51
msgid "Application wants to inhibit shortcuts"
msgstr "Lapplication veut neutraliser les raccourcis"
#. Translators: %s is a keyboard shortcut like "Super+x"
#: js/ui/inhibitShortcutsDialog.js:88
#: js/ui/inhibitShortcutsDialog.js:60
#, javascript-format
msgid "You can restore shortcuts by pressing %s."
msgstr "Pour restaurer les raccourcis, appuyez sur %s."
#: js/ui/inhibitShortcutsDialog.js:93
#: js/ui/inhibitShortcutsDialog.js:65
msgid "Deny"
msgstr "Refuser"
#: js/ui/inhibitShortcutsDialog.js:100
#: js/ui/inhibitShortcutsDialog.js:71
msgid "Allow"
msgstr "Autoriser"
@@ -1407,13 +1407,13 @@ msgid "Leave On"
msgstr "Laisser activé"
#: js/ui/kbdA11yDialog.js:57 js/ui/status/bluetooth.js:133
#: js/ui/status/network.js:1263
#: js/ui/status/network.js:1264
msgid "Turn On"
msgstr "Activer"
#: js/ui/kbdA11yDialog.js:65 js/ui/status/bluetooth.js:133
#: js/ui/status/network.js:128 js/ui/status/network.js:310
#: js/ui/status/network.js:1263 js/ui/status/network.js:1375
#: js/ui/status/network.js:1264 js/ui/status/network.js:1376
#: js/ui/status/nightLight.js:39 js/ui/status/rfkill.js:79
#: js/ui/status/rfkill.js:106
msgid "Turn Off"
@@ -1423,59 +1423,59 @@ msgstr "Éteindre"
msgid "Leave Off"
msgstr "Laisser éteint"
#: js/ui/keyboard.js:200
#: js/ui/keyboard.js:203
msgid "Region & Language Settings"
msgstr "Paramètres de langue et région"
#: js/ui/lookingGlass.js:615
#: js/ui/lookingGlass.js:614
msgid "No extensions installed"
msgstr "Aucune extension installée"
#. Translators: argument is an extension UUID.
#: js/ui/lookingGlass.js:669
#: js/ui/lookingGlass.js:668
#, javascript-format
msgid "%s has not emitted any errors."
msgstr "%s na émis aucune erreur."
#: js/ui/lookingGlass.js:675
#: js/ui/lookingGlass.js:674
msgid "Hide Errors"
msgstr "Masquer les erreurs"
#: js/ui/lookingGlass.js:679 js/ui/lookingGlass.js:739
#: js/ui/lookingGlass.js:678 js/ui/lookingGlass.js:738
msgid "Show Errors"
msgstr "Afficher les erreurs"
#: js/ui/lookingGlass.js:688
#: js/ui/lookingGlass.js:687
msgid "Enabled"
msgstr "Activé"
#. translators:
#. * The device has been disabled
#: js/ui/lookingGlass.js:691 subprojects/gvc/gvc-mixer-control.c:1864
#: js/ui/lookingGlass.js:690 subprojects/gvc/gvc-mixer-control.c:1866
msgid "Disabled"
msgstr "Désactivé"
#: js/ui/lookingGlass.js:693
#: js/ui/lookingGlass.js:692
msgid "Error"
msgstr "Erreur"
#: js/ui/lookingGlass.js:695
#: js/ui/lookingGlass.js:694
msgid "Out of date"
msgstr "Périmé"
#: js/ui/lookingGlass.js:697
#: js/ui/lookingGlass.js:696
msgid "Downloading"
msgstr "Téléchargement"
#: js/ui/lookingGlass.js:721
#: js/ui/lookingGlass.js:720
msgid "View Source"
msgstr "Afficher la source"
#: js/ui/lookingGlass.js:730
#: js/ui/lookingGlass.js:729
msgid "Web Page"
msgstr "Page Web"
#: js/ui/messageTray.js:1480
#: js/ui/messageTray.js:1474
msgid "System Information"
msgstr "Informations du système"
@@ -1559,16 +1559,16 @@ msgstr "Quitter"
#. Translators: If there is no suitable word for "Activities"
#. in your language, you can use the word for "Overview".
#: js/ui/panel.js:471
#: js/ui/panel.js:466
msgid "Activities"
msgstr "Activités"
#: js/ui/panel.js:746
#: js/ui/panel.js:741
msgctxt "System menu in the top bar"
msgid "System"
msgstr "Système"
#: js/ui/panel.js:866
#: js/ui/panel.js:861
msgid "Top Bar"
msgstr "Barre supérieure"
@@ -1800,7 +1800,7 @@ msgid "<unknown>"
msgstr "<inconnu>"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:416 js/ui/status/network.js:1292
#: js/ui/status/network.js:416 js/ui/status/network.js:1293
#, javascript-format
msgid "%s Off"
msgstr "%s éteint"
@@ -1826,7 +1826,7 @@ msgid "%s Disconnecting"
msgstr "Déconnexion de %s en cours"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:434 js/ui/status/network.js:1284
#: js/ui/status/network.js:434 js/ui/status/network.js:1285
#, javascript-format
msgid "%s Connecting"
msgstr "Connexion de %s en cours"
@@ -1866,7 +1866,7 @@ msgid "Mobile Broadband Settings"
msgstr "Paramètres connexion mobile"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:553 js/ui/status/network.js:1289
#: js/ui/status/network.js:553 js/ui/status/network.js:1290
#, javascript-format
msgid "%s Hardware Disabled"
msgstr "Équipement %s désactivé"
@@ -1931,72 +1931,72 @@ msgid "Wi-Fi Settings"
msgstr "Paramètres Wi-Fi"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1280
#: js/ui/status/network.js:1281
#, javascript-format
msgid "%s Hotspot Active"
msgstr "Point daccès %s actif"
#. Translators: %s is a network identifier
#: js/ui/status/network.js:1295
#: js/ui/status/network.js:1296
#, javascript-format
msgid "%s Not Connected"
msgstr "%s non connecté"
#: js/ui/status/network.js:1392
#: js/ui/status/network.js:1393
msgid "connecting…"
msgstr "connexion…"
#. Translators: this is for network connections that require some kind of key or password
#: js/ui/status/network.js:1395
#: js/ui/status/network.js:1396
msgid "authentication required"
msgstr "authentification nécessaire"
#: js/ui/status/network.js:1397
#: js/ui/status/network.js:1398
msgid "connection failed"
msgstr "échec de connexion"
#: js/ui/status/network.js:1447
#: js/ui/status/network.js:1448
msgid "VPN Settings"
msgstr "Paramètres VPN"
#: js/ui/status/network.js:1464
#: js/ui/status/network.js:1465
msgid "VPN"
msgstr "VPN"
#: js/ui/status/network.js:1474
#: js/ui/status/network.js:1475
msgid "VPN Off"
msgstr "VPN désactivé"
#: js/ui/status/network.js:1535 js/ui/status/rfkill.js:82
#: js/ui/status/network.js:1536 js/ui/status/rfkill.js:82
msgid "Network Settings"
msgstr "Paramètres du réseau"
#: js/ui/status/network.js:1564
#: js/ui/status/network.js:1565
#, javascript-format
msgid "%s Wired Connection"
msgid_plural "%s Wired Connections"
msgstr[0] "%s connexion filaire."
msgstr[1] "%s connexions filaires."
#: js/ui/status/network.js:1568
#: js/ui/status/network.js:1569
#, javascript-format
msgid "%s Wi-Fi Connection"
msgid_plural "%s Wi-Fi Connections"
msgstr[0] "%s connexion Wi-Fi."
msgstr[1] "%s connexions Wi-Fi."
#: js/ui/status/network.js:1572
#: js/ui/status/network.js:1573
#, javascript-format
msgid "%s Modem Connection"
msgid_plural "%s Modem Connections"
msgstr[0] "%s connexion à un modem."
msgstr[1] "%s connexions à des modems."
#: js/ui/status/network.js:1701
#: js/ui/status/network.js:1702
msgid "Connection failed"
msgstr "Échec de connexion"
#: js/ui/status/network.js:1702
#: js/ui/status/network.js:1703
msgid "Activation of network connection failed"
msgstr "Lactivation de la connexion réseau a échoué"
@@ -2049,7 +2049,7 @@ msgstr "%d%02d avant chargement complet (%d %%)"
#: js/ui/status/power.js:117 js/ui/status/power.js:119
#, javascript-format
msgid "%d%%"
msgstr "%d %%"
msgstr "%d%%"
#: js/ui/status/remoteAccess.js:42
msgid "Screen is Being Shared"
@@ -2298,12 +2298,12 @@ msgstr ""
msgid "List possible modes"
msgstr "Lister les modes possibles"
#: src/shell-app.c:264
#: src/shell-app.c:260
msgctxt "program"
msgid "Unknown"
msgstr "Inconnu"
#: src/shell-app.c:515
#: src/shell-app.c:511
#, c-format
msgid "Failed to launch “%s”"
msgstr "Impossible de lancer « %s »"
@@ -2322,7 +2322,7 @@ msgstr "La fenêtre dauthentification a été écartée par lutilisateur"
#. translators:
#. * The number of sound outputs on a particular device
#: subprojects/gvc/gvc-mixer-control.c:1871
#: subprojects/gvc/gvc-mixer-control.c:1873
#, c-format
msgid "%u Output"
msgid_plural "%u Outputs"
@@ -2331,14 +2331,14 @@ msgstr[1] "%u sorties"
#. translators:
#. * The number of sound inputs on a particular device
#: subprojects/gvc/gvc-mixer-control.c:1881
#: subprojects/gvc/gvc-mixer-control.c:1883
#, c-format
msgid "%u Input"
msgid_plural "%u Inputs"
msgstr[0] "%u entrée"
msgstr[1] "%u entrées"
#: subprojects/gvc/gvc-mixer-control.c:2736
#: subprojects/gvc/gvc-mixer-control.c:2738
msgid "System Sounds"
msgstr "Sons système"

1520
po/hr.po

File diff suppressed because it is too large Load Diff

1029
po/sk.po

File diff suppressed because it is too large Load Diff

View File

@@ -308,7 +308,7 @@ msgstr "Воридшавии шабакавӣ"
#. Translators: Do NOT translate or transliterate this text (this is an icon file name)!
#: data/org.gnome.Shell.PortalHelper.desktop.in.in:9
msgid "network-workgroup"
msgstr "network-workgroup"
msgstr "шабака-гурӯҳи корӣ"
#: js/extensionPrefs/main.js:116
msgid "Somethings gone wrong"

File diff suppressed because it is too large Load Diff

View File

@@ -1183,26 +1183,13 @@ _shell_app_handle_startup_sequence (ShellApp *app,
gboolean
shell_app_request_quit (ShellApp *app)
{
GActionGroup *group = NULL;
GSList *iter;
if (shell_app_get_state (app) != SHELL_APP_STATE_RUNNING)
return FALSE;
/* First, check whether the app exports an explicit "quit" action
* that we can activate on the bus
*/
group = G_ACTION_GROUP (app->running_state->muxer);
/* TODO - check for an XSMP connection; we could probably use that */
if (g_action_group_has_action (group, "app.quit") &&
g_action_group_get_action_parameter_type (group, "app.quit") == NULL)
{
g_action_group_activate_action (group, "app.quit", NULL);
return TRUE;
}
/* Otherwise, fall back to closing all the app's windows */
for (iter = app->running_state->windows; iter; iter = iter->next)
{
MetaWindow *win = iter->data;

View File

@@ -17,13 +17,15 @@
#include <meta/meta-cursor-tracker.h>
#include <meta/display.h>
#include <meta/compositor-mutter.h>
#include <st/st.h>
#include "shell-global.h"
#include "shell-recorder-src.h"
#include "shell-recorder.h"
#include "shell-util.h"
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
typedef enum {
RECORDER_STATE_CLOSED,
RECORDER_STATE_RECORDING
@@ -56,6 +58,7 @@ struct _ShellRecorder {
int pointer_x;
int pointer_y;
GSettings *a11y_settings;
gboolean draw_cursor;
MetaCursorTracker *cursor_tracker;
cairo_surface_t *cursor_image;
@@ -210,6 +213,8 @@ shell_recorder_init (ShellRecorder *recorder)
recorder->memory_target = get_memory_target();
recorder->a11y_settings = g_settings_new (A11Y_APPS_SCHEMA);
recorder->state = RECORDER_STATE_CLOSED;
recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
recorder->draw_cursor = TRUE;
@@ -234,6 +239,8 @@ shell_recorder_finalize (GObject *object)
recorder_remove_redraw_timeout (recorder);
g_clear_object (&recorder->a11y_settings);
G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
}
@@ -458,16 +465,9 @@ recorder_record_frame (ShellRecorder *recorder,
GST_BUFFER_PTS(buffer) = now;
if (recorder->draw_cursor)
{
StSettings *settings = st_settings_get ();
gboolean magnifier_active = FALSE;
g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
if (magnifier_active)
recorder_draw_cursor (recorder, buffer);
}
if (recorder->draw_cursor &&
!g_settings_get_boolean (recorder->a11y_settings, MAGNIFIER_ACTIVE_KEY))
recorder_draw_cursor (recorder, buffer);
shell_recorder_src_add_buffer (SHELL_RECORDER_SRC (recorder->current_pipeline->src), buffer);
gst_buffer_unref (buffer);

View File

@@ -7,12 +7,14 @@
#include <meta/meta-plugin.h>
#include <meta/meta-shaped-texture.h>
#include <meta/meta-cursor-tracker.h>
#include <st/st.h>
#include "shell-global.h"
#include "shell-screenshot.h"
#include "shell-util.h"
#define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
#define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate;
struct _ShellScreenshot
@@ -200,9 +202,6 @@ write_screenshot_thread (GTask *result,
cairo_image_surface_get_height (priv->image));
creation_time = g_date_time_format (priv->datetime, "%c");
if (!creation_time)
creation_time = g_date_time_format (priv->datetime, "%FT%T%z");
if (gdk_pixbuf_save_to_stream (pixbuf, stream, "png", NULL, NULL,
"tEXt::Software", "gnome-screenshot",
"tEXt::Creation Time", creation_time,
@@ -269,12 +268,9 @@ should_draw_cursor_image (ShellScreenshotMode mode)
{
if (mode == SHELL_SCREENSHOT_WINDOW || !meta_is_wayland_compositor ())
{
StSettings *settings = st_settings_get ();
gboolean magnifier_active = FALSE;
g_autoptr (GSettings) settings = g_settings_new (A11Y_APPS_SCHEMA);
g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
if (!magnifier_active)
if (!g_settings_get_boolean (settings, MAGNIFIER_ACTIVE_KEY))
return TRUE;
}

View File

@@ -30,7 +30,6 @@
#define KEY_DRAG_THRESHOLD "drag-threshold"
#define KEY_GTK_THEME "gtk-theme"
#define KEY_GTK_ICON_THEME "icon-theme"
#define KEY_MAGNIFIER_ACTIVE "screen-magnifier-enabled"
enum {
PROP_0,
@@ -39,7 +38,6 @@ enum {
PROP_DRAG_THRESHOLD,
PROP_GTK_THEME,
PROP_GTK_ICON_THEME,
PROP_MAGNIFIER_ACTIVE,
N_PROPS
};
@@ -50,13 +48,11 @@ struct _StSettings
GObject parent_object;
GSettings *interface_settings;
GSettings *mouse_settings;
GSettings *a11y_settings;
gchar *gtk_theme;
gchar *gtk_icon_theme;
gboolean enable_animations;
gboolean primary_paste;
gboolean magnifier_active;
gint drag_threshold;
};
@@ -109,9 +105,6 @@ st_settings_get_property (GObject *object,
case PROP_GTK_ICON_THEME:
g_value_set_string (value, settings->gtk_icon_theme);
break;
case PROP_MAGNIFIER_ACTIVE:
g_value_set_boolean (value, settings->magnifier_active);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -151,11 +144,6 @@ st_settings_class_init (StSettingsClass *klass)
"GTK+ Icon Theme",
"",
G_PARAM_READABLE);
props[PROP_MAGNIFIER_ACTIVE] = g_param_spec_boolean("magnifier-active",
"Magnifier is active",
"Weather the a11y magnifier is active",
FALSE,
G_PARAM_READABLE);
g_object_class_install_properties (object_class, N_PROPS, props);
}
@@ -202,18 +190,6 @@ on_mouse_settings_changed (GSettings *g_settings,
}
}
static void
on_a11y_settings_changed (GSettings *g_settings,
const gchar *key,
StSettings *settings)
{
if (g_str_equal (key, KEY_MAGNIFIER_ACTIVE))
{
settings->magnifier_active = g_settings_get_boolean (g_settings, key);
g_object_notify_by_pspec (G_OBJECT (settings), props[PROP_MAGNIFIER_ACTIVE]);
}
}
static void
st_settings_init (StSettings *settings)
{
@@ -225,10 +201,6 @@ st_settings_init (StSettings *settings)
g_signal_connect (settings->interface_settings, "changed",
G_CALLBACK (on_mouse_settings_changed), settings);
settings->a11y_settings = g_settings_new ("org.gnome.desktop.a11y.applications");
g_signal_connect (settings->a11y_settings, "changed",
G_CALLBACK (on_a11y_settings_changed), settings);
settings->enable_animations = g_settings_get_boolean (settings->interface_settings,
KEY_ENABLE_ANIMATIONS);
settings->primary_paste = g_settings_get_boolean (settings->interface_settings,
@@ -239,8 +211,6 @@ st_settings_init (StSettings *settings)
KEY_GTK_ICON_THEME);
settings->drag_threshold = g_settings_get_int (settings->mouse_settings,
KEY_DRAG_THRESHOLD);
settings->magnifier_active = g_settings_get_boolean (settings->a11y_settings,
KEY_MAGNIFIER_ACTIVE);
}
/**

View File

@@ -24,8 +24,6 @@
#ifndef __ST_SETTINGS_H__
#define __ST_SETTINGS_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define ST_TYPE_SETTINGS (st_settings_get_type ())
@@ -33,6 +31,4 @@ G_DECLARE_FINAL_TYPE (StSettings, st_settings, ST, SETTINGS, GObject)
StSettings * st_settings_get (void);
G_END_DECLS
#endif /* __ST_SETTINGS_H__ */